实验要求:
学会构建线性回归模型以及模型训练,并使用matplotlib进行可视化
实验步骤:
1. 下载pytorch与matplotlib
2. 将以下代码粘贴并运行
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# 随机生成线性分布数据
def generate_data(nums_data, k=2, if_plot=False):
x = torch.linspace(0, 1, nums_data)
x = torch.unsqueeze(x, dim=1) # 将x变为二维向量
y = k * x + torch.rand(x.size()) # 线性数据加噪声
if if_plot:
plt.scatter(x.numpy(), y.numpy(), c=x.numpy())
plt.show()
data = {"x": x, "y": y}
return data
# 线性回归模型类
class LinearRegressionModel(nn.Module):
def __init__(self):
super(LinearRegressionModel, self).__init__()
self.linear = nn.Linear(1, 1) # 一维输入一维输出
def forward(self, x):
return self.linear(x)
# 训练函数
def train_model(model, data, epochs=50, learning_rate=0.01):
criterion = nn.MSELoss() # 损失函数:均方误差
optimizer = optim.SGD(model.parameters(), lr=learning_rate) # 优化器:随机梯度下降
x_train = data["x"]
y_train = data["y"]
# 可视化模型函数
def plot_model(step):
with torch.no_grad():
predicted = model(x_train).detach().numpy()
plt.scatter(x_train.numpy(), y_train.numpy(), c='blue', label='True data')
plt.plot(x_train.numpy(), predicted, 'r-', label='Fitted line')
plt.title(f'Model at step {step}')
plt.legend()
plt.show()
# 初始化模型可视化
plot_model(0)
# 开始训练
for epoch in range(epochs):
for step in range(len(x_train)):
inputs = x_train[step].unsqueeze(0) # 取单个数据
targets = y_train[step].unsqueeze(0)
outputs = model(inputs) # 模型预测
loss = criterion(outputs, targets) # 计算损失
optimizer.zero_grad() # 梯度清零!!!!!
loss.backward() # 反向传播
optimizer.step() # 优化一步
if step % 10 == 0 and epoch == 0: # 每10步可视化一次初期模型
plot_model(f"epoch_0_step_{step}")
if epoch == 0 or epoch == epochs // 2: # 在训练一半时可视化
plot_model(f"epoch_{epoch}")
# 最终模型可视化
plot_model("final")
# 示例生成数据并可视化
data = generate_data(100, if_plot=True)
model = LinearRegressionModel()
train_model(model, data)
3. 得到结果
实验总结:
该实验让我知道了用pytorch进行一个简单神经网络训练(可能算吧,它也没激活函数)的基本步骤:
1. 处理数据:让数据变成:data = {"x": x, "y": y} 的形式
2. 定义模型:①继承nn.Module类 ②选择模型类别与输入输出形式self.linear = nn.Linear(1, 1) ③定义前向传播计算函数 return self.linear(x)
3. 写训练函数:
1 设定损失函数:criterion = nn.MSELoss() # 损失函数:均方误差
2 设定优化器:optimizer = optim.SGD(model.parameters(), lr=learning_rate)
# 优化器:随机梯度下降
3 描述训练过程:
① 根据优化器构建循环,并确定提取的数据,比如随机梯度下降就是二重循环
② 模型预测 outputs = model(inputs) # 模型预测
③ 计算损失 loss = criterion(outputs, targets) # 计算损失
④ 梯度清零 optimizer.zero_grad() # 梯度清零!!!!!
⑤ 反向传播 loss.backward() # 反向传播
⑥ 更新模型超参数 optimizer.step() # 优化一步
疑惑与解答:
?:
-
loss.backward() # 反向传播 这一步是怎么将自动计算出的梯度传到模型中的呢?
!:
-
前向传播时,从
inputs
到loss
的所有操作都被记录下来,形成了一个计算图。 -
调用
loss.backward()
时,PyTorch 会从loss
开始,沿着计算图反向传播,计算出所有需要计算梯度的张量的梯度。 -
正向传播forward是model的一个方法,所以正向传播形成的计算图与model相连,反向传播通过计算图找到模型并将计算出的梯度存储在每个参数的
.grad
属性中