07. 梯度与学习率
上一篇给模型准备了一张评分表:预测偏差越大,损失通常越高。可有了分数,还不知道两个参数该怎么调。把 w 增大一点会更好吗?一次改多少才合适?
可以先把参数想成旋钮。轻轻向一边试转,观察分数是上升还是下降,再决定下一次怎么转。梯度把这种局部变化信息写成数值,学习率则控制根据这些信息调整多大幅度。本篇先只留一个旋钮,把每一步算清楚,再回到两个参数的运费模型。
配套讲解
朝着能降低损失的方向调整,为什么有时反而错得更多?视频中的红点会展示一次走得合适、一次走过头的区别。也可以阅读讲解逐字稿,再用下面的数字和交互实验检查自己的判断。
从一个参数看局部变化
为了先看清一个旋钮的作用,暂时换成一条便于手算的教学样本:输入 x=2,目标 y=4。固定偏置 b=0,只调整 w,预测就是 ŷ=wx。这条样本专门用于本节,稍后再回到三条运费记录。
沿用上一篇的规则,把“预测减目标”平方,再取一半:
text
L = 0.5 × (wx-y)²
= 0.5 × (2w-4)²L 是损失,wx 是预测,y 是目标。平方把正负偏差变成非负分数,0.5 统一把分数缩小一半,便于后面求变化率;它不改变哪组参数得分最低。当 w=1 时,预测为 2,残差为 -2,损失是 0.5×(-2)²=2。
如果暂时不知道往哪边改,可以各试一点:
| 参数 w | 预测 2w | 损失 L |
|---|---|---|
| 0.99 | 1.98 | 2.0402 |
| 1.00 | 2.00 | 2.0000 |
| 1.01 | 2.02 | 1.9602 |
向右增加一点 w,损失下降了。用“损失变化量 ÷ 参数变化量”算这段的平均变化率,得到 (1.9602-2)/0.01=-3.98。如果试探幅度越来越小,这个比值会越来越接近 -4。在一个位置上,这种极小改动对应的变化率称为导数。
导数写作 dL/dw,读作“L 对 w 的导数”。可以把它看成当前位置的坡度:横向是 w,高度是损失,负数说明向右稍走一点会下坡,绝对值表示局部有多陡。只有一个参数时,梯度就是这个导数。它描述当前位置附近的变化,不是在给新参数指定数值。
从损失公式怎样算出 -4?
先把残差记成 r=wx-y,损失就是 0.5r²。有两段变化需要接起来:
- 残差
r改变时,平方的变化率是2r,乘上0.5后变为r,这里的 2 正好被约掉。 - 参数
w改变时,预测wx的变化率是x,目标y固定,所以残差的变化率也是x。
平方的变化率为什么是 2r?把残差从 r 改成 r+h,h 表示一个小改动。平方的差是 (r+h)²-r²=2rh+h²,除以改动量 h,得到 2r+h。当 h 越来越接近 0,这个比值就越来越接近 2r。这也是乘 0.5 能约掉系数 2 的来由。
把两段变化率相乘,就得到:
text
dL/dw = (wx-y) × x
= (1×2-4) × 2
= -4这种把“参数影响残差、残差影响损失”两段接起来的求导方法,叫链式法则。现在还没学过微积分也没关系,上表已经能验证方向和近似数值;后面的多层网络会继续展开这条计算链。
知道方向之后,一次改多少
有了坡度,还要定这次调整的幅度。这里采用的规则是:
text
新参数 = 原参数 - 学习率 × 当前梯度学习率是事先选定的正数,像旋钮调整的灵敏度。乘上梯度后,才得到本次实际改动量。减号负责选择下降方向:梯度为负,就把参数增大;梯度为正,就把参数减小。这个反复计算梯度、沿相反方向更新的方法叫梯度下降。
学习率取 0.1,改动量为 -0.1×(-4)=+0.4,所以新参数 w'=1.4。这里撇号表示“更新后的”,不是另一个要求导的符号。新预测是 1.4×2=2.8,再按原来的规则评分,得到 0.5×(2.8-4)²=0.72,确实比 2 小。
如果把学习率改为 1,这次就会增加 4,得到 w'=5。新预测为 10,损失升至 0.5×(10-4)²=18。方向起初正确,却一步越过了最低处 w=2,走得太远。
这就是为什么“知道下坡方向”还不够。梯度描述脚边的坡,学习率影响下一步落点;落点好不好,要重新计算损失。0.1 只是在这个例子里合适,换一种模型或数据尺度,还需要重新选择。
两个参数形成损失曲面
只调一个参数时,损失是一条曲线。现在回到运费模型 ŷ=wx+b 与三条记录 (1,3)、(2,5)、(3,7),两个旋钮都可以动。每选一组 w,b,算出三条记录的损失再取平均,就能给这组参数确定一个高度。把所有位置连起来,得到一张损失曲面。
这里横向两个轴放的是参数 w,b,不是重量和运费;高度是错误得分。可以把它看成参数的地形图:希望找到较低的位置。沿 w 方向和沿 b 方向的坡度各算一个数,合在一起才是两个参数的梯度。
∂L/∂w 表示“暂时固定 b,只改变 w 时的变化率”,∂L/∂b 则反过来。这种只看一个方向的导数叫偏导数;符号换成 ∂,是提醒我们还有其他参数暂时没动。
默认的等高线像地图上的海拔线:同一条线上各组参数的损失相同,从上方看也能辨认高低。靠近 (2,1) 的区域更低;代入 预测=2×重量+1,三条记录都预测正确,因此这里损失为零。选择“三维曲面”可以侧着看同一片地形,两种视图展示的是同一个损失函数。
w:重量系数,范围 -1 至 4b:固定费用,范围 -2 至 4L:损失,高度为线性比例
w
b
第 0 次更新
- 当前损失 L
- 13.8333
- 梯度 ∂L/∂w
- -11.3333
- 梯度 ∂L/∂b
- -5
红点是当前参数;单步执行后,参数、损失和轨迹一起更新。
先保持学习率 0.1,执行一次更新。初始 w=0,b=0,三条预测都是 0,残差分别为 -3,-5,-7。损失是 (4.5+12.5+24.5)/3=83/6≈13.8333。
每条残差乘对应重量,再取平均,得到 w 方向的坡度 (-3×1-5×2-7×3)/3=-34/3;每条残差直接取平均,得到 b 方向的坡度 (-3-5-7)/3=-5。后者没有再乘重量,因为 b 增加 1 时,每条预测都直接增加 1。
按同一条更新规则,w'=0-0.1×(-34/3)≈1.1333,b'=0-0.1×(-5)=0.5。重新预测并评分,损失约为 2.7443。交互中的红点移动到这组参数,蓝线留下已经走过的路径。
复位后将学习率改为 1。第一次计算出的参数会超出当前画布范围,实验会显示真实候选值并停止。此时只是图画不下这个位置,可以用下一篇的脚本继续观察:后续损失是否越来越大?
梯度和学习率分别负责什么
计算梯度像测量当前坡度,按规则修改参数才是迈步。负责执行更新规则的算法称为优化器;眼前采用的是最基本的梯度下降规则,后面还会比较会记录过去变化的更新方法。
多层网络计算很多,通常从最终误差往回计算每层参数的梯度,这个过程称为反向传播。它解决“坡度是多少”,优化器解决“参数怎样改”。本篇参数少,可以直接算;等进入多层网络,再看误差怎样一层层往回传。
当前地形像一个碗,最低处只有一片。复杂模型可能有许多高低起伏,局部朝下走未必就能到整张地形的最低处。先掌握这里可核对的一步,再讨论复杂模型中的训练经验。
梯度告诉程序局部变化率,学习率决定沿更新方向移动的尺度。判断更新是否有效,要重新计算损失,而不是只看方向。下一篇把这些步骤写成可以保存结果、独立重载的程序:08. 写出第一次训练循环。
