1. 什么是梯度?
打个比方:想象你在一片黑暗的山丘上,手里有一盏灯,想找到山谷里最低的那一点(也就是模型的最优解)。梯度就像这盏灯的光束,它会告诉你:“往哪个方向走,能最快下山。”
• 数学定义:梯度是函数在某一点的“最陡上升方向”。但在机器学习中,我们通常需要找最小值,所以会朝梯度的反方向走(相当于“下山”)。
2. 为什么需要梯度?
• 目标:训练模型时,我们需要调整参数(比如房价预测中的“面积权重”“房间数权重”),让模型预测值尽量接近真实值。
• 问题:如果盲目的调整参数,可能会像无头苍蝇一样找不到方向。梯度就相当于给了你一张“地图”,告诉你每一步该往哪迈多大的步子。
3. 计算步骤
- 假设模型参数
- 给错误打分(损失函数)
- 计算梯度(找方向)
- 调整参数(开始“下山”)
4. 梯度的实际作用
• 指导方向:梯度指向损失函数下降最快的方向(即最优参数)。
• 控制步长:学习率决定调整幅度(太小会走太慢,太大容易“跳过”最优解)。
• 自动化实现:在PyTorch中,只需调用 .backward() 和 .step(),它会自动计算梯度并更新参数。
案例
假设你想用机器学习预测房价,已知以下数据:
| 房屋面积(x1x_1x1) | 房间数(x2x_2x2) | 真实房价(yyy) |
|---|---|---|
| 80㎡ | 2室 | 200万元 |
| 100㎡ | 3室 | 300万元 |
| 120㎡ | 4室 | 400万元 |
我们用线性模型 y=w1x1+w2x2+by = w_1x_1 + w_2x_2 + by=w1x1+w2x2+b 预测房价,目标是找到最优的 w1,w2,bw_1, w_2, bw1,w2,b。
步骤1:假设初始参数
假设模型参数为 w1=1,w2=1,b=0w_1=1,\quad w_2=1,\quad b=0w1=1,w2=1,b=0,预测房价为:
• 第一套房:80×1+2×1+0=8280 \times 1 + 2 \times 1 + 0 = 8280×1+2×1+0=82 万元(误差:200−82=118200-82=118200−82=118)
• 第二套房:100×1+3×1+0=103100 \times 1 + 3 \times 1 + 0 = 103100×1+3×1+0=103 万元(误差:300−103=197300-103=197300−103=197)
• 第三套房:120×1+4×1+0=124120 \times 1 + 4 \times 1 + 0 = 124120×1+4×1+0=124 万元(误差:400−124=276400-124=276400−124=276)
步骤2:计算损失函数
用均方误差(MSE)作为损失函数:
l=13[(200−82)2+(300−103)2+(400−124)2]=13(13924+38809+75696)=42,969.67
l = \frac{1}{3} \left[ (200-82)^2 + (300-103)^2 + (400-124)^2 \right] = \frac{1}{3}(13924 + 38809 + 75696) = 42,969.67
l=31[(200−82)2+(300−103)2+(400−124)2]=31(13924+38809+75696)=42,969.67
步骤3:计算梯度(公式应用)
公式1:损失对中间变量 yyy 的敏感度(vvv)
对每个预测值 yiy_iyi 求偏导数得到梯度 vvv:
∂l∂yi=2(ypredi−yreali)3
\frac{\partial l}{\partial y_i} = \frac{2(y_{\text{pred}_i} - y_{\text{real}_i})}{3}
∂yi∂l=32(ypredi−yreali)
中间变量 yyy 是预测值,梯度 vvv 表示每个预测值对损失的直接影响:
v=(∂l∂y1∂l∂y2∂l∂y3)=(2(82−200)/32(103−300)/32(124−400)/3)=(−78.67−131.33−184)
v = \begin{pmatrix}
\frac{\partial l}{\partial y_1} \\
\frac{\partial l}{\partial y_2} \\
\frac{\partial l}{\partial y_3}
\end{pmatrix} = \begin{pmatrix}
2(82-200)/3 \\
2(103-300)/3 \\
2(124-400)/3
\end{pmatrix} = \begin{pmatrix}
-78.67 \\
-131.33 \\
-184
\end{pmatrix}
v=∂y1∂l∂y2∂l∂y3∂l=2(82−200)/32(103−300)/32(124−400)/3=−78.67−131.33−184
公式2:中间变量 yyy 对参数 w1,w2,bw_1, w_2, bw1,w2,b 的敏感度(JJJ)
雅可比矩阵 JJJ 表示每个参数对预测值的影响:
J=(∂y1∂w1∂y1∂w2∂y1∂b∂y2∂w1∂y2∂w2∂y2∂b∂y3∂w1∂y3∂w2∂y3∂b)=(x11x121x21x221x31x321)=(80211003112041)
J = \begin{pmatrix}
\frac{\partial y_1}{\partial w_1} & \frac{\partial y_1}{\partial w_2} & \frac{\partial y_1}{\partial b} \\
\frac{\partial y_2}{\partial w_1} & \frac{\partial y_2}{\partial w_2} & \frac{\partial y_2}{\partial b} \\
\frac{\partial y_3}{\partial w_1} & \frac{\partial y_3}{\partial w_2} & \frac{\partial y_3}{\partial b}
\end{pmatrix} = \begin{pmatrix}
x_{11} & x_{12} & 1 \\
x_{21} & x_{22} & 1 \\
x_{31} & x_{32} & 1
\end{pmatrix} = \begin{pmatrix}
80 & 2 & 1 \\
100 & 3 & 1 \\
120 & 4 & 1
\end{pmatrix}
J=∂w1∂y1∂w1∂y2∂w1∂y3∂w2∂y1∂w2∂y2∂w2∂y3∂b∂y1∂b∂y2∂b∂y3=x11x21x31x12x22x32111=80100120234111
• 解释:这是一个雅可比矩阵,描述了你的模型中三个参数(w1w_1w1、w2w_2w2、bbb)如何影响三个中间变量(y1y_1y1、y2y_2y2、y3y_3y3)。
第一套房的预测值比真实值小118,导致损失增加约46单位。
矩阵中的每一行对应一个房屋样本,每一列对应参数的影响:
-
第一行(80㎡ 房子)
• ∂y1∂w1=80\frac{\partial y_1}{\partial w_1} = 80∂w1∂y1=80: 面积权重(w1w_1w1)每增加1,预测房价增加80元。
• ∂y1∂w2=2\frac{\partial y_1}{\partial w_2} = 2∂w2∂y1=2: 房间数权重(w2w_2w2)每增加1,预测房价增加2元。
• ∂y1∂b=1\frac{\partial y_1}{\partial b} = 1∂b∂y1=1: 截距(bbb)每增加1,预测房价增加1元。 -
第二行(100㎡ 房子)
• ∂y2∂w1=100\frac{\partial y_2}{\partial w_1} = 100∂w1∂y2=100: 面积权重(w1w_1w1)对这套房的影响更大。
• ∂y2∂w2=3\frac{\partial y_2}{\partial w_2} = 3∂w2∂y2=3: 房间数权重(w2w_2w2)每增加1,房价增加3元。 -
第三行(120㎡ 房子)
• ∂y3∂w1=120\frac{\partial y_3}{\partial w_1} = 120∂w1∂y3=120: 面积权重(w1w_1w1)对大房子影响最大。
• ∂y3∂w2=4\frac{\partial y_3}{\partial w_2} = 4∂w2∂y3=4: 房间数权重(w2w_2w2)对大房子影响也更大。
最终梯度(链式法则)
损失对参数的梯度为∂l∂θ=v⋅J
\frac{\partial l}{\partial \theta} = v \cdot J
∂θ∂l=v⋅J
详细计算:
∂l∂w1=(−78.67)×80+(−131.33)×100+(−184)×120=−6293.6−13133−22080=−41506.6∂l∂w2=(−78.67)×2+(−131.33)×3+(−184)×4=−157.34−393.99−736=−1287.33∂l∂b=(−78.67)+(−131.33)+(−184)=−394
\begin{aligned}
\frac{\partial l}{\partial w_1} &= (-78.67) \times 80 + (-131.33) \times 100 + (-184) \times 120 \\
&= -6293.6 -13133 -22080 = \boxed{-41506.6} \\
\frac{\partial l}{\partial w_2} &= (-78.67) \times 2 + (-131.33) \times 3 + (-184) \times 4 \\
&= -157.34 -393.99 -736 = \boxed{-1287.33} \\
\frac{\partial l}{\partial b} &= (-78.67) + (-131.33) + (-184) = \boxed{-394}
\end{aligned}
∂w1∂l∂w2∂l∂b∂l=(−78.67)×80+(−131.33)×100+(−184)×120=−6293.6−13133−22080=−41506.6=(−78.67)×2+(−131.33)×3+(−184)×4=−157.34−393.99−736=−1287.33=(−78.67)+(−131.33)+(−184)=−394
步骤4:更新参数
参数更新公式:
w′=w−α⋅∂l∂w
w' = w - \alpha \cdot \frac{\partial l}{\partial w}
w′=w−α⋅∂w∂l
假设学习率 α=0.01\alpha = 0.01α=0.01,计算结果:
w1′=1−0.01×(−41506.6)=1+415.066=416.066w2′=1−0.01×(−1287.33)=1+12.8733=13.8733b′=0−0.01×(−394)=0+3.94=3.94
\begin{aligned}
w_1' &= 1 - 0.01 \times (-41506.6) = 1 + 415.066 = \boxed{416.066} \\
w_2' &= 1 - 0.01 \times (-1287.33) = 1 + 12.8733 = \boxed{13.8733} \\
b' &= 0 - 0.01 \times (-394) = 0 + 3.94 = \boxed{3.94}
\end{aligned}
w1′w2′b′=1−0.01×(−41506.6)=1+415.066=416.066=1−0.01×(−1287.33)=1+12.8733=13.8733=0−0.01×(−394)=0+3.94=3.94
计算结果说明与分析
-
初始参数严重偏离最优值
初始参数 w1=1,w2=1,b=0w_1=1, w_2=1, b=0w1=1,w2=1,b=0 导致预测值远低于真实房价(如第一套房预测 82 万元 vs 真实 200 万元),误差极大。
后果:损失函数对参数的梯度绝对值极大(如 ∂l∂w1=−41506.6\frac{\partial l}{\partial w_1} = -41506.6∂w1∂l=−41506.6),学习率 α=0.01\alpha=0.01α=0.01 乘以梯度后,参数更新量级达数百甚至数千。 -
学习率过高
当前学习率 α=0.01\alpha=0.01α=0.01 与极大梯度相乘,导致参数更新幅度失控。
示例:
w1w_1w1 从 111 变为 416.066416.066416.066,单次更新后预测值:
416.066×80+13.8733×2+3.94≈33,300416.066 \times 80 + 13.8733 \times 2 + 3.94 \approx 33,300416.066×80+13.8733×2+3.94≈33,300 万元(远超真实值 200 万元)。
关键总结
-
梯度计算正确性:
• 雅可比矩阵维度为 样本数 ×\times× 参数数,链式法则推导无误。
• 参数更新公式明确展示负梯度如何转化为参数增大。 -
实践建议:
• 初始学习率不宜过高,避免单次更新幅度过大。
• 可通过多次迭代(如1000次)观察参数收敛过程。 -
自动化梯度计算:
在PyTorch中,只需以下两行代码即可自动完成上述所有计算:model.backward() # 计算梯度 optimizer.step() # 更新参数
实现代码
import torch
# 1. 数据准备
x1 = torch.tensor([80, 100, 120], dtype=torch.float32) # 房屋面积
x2 = torch.tensor([2, 3, 4], dtype=torch.float32) # 房间数
y_true = torch.tensor([200, 300, 400], dtype=torch.float32) # 真实房价
# 2. 初始化参数(设置需要计算梯度)
w1 = torch.tensor(1.0, requires_grad=True)
w2 = torch.tensor(1.0, requires_grad=True)
b = torch.tensor(0.0, requires_grad=True)
# 3. 设置优化器
optimizer = torch.optim.SGD([w1, w2, b], lr=0.01)
# 4. 清零梯度
optimizer.zero_grad()
# 5. 前向传播
y_pred = w1 * x1 + w2 * x2 + b # 线性模型预测
# 6. 计算损失(均方误差)
loss = torch.mean((y_pred - y_true) ** 2)
# 7. 反向传播计算梯度
loss.backward()
# 8. 更新参数
optimizer.step()
print(f"损失值: {loss}") # 42969.66796875
print(f"输出梯度:")
print(f"w1: {w1.grad}") # -41506.66796875
print(f"w2: {w2.grad}") # -1287.3333740234375
print(f"b: {b.grad}") # -394.0
print(f"更新参数:")
print(f"w1: {w1.item()}") # 416.0666809082031
print(f"w2: {w2}") # 13.873332977294922
print(f"b: {b}") # 3.93999981880188
36万+

被折叠的 条评论
为什么被折叠?



