要完成这个任务,我们可以使用Python中的PyTorch库来建立一个简单的神经网络,网络结构只有一个输入层和一个输出层,输入层有5个节点,输出层有1个节点。训练过程中,我们将记录权重的变化,并在训练100轮后绘制出权重变化的图像。以下是步骤和代码的详细解释:
- 构建网络:网络由一个全连接层组成,没有激活函数,因为我们只关注权重的变化。
- 数据准备:随机生成一些输入数据和目标数据用于训练。
- 训练网络:使用均方误差损失和随机梯度下降优化器。
- 记录权重:在每轮训练后记录权重。
- 绘制权重变化图:训练完成后,使用matplotlib绘制权重的变化。
这张图展示了一个简单神经网络中5个权重在100轮训练过程中的变化。每条线代表一个权重值如何随着训练轮次的增加而变化。你可以看到,权重随着训练过程呈现不同程度的变化,这反映了模型在尝试适应数据的过程中权重的更新情况。
在这段代码中,weights_history[:, 0, i]
用于从存储的权重历史记录中提取特定的权重值,以便绘制。下面是这个表达式的详细分析:
-
weights_history
是一个记录了每一训练轮次后模型权重的列表,该列表在每次迭代时被转换为一个PyTorch张量。这个张量的形状是[100, 1, 5]
:- 第一个维度(100)代表训练轮次的数量。
- 第二个维度(1)代表输出层的节点数,这里是1,因为我们的模型是从5个输入到1个输出的线性层。
- 第三个维度(5)代表输入层的节点数,也就是权重的数量,因为我们的线性层有5个输入。
-
weights_history[:, 0, i]
的分解::
选择weights_history
张量中所有的100个训练轮次。0
选择输出层中第一个(也是唯一一个)节点的权重。i
这是一个从0到4变化的索引,用于选择5个输入中的一个特定权重。
因此,当你使用 weights_history[:, 0, i]
,它实际上在每一训练轮次中选取一个特定的输入权重,并跟踪这个权重是如何随着时间变化的。在上面的代码中,这种方式被用来绘制每个输入对应权重随训练轮次变化的图形,展示了每个权重如何随着模型训练进行而更新。
import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np# 定义一个简单的线性模型
class SimpleLinearModel(nn.Module):def __init__(self):super(SimpleLinearModel, self).__init__()self.linear = nn.Linear(5, 1) # 5个输入节点,1个输出节点def forward(self, x):return self.linear(x)# 生成一些随机数据
inputs = torch.randn(100, 5) # 100个样本,每个样本5个特征
targets = torch.randn(100, 1) # 100个目标值 # 初始化模型
model = SimpleLinearModel()# 损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 用于记录权重的列表
weights_history = []# 训练模型
for epoch in range(100): # 训练100轮# 前向传播outputs = model(inputs)loss = criterion(outputs, targets)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()# 记录权重weights_history.append(model.linear.weight.data.numpy().copy())# 转换为numpy数组
weights_history = np.array(weights_history)# 创建subplot
fig, axs = plt.subplots(5, 1, figsize=(10, 15))
for i in range(5): # 对于5个输入特征的每一个权重绘图axs[i].plot(weights_history[:, 0, i], label=f'Weight {i+1}')axs[i].set_title(f'Weight {i+1} Changes Over 100 Epochs')axs[i].set_xlabel('Epoch')axs[i].set_ylabel('Weight Value')axs[i].legend()plt.tight_layout()
plt.savefig("test")
上述代码实现了一个简单的神经网络训练,并绘制了每个输入特征的权重变化。以下是代码的详细步骤分析:
-
导入库:
- 导入了
torch
和torch.nn
用于神经网络的构建和训练。 - 导入
matplotlib.pyplot
用于绘制图像。
- 导入了
-
定义模型:
- 定义了一个简单的线性模型
SimpleLinearModel
,包含一个全连接层linear
,输入5个特征输出1个值。
- 定义了一个简单的线性模型
-
初始化模型、损失函数和优化器:
- 实例化了模型
model
。 - 使用均方误差损失函数
criterion
,适合回归问题。 - 使用随机梯度下降优化器
optimizer
,学习率设置为0.01。
- 实例化了模型
-
准备数据:
- 生成了随机输入数据
inputs
和目标数据targets
,分别有100个样本,输入有5个特征,输出有1个目标值。
- 生成了随机输入数据
-
训练过程:
- 创建一个空列表
weights_history
用于记录每轮训练后的权重。 - 进行100轮训练,在每轮中:
- 计算模型的输出
outputs
。 - 计算损失
loss
。 - 清空梯度,进行反向传播,更新权重。
- 记录当前的权重,保存到
weights_history
中。
- 计算模型的输出
- 创建一个空列表
-
数据转换和绘图:
- 将
weights_history
转换为numpy
数组,以便于处理。 - 使用
plt.subplots
创建5个子图,每个子图显示一个输入特征的权重变化。 - 遍历每个输入特征的权重数据,绘制在相应的子图上:
axs[i].plot(...)
绘制第i
个输入特征的权重变化曲线。- 设置子图的标题、坐标轴标签和图例。
- 使用
plt.tight_layout()
使子图布局紧凑整齐。 - 显示绘制好的图像。
- 将
每个子图显示了对应输入特征的权重在100轮训练中的变化情况。这种细分展示方法有助于观察每个权重如何随着训练过程逐步调整和收敛。