2.2 初识网络代码——线性表示代码

发布时间:2026/9/17 21:04:05
2.2 初识网络代码——线性表示代码
前言线性回归是机器学习中最基础且重要的模型之一它通过寻找自变量与因变量之间的线性关系来进行预测。在深度学习时代虽然神经网络模型日益复杂但理解线性回归的训练原理仍然是掌握机器学习核心思想的基石。本文将从零开始完整演示线性回归模型的训练流程涵盖数据生成、模型构建、损失计算、参数优化到结果可视化的全过程。本文目标掌握线性回归模型的基本原理和训练流程学会使用PyTorch实现线性回归的完整训练过程理解梯度下降算法的实际应用掌握模型训练中的关键调试技巧和常见问题解决方法通过本文的学习读者将能够独立实现一个完整的线性回归模型训练并为后续学习更复杂的神经网络模型打下坚实基础。模型大概的训练流程数据处理–构造函数–计算loss与梯度–更新参数–可视化(绘图)下面是这次训练要用到的包importtorchimportmatplotlib.pyplotaspltimportrandom一、数据处理数据是机器学习的基础良好的数据处理流程直接影响模型性能。本章节将详细介绍数据的生成与提供方法。1.1 生成数据在真实场景中我们通常从数据库、文件或API获取数据。但在教学示例中我们首先生成模拟数据来演示完整流程。importtorchimportnumpyasnpdefcreate_data(w,b,data_num):xtorch.normal(0,1,(data_num,len(w)))#以0为均值1为标准差正态生成样本xytorch.matmul(x,w)b#将x(500x4)与w(4x1)相乘生成标签y(500x1)matmul表示矩阵相乘noisetorch.normal(0,0.01,y.shape)#加入噪声ynoise#yynoise会创建一个新变量returnx,y注意事项噪声的添加使数据更接近真实场景避免模型过拟合到完美线性关系特征标准化本文未展示在实际应用中通常能加速模型收敛数据分割训练集/验证集/测试集是避免过拟合的关键步骤可以画图来看看数据长什么样子num500true_wtorch.tensor([8.1,2,2,4])#给出真实wtrue_btorch.tensor(1.1)#给出真实bX,Ycreate_data(true_w,true_b,num)#调用函数来生成数据plt.scatter(X[:,3],Y)#绘制数据x是500x4矩阵y是500x1矩阵所以x要切片plt.show()#展示结果如下1.2 提供数据数据加载器深度学习通常无法一次性加载所有数据到内存特别是处理大规模数据集时。分批加载数据mini-batch有以下优势内存效率减少单次内存占用训练稳定性小批量梯度下降比全批量更稳定收敛速度适当的小批量大小能加速收敛我们做一个数据提供器每一次调用这个函数就提供一批数据defdata_provider(X,Y,batch_size):defdata_provider(data,label,batch_size):lenthlen(data[:,0])#测量数据条数indiceslist(range(lenth))#生成索引,方便shuffle#我不能按顺序取做不到普适性和随机性random.shuffle(indices)#随机打乱提高训练效果foreachinrange(0,lenth,batch_size):#循环每次取batch_size个数据get_indicesindices[each:min(eachbatch_size,lenth)]#取出本批次数据的索引get_datadata[get_indices]#根据索引取出自变量get_labellabel[get_indices]#根据索引取出对应标签yieldget_data,get_label batch_size16forbatch_x,batch_yindata_provider(X,Y,batch_size):#调试的重要print(batch_x,batch_y)#打印数据breakpycharm非常重要的功能之一就在于它的调试在调试过程中我们更容易了解参数的变化批次大小选择建议小批量32-256大多数场景的默认选择平衡了内存使用和梯度稳定性大批量1024需要更多内存但可以利用GPU并行计算优势全批量适用于小数据集梯度方向最准确但可能陷入局部最优数据增强技巧对于图像等数据随机裁剪、旋转、翻转颜色抖动、亮度调整Mixup、Cutmix等高级增强技术二、模型构建线性回归实现线性回归是机器学习中最基础的模型其数学形式为yXwby Xw byXwb其中XXX是输入特征矩阵www是权重向量bbb是偏置项yyy是预测值前向传播函数如下deffun(x,w,b):#需要x,w,b来组成预测值pred_ytorch.matmul(x,w)breturnpred_y关键理解点维度匹配确保输入特征维度与权重维度一致广播机制PyTorch自动处理不同形状张量间的运算梯度计算requires_gradTrue的参数会自动计算梯度模块化思想将模型封装为函数或类便于复用和调试三、loss与梯度回传取均绝对值误差defmaeloss(pred_y,y):#需要预测值和真实值returntorch.sum(abs(pred_y-y))/len(y)随机梯度下降defsgd(paras,lr):#需要参数还有学习率withtorch.no_grad():#不开启梯度计算因为这部分不需要forparainparas:#遍历所有参数para-para.grad*lr#更新参数不能写成parapara-para.grad*lr,会创建新变量para.grad.zero_()#清空梯度防止阻碍下一次梯度回传梯度下降流程随机选取一个w计算loss对w偏导更新w的值深度学习的基本原理也是这样四、训练训练准备lr0.01#设置学习率w_0torch.normal(0,0.01,true_w.shape,requires_gradTrue)#设置w初始值b_0torch.tensor(0.01,requires_gradTrue)#设置b初始值print(w_0,b_0)#打印看看初始情况正式训练epochs50#训练轮数forepochinrange(epochs):data_loss0#记录本轮训练的损失forbatch_x,batch_yindata_provider(X,Y,batch_size):#用batch_x,batch_y反复承接调用data_provider函数获得的数据进行训练pred_yfun(batch_x,w_0,b_0)#根据数据得到预测值lossmaeloss(pred_y,batch_y)#计算预测值与真实值的损失loss.backward()#梯度计算sgd([w_0,b_0],lr)#更新参数data_lossloss#累加损失print(fepoch:{epoch:3d},loss:{data_loss:.4f})#输出本轮训练的损失方便直观看清楚训练过程print(f真实的参数值{true_w,true_b})#打印真实参数print(f训练得到的参数值{w_0,b_0})#打印训练得到的参数结果如下对于我们想训练的w_0和b_0来说它们只见过batch_x和batch_y只有这两个东西与它们产生了交互从来没有见过true_w和true_b而训练之后都结果相当接近这就体现了神经网络的强大之处。我们再来调试观察梯度出现情况在执行梯度回传后grad从none变为有数值当学习率过小时五、绘图idx0#由于训练得到的参数是多个维度但是画图时这里只能取一个维度plt.plot(X[:,idx].detach().numpy(),X[:,idx].detach().numpy()*w_0[idx].detach().numpy()b_0.detach().numpy())#在x的这个维度上以x为横坐标以x*w_0b_0预测值为纵坐标画一条直线plt.scatter(X[:,idx],Y)#在x的这个维度上绘制x与y的散点图plt.show()#展示结果如下idx0idx1idx3可能的报错1这是由于没有把参数从张量网上取下就进行画图可能的报错2这是由于搞错了w的维度这里x是500x4而w是4x1所以相乘时应该是w_0[idx]就好六、总结再次回顾本次训练首先是数据我们一开始没有数据所以我们自己生成了数据而后我们写了一个函数用于分批次地提供数据其次是构造函数也就是搭建神经网络这里简单地设计了fun函数输入x,w,b会返回预测值再次是构造loss与梯度回传这里直接将预测值与真实值之间差的绝对值作为loss然后写了sgd来根据梯度更新参数之后是开始训练设置好batchsize批次大小epochs总论数用epoch代表当前轮数第二层for循环中反复调用data_provider()提供数据之后调用fun()再后调用maeloss()与sgd()sgd前进行反向传播backward()最后将本批次loss加到本轮次data_loss中每一轮都将损失值打印出来最后是打印结果打印出真实值与训练值使用plt进行可视化注意x维度和wb是否从张量网中取下在实际情况中loss与梯度回传基本不用我们在意神经网络训练中有一个关键点深度学习的神经网络训练过程最重要的地方就在于它的维度维度是我们最值得注意的事情如果维度变化没有出错那么一般网络也不会出错七、后续与思考7.1 模型泛化能力在实际应用中训练好的模型需要在未见过的数据上表现良好这就是模型的泛化能力。本文中我们使用了与训练数据同分布生成的测试数据但在真实场景中数据分布偏移训练数据与真实应用场景的数据可能存在分布差异特征工程的重要性选择合适的特征表示对模型性能至关重要交叉验证使用k折交叉验证可以更准确地评估模型泛化能力7.2 过拟合风险与应对策略线性回归虽然相对简单但仍存在过拟合风险正则化技术L1正则化Lasso可以产生稀疏解实现特征选择L2正则化Ridge限制参数大小防止过度拟合Elastic Net结合L1和L2正则化的优点早停法监控验证集损失在性能开始下降时停止训练增加训练数据更多样化的数据有助于模型学习更通用的模式7.3 学习率调整策略学习率是梯度下降算法中最重要的超参数之一固定学习率的局限性学习率过大可能导致震荡甚至发散学习率过小收敛速度慢可能陷入局部最优自适应学习率算法Adam结合动量法和自适应学习率调整RMSprop根据梯度平方的移动平均调整学习率Adagrad为每个参数分配不同的学习率学习率调度策略# 示例学习率衰减schedulertorch.optim.lr_scheduler.StepLR(optimizer,step_size30,gamma0.1)forepochinrange(epochs):# 训练步骤...scheduler.step()# 每个epoch后更新学习率7.4 模型评估与改进评估指标均方误差MSE对异常值敏感平均绝对误差MAE本文使用的方法对异常值更鲁棒R²分数衡量模型解释的方差比例模型诊断残差分析检查残差是否随机分布多重共线性检测避免特征间高度相关异方差性检验确保误差方差恒定7.5 扩展到更复杂的场景多项式回归通过添加特征的高次项来拟合非线性关系多元线性回归处理多个自变量与因变量的关系逻辑回归将线性回归扩展到分类问题神经网络中的线性层理解全连接层与线性回归的关系7.6 实践建议数据预处理标准化对特征进行标准化可以加速收敛梯度检查在复杂模型中验证梯度计算的正确性超参数调优使用网格搜索或随机搜索寻找最优超参数模型解释性线性回归的系数具有明确的物理意义通过深入思考这些进阶话题读者可以更好地将线性回归的知识应用到实际项目中并为学习更复杂的机器学习模型奠定坚实的基础。