《动手学深度学习》3.2 线性回归从零开始实现
1前言
从零开始学习ai文章系列计划是个人在《动手学深度学习》和《磨菇书》两本书的学习中的个人笔记,文章也会以课本中的章节分开,即每个章节一片笔记。我会尽量的把主要内容以及遇到的难点进行记录与解决,如果哪里有错误的欢迎指正。或者不清晰的可以直接查看原文部分。
《动手学深度学习》原文(课本):https://tangshusen.me/Dive-into-DL-PyTorch/#/
《动手学深度学习》代码:https://github.com/ShusenTang/Dive-into-DL-PyTorch
(由于有时候公式太多,可能会直接贴图片)
在了解了线性回归的背景知识之后,现在我们可以动手实现它了。尽管强大的深度学习框架可以减少大量重复性工作,但若过于依赖它提供的便利,会导致我们很难深入理解深度学习是如何工作的。因此,本节将介绍如何只利用Tensor和autograd来实现一个线性回归的训练。
首先,导入本节中实验所需的包或模块,其中的matplotlib包可用于作图,且设置成嵌入显示。
1 | import torch |
2 构造一个简单的人工训练数据集
设训练数据集样本数为1000,输入个数(特征数)为2。给定随机生成的批量样本特征X,使用线性回归模型真实权重 \(w=[2,−3.4]^⊤\) 和偏差 b=4.2,以及一个随机噪声项 ϵ 来生成标签 \[ y=Xw+b+ϵ \] torch.randn 是 PyTorch 中用于生成服从标准正态分布(均值为 0,标准差为 1)的随机张量的函数。
1 | num_inputs = 2 |
3.读取数据

上图中,j 通过torch.longTensor,获取了一个由标量组成的列表张量,如 [ 1, 3, 4, 67, 22] 。
index_select(dim, index) 用于在指定维度 dim 上,根据索引 index 选择张量的特定元素。
features.index_select(0, j):从 features 按行选择索引 j 对应的样本
函数执行后就直接从fetures与labels中返回对应大小行数的的tensor了


4. 初始化模型参数
将权重初始化成均值为0、标准差为0.01的正态随机数,偏差则初始化成0。之后的模型训练中,需要对这些参数求梯度来迭代参数的值,因此我们要让它们的requires_grad=True。
(可以看出这里是w是列向量)
1 | w = torch.tensor(np.random.normal(0, 0.01, (num_inputs, 1)), dtype=torch.float32) |
## 5.定义模型
我们使用mm函数做矩阵乘法。
1 | def linreg(X, w, b): |
6.定义损失函数
使用上一节描述的平方损失来定义线性回归的损失函数。在实现中,我们需要把真实值y变形成预测值y_hat的形状。以下函数返回的结果也将和y_hat的形状相同。
这里的 y.view(y_hat.size()) 主要作用是让 y 的形状与 y_hat 保持一致,以便执行后续的减法运算 y_hat - y
y 的原始形状: torch.Size([3])
y 经过 view 变成: torch.Size([3, 1])
1 | def squared_loss(y_hat, y): |
7.定义优化算法
以下的sgd函数实现了上一节中介绍的小批量随机梯度下降算法。它通过不断迭代模型参数来优化损失函数。这里自动求梯度模块计算得来的梯度是一个批量样本的梯度和。我们将它除以批量大小来得到平均值。

param.grad 和 param 的形状是完全相同的,这样可以逐元素计算梯度,并对 param 中的每个数值进行更新。
1 | def sgd(params, lr, batch_size): |
8.训练模型
1 | lr = 0.03 |
训练完成后,我们可以比较学到的参数和用来生成训练集的真实参数。它们应该很接近。
1 | print(true_w, '\n', w) |
