用 Pytorch 实现线性回归

📅 2026/8/27 8:36:22
用 Pytorch 实现线性回归
目录第一步 准备数据第二步 设计模型第三步 构造损失函数和优化器1、损失函数2、优化器第四步 训练过程第五步 测试模型代码作业Adagrad优化器1、介绍2、代码y_hat w * x b第一步 准备数据采用minibatch风格的梯度下降的算法利用pytorch的广播机制因此X,Y必须是矩阵3×1的向量w矩阵的维度要根据 X 和 Y 的维度来确定第二步 设计模型重点是构造计算图想要构造w和b的维度形状需要知道输入x和输出y_hat的维度因为X,Y都以张量的形式计算所以计算出的loss也是张量的形式因此需要对 loss_i 求和再根据需要决定是不是要求均值所有模型类一定要继承于Module必须要实现__init__构造函数和forward前馈网络两个函数继承于Module类会自动实现 backward() 的过程class torch.nn.Linear(in_features, out_features, biasTure)超参数不可训练但可配置1in_features --每一个输入的特征样本x的维度2out_features --每一个输出的特征样本y的维度3bias --指定是否需要偏置值b可训练的参数1weight --学习权重矩阵形状是out_features×in_features2bias --偏置向量形状是out_featuresself.linear torch.nn.Linear(11) 是一个对象其中包含权重w和偏置值b两个张量因此可以使用linear来自动实现这样一个计算linear也继承自Module因此也可以自动进行反向传播注意in_features 和out_features是指每一个特征样本x或y的维度例如在一元线性回归中输入为x输出为y所以值为in_features 1out_features1,此时输入X的形状为[batchsizein_features][n1]Y的形状为[n1]W的形状为1×1b的形状为1×1在多元线性回归中输入为x1,x2,x3输出为y所以值为in_features 3out_features1此时输入X的形状为[batchsizein_features][n3]Y的形状为[n1]W的形状为1×3b的形状为1×1。self.linear(x)是一个可以调用的对象其作用是完成线性函数的计算得到y_predmodel LinearModel()中 model也是一个可以调用的对象第三步 构造损失函数和优化器1、损失函数类classtorch.nn.MSELoss(size_averageTrue, reduceTrue)MSELoss也是继承于nn.Modulesize_average -- 是不是要对所有样本的Loss求均值一般设置为Falsereduce -- 最后是不是要把得到的Loss向量降维也就是求和一般不管对象criterion是这个类的一个可调用对象核心方法就是__call__需要的参数是y_hat和y用于求Loss2、优化器类classtorch.optim.SGD(params, lrobject object, momentum0, dampening0, weight_decay0, nesterovFalse)params就是指权重Model里面没有定义权重只有一个Linear成员这个成员包含两个权重model.parameters()会检查model中的所有成员取得Linear的权重是通过调用linear.parameters如果成员里面有相应的权重它就把这些都加入到要训练的参数集合里面lr是学习率对象optimizer就是一个优化器对象它知道自己要优化哪些参数也知道学习率optimizer对象的核心方法方法作用是否需要参数optimizer.zero_grad()清零所有参数的梯度❌ 不需要optimizer.step()用梯度更新所有参数❌ 不需要optimizer.param_groups查看参数组调试用❌ 不需要注意虽然这里的优化器是SGD但这段代码算法实际是BGD。这是因为 PyTorch偷懒。torch.optim.SGD这个类名它具体执行的是 SGD、BGD 还是 Mini-batch SGD完全不取决于优化器本身而是取决于传给它的 数据批次大小Batch Size如果把所有数据一次性喂进去如你的代码 →就是 BGD。如果把1个样本喂进去 →就是纯 SGD。如果把32个样本喂进去Mini-batch →就是 Mini-batch SGD工业界最常用大家平时口头说的“SGD”通常指这个。第四步 训练过程print(loss)时会自动调用loss.__str__()不会产生计算图.step()会根据每个参数的梯度和更新每次backward求梯度之前要把之前的梯度清零第五步 测试模型前面的步骤已经将模型训练好了重新创建一个tensor张量x_test输入给模型得到输出y_test model(x_test)—— 执行预测前向传播model(x_test)实际上会调用model.__call__()方法而__call__()方法内部会自动调用forward()所以model的参数应该与forward()传入的参数一样也就是x代码import torch import matplotlib.pyplot as plt x_data torch.Tensor([[1.0], [2.0], [3.0]]) y_data torch.Tensor([[2.0], [4.0], [6.0]]) class LinearModel(torch.nn.Module): def __init__(self): super(LinearModel, self).__init__() self.linear torch.nn.Linear(1, 1) def forward(self, x): y_pred self.linear(x) return y_pred model LinearModel() criterion torch.nn.MSELoss(size_averageFalse) optimizer torch.optim.SGD(model.parameters(), lr0.01) for epoch in range(100): y_pred model(x_data) loss criterion(y_pred, y_data) print(epoch, loss.item()) optimizer.zero_grad() loss.backward() optimizer.step() print(w , model.linear.weight.item()) print(b ,model.linear.bias.item()) x_test torch.Tensor([[4.0]]) y_test model(x_test) plt.plot(range(1, 101, 1), loss_list) plt.xlabel(epoch) plt.ylabel(Loss) plt.show() print(y_pred , y_test.data)运行结果w 1.7945618629455566 b 0.4670093357563019y_pred tensor([[7.6134]])作业Adagrad优化器1、介绍传统 SGD优化器所有参数用同一个学习率但是有些参数更新频繁有些很少用同一个学习率不合理。Adagrad中每个参数有自己的学习率。更新频繁的参数学习率自动变小更新稀少的参数学习率自动变大数学公式为# 累计梯度平方和历史信息G G (梯度)²# 参数更新公式w w - (lr / (√G ε)) * 梯度torch.optim.Adagrad(params, # 要优化的参数必需lr0.01, # 学习率默认 0.01lr_decay0, # 学习率衰减默认 0weight_decay0, # L2 正则化默认 0eps1e-10, # 防止除零默认 1e-10initial_accumulator_value0 # G 的初始值默认 0)2、代码只需将optimizer torch.optim.SGD(model.parameters(), lr0.01)改为optimizer torch.optim.Adagrad( model.parameters(), lr0.01, # 学习率 weight_decay0.001 # 可以加 L2 正则化 )运行结果w 0.6798529624938965 b 1.0155056715011597 y_pred tensor([[3.7349]])