全手工模拟:https://blog.csdn.net/qq_37397652/article/details/136606208
import torch
# Here we replace the manually computed gradient with autograd
# Linear regression
# f = w * x
# here : f = 2 * x
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
w = torch.tensor(0.0, dtype=torch.float32, requires_grad=True)
# model output
def forward(x):
return w * x
# loss = MSE
def loss(y, y_pred):
return ((y_pred - y)**2).mean()
print(f'Prediction before training: f(5) = {forward(5).item():.3f}')
# Training
learning_rate = 0.01
n_iters = 100
for epoch in range(n_iters):
# predict = forward pass
y_pred = forward(X)
# loss
l = loss(Y, y_pred)
# calculate gradients = backward pass
l.backward()
# update weights
#w.data = w.data - learning_rate * w.grad
with torch.no_grad():
w -= learning_rate * w.grad
# zero the gradients after updating
w.grad.zero_()
if epoch % 10 == 0:
print(f'epoch {epoch+1}: w = {w.item():.3f}, loss = {l.item():.8f}')
print(f'Prediction after training: f(5) = {forward(5).item():.3f}')
输出:
Prediction before training: f(5) = 0.000
epoch 1: w = 0.300, loss = 30.00000000
epoch 11: w = 1.665, loss = 1.16278565
epoch 21: w = 1.934, loss = 0.04506890
epoch 31: w = 1.987, loss = 0.00174685
epoch 41: w = 1.997, loss = 0.00006770
epoch 51: w = 1.999, loss = 0.00000262
epoch 61: w = 2.000, loss = 0.00000010
epoch 71: w = 2.000, loss = 0.00000000
epoch 81: w = 2.000, loss = 0.00000000
epoch 91: w = 2.000, loss = 0.00000000
Prediction after training: f(5) = 10.000
这段代码演示了使用PyTorch自动微分功能(autograd)来训练一个简单的线性回归模型。线性回归的目的是找到一个权重 (w),使得模型 (f(x) = w \times x) 能够尽可能准确地预测给定输入 (x) 对应的输出 (y)。这个例子中,我们希望模型学习到的权重使得 (f(x)) 接近真实函数 (f(x) = 2x)。
代码逐行解释:
-
初始化数据和权重:
X
和Y
分别是模型的输入和对应的真实输出。w
是模型的权重,初始化为 0,并且设置requires_grad=True
以告诉PyTorch我们需要计算这个权重的梯度。
-
定义模型和损失函数:
forward
函数定义了模型的前向传播,即如何根据输入 (x) 和权重 (w) 计算预测值。loss
函数定义了均方误差(MSE)损失,用于评估预测值与真实值之间的差距。
-
训练过程:
- 在每次迭代中,首先进行前向传播计算预测值。
- 然后计算损失,评估模型当前预测的准确性。
- 通过调用
l.backward()
自动计算损失函数相对于权重 (w) 的梯度。 - 使用
torch.no_grad()
暂时关闭梯度跟踪,因为接下来的权重更新不应该被记录为计算图的一部分。 - 更新权重 (w),利用计算出的梯度和一个预定义的学习率,这一步是梯度下降法的实现。
- 通过
w.grad.zero_()
重置梯度,为下一次迭代准备。
关键点:
-
自动梯度计算:PyTorch的自动微分引擎(autograd)使得计算梯度变得简单。通过在损失张量上调用
.backward()
方法,PyTorch会自动计算所有requires_grad=True
的张量(在这个例子中是权重 (w))的梯度,并将其存储在它们各自的.grad
属性中。 -
权重更新:权重的更新是在不追踪梯度的上下文中完成的,这是为了确保这一步骤不会影响到后续梯度的计算。
-
梯度清零:在每次权重更新后,必须清零梯度,因为PyTorch默认会累积梯度,如果不清零,下一次
.backward()
调用时会将新的梯度加到旧的梯度上。
结果:
- 在训练开始前,模型的预测值是基于初始权重(这里是0)的,所以对于输入5,预测结果也是0。
- 经过训练后,权重 (w) 被更新为接近真实函数 (f(x) = 2x) 的斜率,因此模型的预测变得更加准确。
- 通过输出可以看到,随着训练的进行,权重 (w) 逐渐增加,损失逐渐减小,模型的预测能力得到了显著提升。