波波算法笔记

Bob Peng

有关线性回归模型训练的基本思路

2025-03-31
有关线性回归模型训练的基本思路

有关线性回归模型训练的基本思路

前言

嘿!这里是笔者的《动手学深度学习》v2学习篇,最近一段时间由于工作需要,目前在深度学习“深度学习”
![](https://res.wx.qq.com/t/wx_fed/we-
emoji/res/v1.3.10/assets/newemoji/2_06.png) ,以下皆为学习笔记与思考的分享。欢迎指正与follow。

有关线性回归模型训练的基本思路

前言

机器学习问题包含 分类问题回归问题 。我们今天讨论一下 有关线性回归模型的训练基本思路

注意:代码只是用于学习思路,理解原理,比较繁琐。

基础理论

应用场景

代码实现

导入基本库

%matplotlib inline  
import random  
import torch  
from d2l import torch as d2l  

数据集生成

提前设置好w,b参数(仅用于生成符合w,b参数的数据),构造数据集。

后续会随机初始化模型的w,b参数,训练模型,使得其向数据集的w,b值靠近。

def synthetic_dataset(w,b,num_examples):  
    X=torch.normal(0,1,(num_examples,len(w)))  
    y=torch.matmul(X,w)+b  
    y+=torch.normal(0,0.01,y.shape)  
  
    return X,y.reshape((-1,1))

可以测试一下方法的效果

true_w=torch.tensor([2,-3.4])  
true_b=4.2  
  
features,lables=synthetic_dataset(true_w,true_b,1000)

小批量拿数据

根据我们设置的batchsize大小,在数据样本中取一个批次的样本数。直到遍历完所有的数据样本。我们就完成了一个epoch训练。

关于batchsize大小

越大的 batch size 使下降方向越准确,震荡越小;batch size 如果过大,则可能会出现局部最优的情况。

小的 bath size 引入的随机性更大,可能难以达到收敛,但是小批次噪音多,某种方面会提高模型性能。

def data_iter(batchsize,features,lables):  
    num=len(features)  
    indices=list(range(num))  
    random.shuffle(indices)  
    for i in range(0,num,batchsize):  
        batch_indices=torch.tensor(indices[i:min(i+batchsize,num)])  
        yield features[batch_indices],lables[batch_indices]  
    

初始化w,b参数。定义模型(线性回归方程)

这里初始化了w,b参数,构建了模型函数。接下来就需要利用数据训练模型,优化更新w,b参数,使得模型更加拟合数据

   w=torch.normal(0,0.01,size=(2,1),requires_grad=True)  
   b=torch.zeros(1,requires_grad=True)   
   def linreg(X,w,b):  
    return torch.matmul(X,w)+b

定义损失函数,优化算法

损失函数使用的是均方误差(MSE),预测值与实际值的差值的平方除以2,表示损失。训练过程中损失降低意味着误差越来越小,模型越来越好。

优化算法使用的是SGD,反梯度方向更新参数。通过最小化损失来学习参数。

你会注意到代码中梯度的下降有关学习率(lr).

学习率太小会导致参数更新得太慢了,因为每训练一个batchsize更新一次参数,可能训练完所有数据模型参数还没有收敛.

学习率太大会导致步子参数更新幅度太大,过头了,会产生震荡,也难以收敛.

def squared_loss(y_hat,y):  
    return (y_hat-y.reshape(y_hat.shape))**2/2  
      
def sgd(params,lr,batch_size):  
    with torch.no_grad():  
        for param in params:  
            param-=lr*param.grad/batch_size  
            param.grad.zero_()

训练

lr=0.03  
num_epoch=3  
loss=squared_loss  
net=linreg  
  
for epoch in range(num_epoch):  
    for X,y in data_iter(batchsize,features,lables):  
        l=loss(net(X,w,b),y)  
  
        l.sum().backward()  
  
        sgd([w,b],lr,batchsize)  
  
    with torch.no_grad():  
  
        train_l=loss(net(features,w,b),lables)  
  
        print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')  
  
    print(w,b)

结果如下

可以发现loss损失值一直在下解,且模型的w,b的值,也在向构造数据集时设置的w,b的值靠近。so,实验正确。

epoch 1, loss 0.041691  
tensor([[ 1.8858],  
        [-3.2330]], requires_grad=True) tensor([3.9893], requires_grad=True)  
epoch 2, loss 0.000148  
tensor([[ 1.9943],  
        [-3.3918]], requires_grad=True) tensor([4.1902], requires_grad=True)  
epoch 3, loss 0.000047  
tensor([[ 2.0001],  
        [-3.3994]], requires_grad=True) tensor([4.1996], requires_grad=True)