3.2 线性回归的从零开始实现
导入所需要的库
1 | import torch |
生成数据集
构造一个简单的人工训练数据集,设训练数据集样本数为1000,输入个数(特征数)为2。使用线性回归模型真实权重\(w=[2,-3.4]^T\)和偏差\(b=4.2\),以及一个随机噪声项\(\epsilon\)生成标签。
其中噪声项 \(\epsilon\) 服从均值为0、标准差为0.01的正态分布。噪声代表了数据集中无意义的干扰。
1 | num_inputs=2 #特征数 |
读取数据
在训练模型的时候,需要遍历数据集并不断读取小批量数据样本。定义一个函数,每次返回batch_size
(批量大小)个随机样本的特征和标签。
1 | def data_iter(batch_size, features, labels): #batch_size:批量大小,features:特征,labels:标签 |
初始化模型参数
将权重初始化成均值为0、标准差为0.01的正态随机数,偏差则初始化成0。
1 | w=torch.tensor(torch.normal(0,0.01,size=(num_inputs,1)),dtype=torch.float32) |
之后的模型训练中,需要对这些参数求梯度来迭代参数的值,因此要让它们的requires_grad=True
。
1 | w.requires_grad_(requires_grad=True) #设置为True表示会被求导 |
定义模型
下面是线性回归的矢量计算表达式的实现。使用mm
函数做矩阵乘法。
1 | def linreg(X,w,b): #定义线性回归模型 |
定义损失函数
先将真实值y
变形成预测值y_hat
的形状。以下函数返回的结果也将和y_hat
的形状相同。
1 | def squared_loss(y_hat,y): #定义损失函数 |
定义优化算法
以下的sgd
函数实现了小批量随机梯度下降算法。它通过不断迭代模型参数来优化损失函数。这里自动求梯度模块计算得来的梯度是一个批量样本的梯度和。将它除以批量大小来得到平均值。
1 | def sgd(params,lr,batch_size): #定义优化算法,params:待优化参数,lr:学习率,batch_size:批量大小 |
训练模型
在训练中,将多次迭代模型参数。在每次迭代中,根据当前读取的小批量数据样本(特征X
和标签y
),通过调用反向函数backward
计算小批量随机梯度,并调用优化算法sgd
迭代模型参数。由于之前设批量大小batch_size
为10,每个小批量的损失l
的形状为(10, 1)。由于变量l
并不是一个标量,所以可以调用.sum()
将其求和得到一个标量,再运行l.backward()
得到该变量有关模型参数的梯度。注意在每次更新完参数后不要忘了将参数的梯度清零。
在一个迭代周期(epoch)中,将完整遍历一遍data_iter
函数,并对训练数据集中所有样本都使用一次(假设样本数能够被批量大小整除)。这里的迭代周期个数num_epochs
和学习率lr
都是超参数,分别设3和0.03。
1 | lr=0.03 #学习率 |