我们用生活化比喻 + 简单代码 + 图解思维,向初学者彻底讲清楚:
🎯 PyTorch 自动求导(Autograd)—— 什么是?为什么用?怎么用?
一、一句话总结:
自动求导 = PyTorch 帮你自动算梯度,不用手写导数公式!
就像你开车不用自己造发动机,PyTorch 的 autograd 系统帮你自动计算神经网络中每个参数的“变化方向”,让模型能自己学习!
二、生活化比喻:登山向导 🧭
想象你是一个登山者(模型),站在一座雾气弥漫的山上(损失函数曲面),你想最快下山(最小化损失)。但你看不清路!
✅ PyTorch 自动求导 = 你的智能登山向导
它会告诉你:“现在往左前方倾斜 30 度,坡度最陡,下降最快!” —— 这个“方向+坡度”,就是梯度(gradient)。
你不用自己拿纸笔算山坡导数,向导(autograd)自动帮你算好!
三、为什么需要自动求导?
在机器学习/深度学习中,我们要:
- 定义一个模型(比如 y = w * x + b)
- 定义一个损失函数(比如预测值和真实值的差距)
- 调整参数(w, b)让损失变小 → 需要知道损失对 w 和 b 的导数(梯度)
- 用梯度下降更新参数:
w = w - lr * grad_w
🔍 问题:如果模型有百万参数,手写导数?不可能!
✅ 解决方案:PyTorch 自动求导系统(autograd)自动帮你算所有梯度!
四、核心概念三要素
| 概念 | 说明 |
|---|---|
requires_grad=True | 告诉 PyTorch:“这个张量是我需要求梯度的参数!” |
.backward() | “开始反向传播,计算所有梯度!” |
.grad | 存放计算好的梯度值(导数) |
五、代码示例:从 0 学会自动求导
🧮 例子:计算 y = x² 在 x=3 处的导数
我们知道:dy/dx = 2x → x=3 时,导数应为 6。
import torch
# 1. 创建张量,设置 requires_grad=True —— “我要对它求导!”
x = torch.tensor(3.0, requires_grad=True)
# 2. 定义计算过程(前向传播)
y = x ** 2 # y = x²
# 3. 反向传播 —— 自动计算梯度
y.backward() # 相当于 dy/dx
# 4. 查看梯度
print(x.grad) # 输出:tensor(6.) ✅ 正确!
📈 例子2:带多个变量 —— y = a * x + b
import torch
x = torch.tensor(2.0)
a = torch.tensor(3.0, requires_grad=True) # 要求导
b = torch.tensor(1.0, requires_grad=True) # 要求导
y = a * x + b # y = 3*2 + 1 = 7
y.backward() # 自动计算 dy/da 和 dy/db
print("dy/da =", a.grad) # dy/da = x = 2.0 → 输出:tensor(2.)
print("dy/db =", b.grad) # dy/db = 1 → 输出:tensor(1.)
✅ 注意:
- 不是所有张量都需要梯度,只有你关心的参数(如神经网络权重)才设
requires_grad=True backward()默认只对标量(一个数)求导。如果是向量,要传gradient参数(后面讲)
六、在神经网络中的真实应用场景
import torch
import torch.nn as nn
# 定义一个简单线性模型
model = nn.Linear(1, 1) # y = w*x + b
# 损失函数
loss_fn = nn.MSELoss()
# 优化器(它会用 .grad 来更新参数)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
# 假数据
x = torch.tensor([[1.0], [2.0], [3.0]])
y_true = torch.tensor([[2.0], [4.0], [6.0]]) # 真实值:y = 2*x
for epoch in range(100):
optimizer.zero_grad() # 1️⃣ 清空旧梯度
y_pred = model(x) # 2️⃣ 前向传播
loss = loss_fn(y_pred, y_true) # 计算损失
loss.backward() # 3️⃣ 自动求导!计算所有参数的梯度
optimizer.step() # 4️⃣ 用梯度更新参数 w 和 b
if epoch % 20 == 0:
print(f"Epoch {epoch}, Loss: {loss.item():.4f}")
📌 关键四步:
zero_grad()—— 清除上一轮梯度(否则会累加!)- 前向计算 → 得到 loss
loss.backward()—— 自动计算所有requires_grad=True参数的梯度optimizer.step()—— 用梯度更新参数
七、常见问题 & 注意事项(初学者必看!)
❗ 1. 为什么梯度是累加的?
PyTorch 默认梯度累加(为了支持梯度累积等高级技巧),所以每次训练前必须清零:
optimizer.zero_grad()
# 或者
model.zero_grad()
❗ 2. 什么时候用 requires_grad=True?
- 神经网络的参数(weights, bias) → 框架自动设置(如
nn.Linear) - 你自己定义的需要优化的变量 → 手动设置
- 输入数据(x)通常不需要求导 → 保持默认
False
❗ 3. 如果 y 不是标量怎么办?
x = torch.tensor([2.0, 3.0], requires_grad=True)
y = x ** 2 # y = [4., 9.] —— 向量!
# ❌ 不能直接 y.backward()!
# ✅ 要传一个权重向量(通常用于多输出)
y.backward(torch.tensor([1.0, 1.0])) # 相当于对 y.sum() 求导
print(x.grad) # 输出:tensor([4., 6.]) → 2x 在 x=2,3 处
💡 简单记:loss 一定要是标量(一个数),比如
loss.mean()或loss.sum()
八、图解自动求导(计算图)
PyTorch 在后台为你构建“计算图”:
x (requires_grad=True)
│
▼
y = x ** 2
│
▼
loss = y → 标量
│
▼
loss.backward() → 从 loss 开始,反向传播,计算 dy/dx
每个操作(+、*、sin、exp...)PyTorch 都知道怎么求导,自动链式法则组合!
九、总结:自动求导三步走
- 标记:对需要求导的张量设置
requires_grad=True - 计算:进行前向计算,得到最终标量(如 loss)
- 反传:调用
.backward(),PyTorch 自动计算所有梯度,存到.grad中
🎁 给初学者的贴心提示:
- ✅ 自动求导是深度学习的“发动机”,不用怕数学,PyTorch 帮你搞定导数!
- ✅ 多写几个小例子(比如 y = sin(x), y = x * log(x)),亲手验证梯度
- ✅ 调试时打印
.grad看看值对不对,是很好的学习方式 - ✅ 记住:
zero_grad()→forward→backward()→step()是训练循环黄金四步!