Skip to content

E.3.1 微积分基础:导数、梯度与链式法则

前置知识:本篇不需要微积分基础,但建议先读完附录导读中的"两状态贯穿例子"和E.1.1 向量与矩阵


函数、目标和变化率

强化学习的核心任务是优化——调整策略参数让平均回报越来越高。前几篇附录讲过的向量、矩阵和贝尔曼方程告诉我们"当前策略有多好",但没说"怎么让它变得更好"。要回答这个问题,就需要知道:参数变一点,目标函数跟着变多少。这正是微积分要解决的问题。

想象你在调节收音机的旋钮寻找某个电台。旋钮转到不同位置,收到的信号清晰度不一样。微积分做的事情类似:它研究”一个量变化时,另一个量跟着怎么变”。在强化学习中,这个”旋钮”就是策略参数 θ\theta,而”信号清晰度”就是目标函数 J(θ)J(\theta)

目标函数可以理解成一个输入输出关系:

θJ(θ).\theta \longmapsto J(\theta).

如果 J(θ)J(\theta) 表示平均回报,那么训练就是在寻找让 J(θ)J(\theta) 更大的那组参数。导数和梯度回答的是一个很朴素的问题:现在站在这里,往哪个方向走,目标会上升最快?

搞懂了这一点,就会发现微积分不是一堆孤立的公式,而是优化算法赖以运转的基础语言。


从一维函数看导数

刚才说的"往哪个方向走"需要更精确的描述工具。这个工具就是导数。我们先用只有一个参数的简单函数来感受它。

J(θ)=(θ0.8)2+1.J(\theta)=-(\theta-0.8)^2+1.

可以把 θ\theta 理解成一个非常简化的策略参数。例如 θ=0.2\theta=0.2 表示选择 right 的概率较小,θ=0.8\theta=0.8 表示选择 right 的概率较大。

这个函数在 θ=0.8\theta=0.8 时最大。我们先不看图,只看几个数字:

θ\thetaJ(θ)J(\theta)
0.20.20.640.64
0.50.50.910.91
0.80.81.001.00
1.01.00.960.96

0.20.20.50.5,目标变大;从 0.80.81.01.0,目标变小。导数就是在描述这种现象:当前位置附近,函数值随着参数变化的速度和方向。

对这个函数求导,得到的结果记作 J(θ)J'(\theta)(读作”J prime of theta”,撇号表示”导数”):

J(θ)=2(θ0.8).J'(\theta)=-2(\theta-0.8).

θ=0.2\theta=0.2 时:

J(0.2)=1.2.J'(0.2)=1.2.

导数为正,说明往右调会让目标上升。在 θ=1.0\theta=1.0 时:

J(1.0)=0.4.J'(1.0)=-0.4.

导数为负,说明往左调会让目标上升。


梯度上升与梯度下降

知道了方向,下一步自然是"顺着方向走"。如果目标是最大化回报,就用梯度上升(gradient ascent):

θθ+αJ(θ).\theta \leftarrow \theta + \alpha J'(\theta).

θ=0.2\theta=0.2 开始,学习率取 α=0.1\alpha=0.1

θ0.2+0.1×1.2=0.32.\theta \leftarrow 0.2 + 0.1\times1.2 = 0.32.

再算一次导数:

J(0.32)=2(0.320.8)=0.96.J'(0.32)=-2(0.32-0.8)=0.96.

继续更新:

θ0.32+0.1×0.96=0.416.\theta \leftarrow 0.32 + 0.1\times0.96 = 0.416.

参数一步步靠近 0.80.8。每一步都沿着导数指的方向走一小步,这就是梯度上升的核心逻辑。

反过来,如果目标是最小化某个损失函数 L(θ)L(\theta),就把加号改成减号,叫做梯度下降(gradient descent):

θθαL(θ).\theta \leftarrow \theta - \alpha L'(\theta).

深度学习里常说的”反向传播 + 优化器”,核心就是反复做这件事:计算梯度,然后更新参数。


从导数到梯度:参数不止一个时怎么办

一维的导数好理解,但真实模型通常有几十万甚至上亿个参数。好在这个概念可以直接推广。假设目标函数有两个参数:

J(θ1,θ2)=(θ11)2(θ22)2+5.J(\theta_1,\theta_2)=-(\theta_1-1)^2-(\theta_2-2)^2+5.

它在 (1,2)(1,2) 处最大。对每个参数分别求导,把结果排成一个向量,就得到梯度(gradient)。符号 \nabla(读作"nabla")表示"把所有偏导数收集到一起":

J(θ1,θ2)=[2(θ11)2(θ22)].\nabla J(\theta_1,\theta_2)= \begin{bmatrix} -2(\theta_1-1) \\ -2(\theta_2-2) \end{bmatrix}.

如果当前参数是 (0,0)(0,0),梯度是:

J(0,0)=[24].\nabla J(0,0)= \begin{bmatrix} 2 \\ 4 \end{bmatrix}.

这表示:θ1\theta_1 应该增加,θ2\theta_2 也应该增加,而且 θ2\theta_2 增加得更快。梯度就是这样一个"方向盘",同时告诉每个参数该往哪动。学习率取 0.10.1,一次梯度上升后:

[θ1θ2][00]+0.1[24]=[0.20.4].\begin{bmatrix} \theta_1 \\ \theta_2 \end{bmatrix} \leftarrow \begin{bmatrix} 0 \\ 0 \end{bmatrix} +0.1 \begin{bmatrix} 2 \\ 4 \end{bmatrix} = \begin{bmatrix} 0.2 \\ 0.4 \end{bmatrix}.

梯度这个概念不限于两个参数。神经网络有成千上万个参数,梯度就是一个同样维度的向量,告诉每个参数应该怎么动。


链式法则:信号如何在层与层之间传递

到目前为止,我们讨论的都是"直接对参数求导"。但神经网络是很多函数一层层复合起来的——输入经过第一层变换,结果再传给第二层,以此类推,最后才输出损失。链式法则(chain rule)就是处理这种复合结构的工具:它告诉我们,外层的变化如何通过中间变量一步步传到内层参数。

看一个具体例子:

y=3θ,L=(y6)2.y = 3\theta, \qquad L=(y-6)^2.

如果 θ=1\theta=1,那么 y=3y=3,损失是:

L=(36)2=9.L=(3-6)^2=9.

我们想知道 θ\theta 变一点,LL 怎么变。当然可以直接把 y=3θy=3\theta 代入 LL 再求导:

L=(3θ6)2.L=(3\theta-6)^2.

求导得到:

dLdθ=2(3θ6)×3.\frac{dL}{d\theta}=2(3\theta-6)\times3.

θ=1\theta=1 时:

dLdθ=2(36)×3=18.\frac{dL}{d\theta}=2(3-6)\times3=-18.

这里的 2(3θ6)2(3\theta-6) 是损失对 yy 的导数(记作 dLdy\frac{dL}{dy}),33yyθ\theta 的导数(记作 dydθ\frac{dy}{d\theta})。链式法则把它们乘起来:

dLdθ=dLdydydθ.\frac{dL}{d\theta}=\frac{dL}{dy}\cdot\frac{dy}{d\theta}.

用文字来说就是:"θ\theta 影响 yyyy 影响 LL,所以 θ\thetaLL 的影响等于这两段影响相乘。"反向传播(backpropagation)就是在大规模神经网络里高效地做这件事——从损失开始,沿着计算图往回传,一层一层地应用链式法则。


偏导数:只动一个旋钮,其他不动

到目前为止我们用的导数符号都是 dd,对应只有一个变量的情形。当函数有多个变量时,我们需要一个新的符号 \partial(读作"partial"):它表示"只对其中一个变量求导,把其余变量当成常数"。这就是偏导数(partial derivative)。还是用刚才那个两参数的目标函数:

J(θ1,θ2)=(θ11)2(θ22)2+5.J(\theta_1,\theta_2)=-(\theta_1-1)^2-(\theta_2-2)^2+5.

它有两个参数。我们可以分别问:固定 θ2\theta_2 不动时,θ1\theta_1 怎么影响目标?反过来,固定 θ1\theta_1 时呢?这就是偏导数做的事。

θ1\theta_1 的偏导是:

Jθ1=2(θ11).\frac{\partial J}{\partial \theta_1}=-2(\theta_1-1).

θ2\theta_2 的偏导是:

Jθ2=2(θ22).\frac{\partial J}{\partial \theta_2}=-2(\theta_2-2).

把所有偏导数排成向量,就得到梯度:

θJ=[Jθ1Jθ2].\nabla_\theta J= \begin{bmatrix} \frac{\partial J}{\partial \theta_1} \\ \frac{\partial J}{\partial \theta_2} \end{bmatrix}.

(θ1,θ2)=(0,0)(\theta_1, \theta_2)=(0,0) 处:

θJ(0,0)=[24].\nabla_\theta J(0,0)= \begin{bmatrix} 2 \\ 4 \end{bmatrix}.

这表示两个参数都应该增大,而且第二个参数的上升方向更强。神经网络的梯度也是同样道理,只是参数数量从 2 个变成了几百万甚至更多。


学习率:每一步走多远

梯度告诉我们方向,但走多远是另一回事。学习率 α\alpha 就是控制步长大小的旋钮。

如果当前参数是

θ=[00],J=[24],\theta= \begin{bmatrix} 0 \\ 0 \end{bmatrix}, \qquad \nabla J= \begin{bmatrix} 2 \\ 4 \end{bmatrix},

学习率取 α=0.1\alpha=0.1,一次梯度上升是:

θ[00]+0.1[24]=[0.20.4].\theta\leftarrow \begin{bmatrix} 0 \\ 0 \end{bmatrix} +0.1 \begin{bmatrix} 2 \\ 4 \end{bmatrix} = \begin{bmatrix} 0.2 \\ 0.4 \end{bmatrix}.

如果学习率过小,训练会很慢——每次只挪一点点;如果学习率过大,参数可能越过最优点甚至发散——步子太大直接跳过了山顶。强化学习的梯度本身就带有较多噪声,所以学习率的选择格外敏感,梯度裁剪、Adam 优化器、PPO 裁剪这些技巧本质上都在解决步长稳定性的问题。

常见误区

学习率不是"越大学习越快"。过大的学习率会让参数在最优点附近震荡甚至发散。实践中常用 10310^{-3}3×1043\times10^{-4} 这样的小值,再配合学习率衰减或自适应优化器。


从数学公式到代码中的反向传播

前面几节我们在纸上推导了导数、梯度和链式法则。在实际写代码时,不会手算每个参数的偏导数,而是交给自动微分(autodiff)系统来完成。自动微分依赖的正是链式法则。

例如一个简单计算图:

θy=3θL=(y6)2.\theta \to y=3\theta \to L=(y-6)^2.

反向传播从最后的损失开始,先算 dLdy\frac{dL}{dy},再乘上 dydθ\frac{dy}{d\theta},得到 dLdθ\frac{dL}{d\theta}

这和深度网络一样:每一层只需要知道本层的局部导数,整条链路的梯度就能通过链式法则一路传回去。策略网络、价值网络和奖励模型的训练,全部依赖这套机制。


小结

本篇建立了微积分的五个核心工具:

概念作用RL 中的角色
导数描述函数在一点的变化方向和速度判断参数该往哪调
梯度多参数时所有偏导数组成的向量同时告诉每个参数该往哪动
链式法则处理复合函数的求导反向传播的理论基础
偏导数只对一个变量求导,其余当作常数神经网络中逐参数计算梯度
学习率控制每次参数更新的步长平衡训练速度和稳定性

这些工具组合起来就是"算梯度、走一步"的完整循环。下一篇把这些数学工具直接用到策略优化上——看看策略梯度是怎么从"好动作概率上升"这个直觉推导出来的。

下一篇E.3.2 策略梯度与优势函数 —— 把梯度用到策略优化上。

Built for reusable bilingual course delivery