08 Pytorch实现线性回归
Pytorch实现线性回归
这一篇博客主要介绍怎样使用 Pytorch 提供的工具帮助我们重现线性模型的过程。比如我们怎么构造神经网络,如何构造损失函数以及如何构造随机梯度下降的优化器。
我们首先回忆一下之前学习的线性模型中,首先需要确定我们的模型,之后要定义损失函数,而且损失函数计算出来的值必须是一个标量值。
我们用 Pytorch 来写深度神经网络,第一步先要准备数据集(Prepare dataset),第二步就是要设计模型(计算 y_hat),第三步构造损失函数和优化器,第四步就是写训练周期(forward、backward、update),forward 计算损失,backward 计算梯度,update 就是用梯度下降算法更新权重。
1. Prepare Dataset
那么首先来看看怎么准备数据?我们之前使用的都是两个向量 x_data 和 y_data。在这次的例子中,我们使用 mini-batch 这样一个风格,意思是我们现在想要一次性将结果都求解出来。
对于之前的模型 y_hat =
w
∗
x
+
b
w*x + b
w∗x+b,现在有三个数据样本
(
x
1
,
y
1
)
(x_1, y_1)
(x1,y1),
(
x
2
,
y
2
)
(x_2, y_2)
(x2,y2) 和
(
x
3
,
y
3
)
(x_3, y_3)
(x3,y3),之后要求损失函数就得把所有对
x
x
x 的 y_hat 求解出来,即 y_hat1 =
w
∗
x
1
+
b
w*x_1 + b
w∗x1+b, y_hat2 =
w
∗
x
2
+
b
w*x_2 + b
w∗x2+b,y_hat3 =
w
∗
x
3
+
b
w*x_3 + b
w∗x3+b。我们在使用 numpy 时,里面有一种广播机制,如果你用一个 3x3 的矩阵和一个 3x1 的矩阵相加,原理上是不能相加的,但是 numpy 会将第二个矩阵扩充成 3x3 的矩阵,会进行这样的自动广播。比如:
接下来,我们再来看这三个式子。
如果我们把这三个式子写成向量化的表达方式:
那么我们注意里面这个维度,y_hat 是一个 3 行 1 列的矩阵,
x
x
x 也是一个 3 行 1 列的矩阵,所以在进行计算的时候,
w
w
w 会被自动进行广播扩充为 3 行 1 列的矩阵,
b
b
b 同理也会被自动进行广播扩充为 3 行 1 列的矩阵。
这就是我们在使用 Pytorch 进行小批量计算时所使用的方法。
将来我们在计算损失时,损失的式子是:
那么对于每一个样本,相应的损失就等于:
当我们将上面的式子进行向量化,就变成:
所以我们在构造数据集的时候,
x
x
x 和
y
y
y 的值必须是矩阵。
2. Design Model
之前我们是人工求解导数,就是把导数的解析式求解出来,那么到了 Pytorch 之后,我们就不再考虑人工来求解导数,我们的重点目标变成了构造计算图。只要能够把计算图构造出来,那么将来它会自动帮我们把梯度求解出来,然后就可以直接做优化了。这就是第二步要做的事情,Design Model。在我们这个例子中,用了一个仿射模型,Pytorch 将它称做 Linear Unit(线性单元)。一个线性单元就是 w ∗ x + b w*x + b w∗x+b,这个线性单元将来我们构造的时候,需要确定权重 w w w 的 shape 是什么? b b b 的 shape 是什么?
那么我们要想确定
w
w
w 的大小,那么我们就得先确定
x
x
x 的 shape,比如
z
=
w
x
+
b
z = wx + b
z=wx+b,
x
x
x 是一个 4x1 的矩阵,
z
z
z 是一个 3x1 的矩阵,那么
w
w
w 就得是一个 3x4 的矩阵,
b
b
b 是一个 3x1 的矩阵。所以对于 Linear Unit 来说,我们要想确定权重的维度,就需要知道
x
x
x 的维度,还需要知道输出的 y_hat 的维度,只要知道了这两个值,那么就可以确定
w
w
w 和
b
b
b 的维度。y_hat 计算出来之后,下一步就要计算 Loss 函数,最终求出损失值。
换句话说,我们要构造这样的一个计算图,从
x
x
x 开始,经过权重参与的运算,最终经过损失函数计算出 Loss,然后我们就可以在 Loss 这个地方调用 backward,然后就可以对整个计算图进行反向传播。这就是大体的模型设计流程。
这里需要注意的是,y_hat 的维度可以是任意的,但是 loss 最终必须是一个标量。但是根据之前的计算式可以发现,计算出来的 Loss 也是一个矩阵。
所以最终要得到 Loss 值,那我们就需要把所有的 Loss 进行求和,然后再选择是否要求一个均值。所以最后的 loss 是一个标量。因为如果你的 loss 最后算出来是一个向量的话,是没法使用 backward 的。
接下来我们看看在 Pytorch 里面怎么 Design Model。
接下来我们来来 Linear 这个类。
3. Construct loss and optimizer
第三步就是构造损失函数和优化器。我们上面的例子中使用的损失函数就是 MSE,在 Pytorch 中有一个现成的类 torch.nn.MSELoss。
接下来再来看看优化器.。
4. Training Cycle
然后就是第四步 Training Cycle。
总结来说,就是来说就四步:
1. 计算 y_hat
2. 计算 Loss
3. backward(之前一定要将梯度清零)
4. Update
5. 总结
那么,整个流程就是这样的:
如果有兴趣的小伙伴可以使用不同的优化器来观察优化效果。Pytorch 中提供了非常多的优化器:
可以比较一下,不同的优化器,它们得到的损失值的大小,以及最后得到的参数。
具体代码见 08 Pytorch实现线性回归.ipynb