PyTorch 自动微分与完整手动实现对比
- 一、手动实现前向传播
-
- [1. 问题设定](#1. 问题设定)
- 2.代码实现
- [3. 手动计算梯度(反向传播)](#3. 手动计算梯度(反向传播))
- [4. 参数更新(手动实现 optimizer.step ())](#4. 参数更新(手动实现 optimizer.step ()))
- [二、 PyTorch 自动微分](#二、 PyTorch 自动微分)
- [三、 总结](#三、 总结)
一、手动实现前向传播
1. 问题设定

2.代码实现
python
# 输入数据和标签
x = [1.0, 2.0] # 输入特征
y = 3.0 # 真实标签
# 模型参数(随机初始化)
w = [0.5, 0.5] # 权重
b = 0.1 # 偏置
# 前向传播计算预测值
y_pred = w[0] * x[0] + w[1] * x[1] + b
# 计算损失(MSE)
loss = 0.5 * (y_pred - y) ** 2
print(f"预测值: {y_pred}, 损失: {loss}")
3. 手动计算梯度(反向传播)

python
# 计算中间梯度
dL_dy_pred = y_pred - y # ∂L/∂ŷ
# 计算参数梯度
dL_dw1 = dL_dy_pred * x[0] # ∂L/∂w1 = ∂L/∂ŷ * ∂ŷ/∂w1
dL_dw2 = dL_dy_pred * x[1] # ∂L/∂w2 = ∂L/∂ŷ * ∂ŷ/∂w2
dL_db = dL_dy_pred # ∂L/∂b = ∂L/∂ŷ * ∂ŷ/∂b
print(f"梯度: ∂L/∂w1 = {dL_dw1}, ∂L/∂w2 = {dL_dw2}, ∂L/∂b = {dL_db}")
4. 参数更新(手动实现 optimizer.step ())
使用梯度下降更新参数:
python
learning_rate = 0.01
# 更新参数
w[0] = w[0] - learning_rate * dL_dw1
w[1] = w[1] - learning_rate * dL_dw2
b = b - learning_rate * dL_db
print(f"更新后的参数: w = {w}, b = {b}")
二、 PyTorch 自动微分
python
import torch
import torch.nn as nn
# ===== PyTorch 自动微分实现 =====
# 创建模型和数据
net = nn.Sequential(nn.Linear(2, 1))
net[0].weight.data = torch.tensor([[0.5, 0.5]]) # 初始权重
net[0].bias.data = torch.tensor([0.1]) # 初始偏置
x_tensor = torch.tensor([[1.0, 2.0]], requires_grad=False)
y_tensor = torch.tensor([[3.0]])
# 前向传播
y_pred_tensor = net(x_tensor)
loss_tensor = nn.MSELoss()(y_pred_tensor, y_tensor)
# 反向传播
loss_tensor.backward()
print("\nPyTorch 自动微分结果:")
print(f"预测值: {y_pred_tensor.item()}, 损失: {loss_tensor.item()}")
print(f"梯度: ∂L/∂w1 = {net[0].weight.grad[0, 0].item()}, "
f"∂L/∂w2 = {net[0].weight.grad[0, 1].item()}, "
f"∂L/∂b = {net[0].bias.grad.item()}")
# ===== 手动实现结果 =====
print("\n手动实现结果:")
print(f"预测值: {y_pred}, 损失: {loss}")
print(f"梯度: ∂L/∂w1 = {dL_dw1}, ∂L/∂w2 = {dL_dw2}, ∂L/∂b = {dL_db}")
输出对比(假设学习率为 0.01)
:
python
PyTorch 自动微分结果:
预测值: 1.6, 损失: 0.98
梯度: ∂L/∂w1 = 1.4, ∂L/∂w2 = 2.8, ∂L/∂b = 1.4
手动实现结果:
预测值: 1.6, 损失: 0.98
梯度: ∂L/∂w1 = 1.4, ∂L/∂w2 = 2.8, ∂L/∂b = 1.4
三、 总结
计算图的本质 :
无论使用 PyTorch 还是手动计算,梯度的流动路径都是由数学公式决定的。PyTorch 只是自动帮你构建了这个路径。
链式法则的核心作用 :
梯度从损失函数开始,通过链式法则逐层传递到每个参数。例如:
∂L/∂w1 = (∂L/∂ŷ) * (∂ŷ/∂w1) = (ŷ - y) * x1
PyTorch 的自动微分
当你调用 loss.backward() 时,PyTorch 会:
- 自动追踪从 loss 到 weight 和 bias 的所有操作路径。
- 对每个操作应用链式法则计算局部梯度。
- 将最终梯度存储在 weight.grad 和 bias.grad 中。