Python 现代开发学习笔记

(六)导数、偏导与参数变化方向

为了看清一次更新,暂时只保留一个输入:x=2、实际值 y=5,计算式为 ŷ=wx+b\hat y=wx+b,初始 w=1、b=0。此时预测为 2,平方损失为 9。

1. 用小变化观察斜率

把函数值变化除以输入变化,可以得到这段上的平均变化率。让变化越来越小,就得到该位置的导数。例如 f(w)=w2f(w)=w^2:

f(w+h)−f(w)h=(w+h)2−w2h=2w+h. \frac{f(w+h)-f(w)}{h}=\frac{(w+h)^2-w^2}{h}=2w+h.

当 hh 趋近零时,剩下 f′(w)=2wf'(w)=2w。在 w=1 附近,向右增加一点会让平方值增加,导数为正。

2. 固定其他参数计算偏导

我们的损失依赖两个参数:L(w,b)=(2w+b−5)2L(w,b)=(2w+b-5)^2。计算对 w 的影响时,先把 b 固定;计算对 b 的影响时,先把 w 固定。这分别称为对 w、对 b 的偏导,记作 ∂L/∂w\partial L/\partial w、∂L/∂b\partial L/\partial b。

在初始位置,误差为 -3。w 增加 0.01,误差变为 -2.98,损失从 9 降到 8.8804;b 增加 0.01,损失降到 8.9401。因此当前位置对两个参数的变化率均为负,增加它们会先让损失下降。

# 项目文件:demos/manual_derivative.py
def loss(w, b):
    prediction = w * 2 + b
    return (prediction - 5) ** 2


epsilon = 0.0001
# 固定另一个参数,只让 w 或 b 各自发生一次很小的变化。
dw = (loss(1 + epsilon, 0) - loss(1 - epsilon, 0)) / (2 * epsilon)
db = (loss(1, epsilon) - loss(1, -epsilon)) / (2 * epsilon)
print("数值偏导", round(dw, 6), round(db, 6))
print("更新后损失", loss(1 - 0.05 * dw, 0 - 0.05 * db))

脚本用左右各一次微小变化近似偏导,得到 -12 与 -6。这可用于核对手算,但训练时会使用下一节的链式法则直接计算。

固定偏置时分别代入权重一点零一和零点九九,固定权重时改变偏置,对比损失变化并读出负向斜率

笔记正文与全部题解 · Ctrl / ⌘ K