想象你走进一家糖果工厂,看到一条组装生产线:第一站给奶糖剥糖纸,第二站裹上巧克力脆皮,第三站压出漂亮花纹。整条线串起来,一端的原料糖块,变成了另一端的成品花糖。每站只干自己那道工序,但成品的任何变化,都会由这道工序接力放大或缩小。 现在质检员说:“成品甜度不够,请调整一下。”你会怎么做?你不会从头到尾重设每台机器,而是从最后一站开始,往回逐站查:最后一道工序每变一点,成品跟着变多少?上一道工序每变一点,最后一道工序的输入又变多少?把这一连串的“变化率”乘起来,你就知道原料端该调几下。这就是链式法则——把复合函数这条“流水线”的总变化率,拆成每个工作站局部变化率的乘积。它不仅是微积分的核心工具,更是深度学习里“反向传播”算法的数学灵魂。
掌握链式法则,你就拿到了理解神经网络训练机制的钥匙。面试官问“梯度怎么回传”时,你能从数学本质上讲透,而不是只会调框架。
可视化演示
展示复合函数链式法则公式、计算图前向反向传播、多层嵌套逐层求导及反向传播梯度消失,通过多模式交互理解核心数学原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
链式法则基本公式 复合函数y=f(g(x))需逐层求导 外层对中间变量u求导f(u) 内层对x求导g(x) dy/dx = f(u) × g(x) 链式法则是复合函数求导核心工具
复合函数辨识
糖果流水线的第一步不是开动机器,而是看清这条线到底有几道工序、每道工序的输入输出是什么。剥糖纸的机器吃进去的是糖块,吐出来的是裸糖;裹巧克力的机器吃进去的是裸糖,吐出来的是脆皮糖。它们是前后串联的,后一道机器的输入,恰好是前一道机器的输出。两个机器叠在一起,就形成了“嵌套”的完整生产线。
数学里的复合函数,就是这种嵌套的流水线。设内层工序为 \(u = g(x)\),外层工序为 \(y = f(u)\),那么从原料 \(x\) 到成品 \(y\) 的直接描述是 \(y = f(g(x))\)。学习链式法则的第一课,就是学会辨认这种结构:看到一个复杂函数,先问自己——哪部分是“先发生的操作”,哪部分是“后发生的操作”?剥掉外层,剩下的就是内层;层层剥开,结构就清楚了。
1. 内层函数:\(g(x)\) 先作用于输入 \(x\),如同流水线第一站处理原料。
2. 外层函数:\(f\) 再作用于中间量 \(u\),如同第二站处理半成品。
3. 嵌套表示:将两步合并,写成 \(f \circ g\),读作“\(f\) 复合 \(g\)”。
看清水流线的工序结构,就成功了一半。很多同学一上来就套公式求导,结果把内层当外层,求出来的导数自然是错的。先花十秒钟把“哪层在内、哪层在外”标出来,后面的计算就顺畅了。就像车间主任拿到新糖型,先是画工序图,而不是急着调机器。
法则核心公式
现在质检员要求:改变原料糖的甜度 \(x\),让成品甜度 \(y\) 变化得更多。于是你要到每一道工序去问同样一个问题:“我的输入变一点点,你的输出跟着变多少?”这个比例,数学上就叫导数。剥糖纸这一站,输出 \(u\) 对输入 \(x\) 的变化率是 \(\frac{du}{dx}\);裹巧克力这一站,输出 \(y\) 对输入 \(u\) 的变化率是 \(\frac{dy}{du}\)。
如果两站串联,原料小幅变化 \(\mathrm{d}x\),先被第一站放大成 \(\mathrm{d}u = \frac{du}{dx}\mathrm{d}x\),再被第二站放大成 \(\mathrm{d}y = \frac{dy}{du}\mathrm{d}u\)。把两个放大倍数乘起来,就是整条流水线的总放大率。这就是链式法则的核心直觉:变化率沿着流水线逐站相乘。
1. 中间变量:\(u = g(x)\) 是内外层之间的桥梁,相当于第一站的输出。
2. 外层求导:\(y\) 对 \(u\) 求导,得到第二站的局部变化率。
3. 内层求导:\(u\) 对 \(x\) 求导,得到第一站的局部变化率。
4. 相乘合并:两个局部变化率相乘,得到总变化率。
这个式子的莱布尼茨记号特别优雅:左边是终点 \(y\) 对起点 \(x\) 的导数,右边把中间变量 \(u\) 的微分在分子分母各出现一次,像约分一样“消掉”了。它暗示我们,无论中间有几站,都可以一层层写下去、乘起来。这套记号本身就是为流水线设计的,读它就像读一张车间布局图。
单层嵌套求导
光看公式还不够,直接上手干一道最简单的活:求 \(y = (3x+1)^5\) 的导数。这就像流水线上只有两道工序——第一站把糖块称重成 \(u = 3x+1\),第二站把糖块放入模具压成五次方。现在要问:原料 \(x\) 变化一丁点,成品 \(y\) 变化多少?
先找内外层:外层是“五次方”机器,内层是“乘三加一”机器。外层机器对输入的局部变化率是“五次方”的导数,即 \(5u^4\);内层机器对原料的局部变化率是“乘三加一”的导数,即 \(3\)。按照流水线法则,把两个放大倍数相乘,就得到总变化率。
1. 设中间变量:令 \(u = 3x+1\),内层是线性变换,如同第一站机器。
2. 外层求导:\(y = u^5\) 对 \(u\) 求导,幂函数求导规则生效。
3. 内层求导:\(u = 3x+1\) 对 \(x\) 求导,常数项消失,系数留下。
4. 结果还原:把中间变量换回 \(3x+1\),两部分相乘。
这里最容易犯的错是只写 \(5(3x+1)^4\),把内层的系数 \(3\) 弄丢了。想象一下:如果第一站机器每转一周能处理三颗糖,而你只算了压模机的放大率,那整条线的产能就低估了三分之二。在流水线上,每一站的放大率都不能漏;在链式法则里,每一层的导数都不能缺。
多层嵌套求导
当流水线从两站变成四站、五站时,链式法则的威力才真正显现。比如求 \(y = \sin\left((x^2+1)^2\right)\) 的导数。这条流水线的工序是:第一站做 \(x^2+1\),第二站把它平方,第三站取正弦。仿佛一个多层洋葱,剥开一层还有一层。
处理这种多层嵌套的秘诀是“由外向内逐层剥”:先把最外层的“正弦”当成一个函数,把里面整块 \((x^2+1)^2\) 视为它的输入,求导得到 \(\cos\left((x^2+1)^2\right)\);接着进入下一层,对 \((x^2+1)^2\) 求导,用链式法则得 \(2(x^2+1) \cdot 2x\);最后把每一层的结果乘起来。每剥一层,就多乘一个因子。
1. 剥最外层:外层是 \(\sin(\cdot)\),求导后变 \(\cos(\cdot)\),内部保持不动。
2. 剥第二层:对 \((x^2+1)^2\) 求导,幂函数规则加内层再导。
3. 剥第三层:对 \(x^2+1\) 求导,只剩 \(2x\)。
4. 累乘全部因子:三层的局部导数依次相乘,得到最终答案。
洋葱剥到最里层时,手上已经积了一串因子。只要每层都问一句“我的输入是什么、怎么变”,然后认真相乘,再复杂的嵌套也能拆干净。要特别提醒的是,千万别认为剥到第二层就结束了,最里面的 \(2x\) 是这条流水线的源头,漏掉它,整条线的产能就又算错了一截。
计算图直观
面对五层甚至十层的流水线,靠脑子记住每道工序的关系太累了。工程师的做法是画一张车间流程图:每个圆代表一台机器(一个数学函数),每条箭头代表半成品流向(数据传递)。这张图在深度学习里有个正式名字——计算图。
在计算图上,导数的传播变得非常直观。每个节点对它直接输入的导数,叫局部梯度;反向传播时,上游传来的梯度乘以当前节点的局部梯度,就是继续往前传的梯度。这就好比质检员在流水线末端给出一个“误差量级”,它逆着箭头流动,每经过一台机器就乘以这台机器的放大率,越往源头走,数值就越能反映“该调整哪台机器、调多少”。
1. 上游梯度:\(\frac{\partial L}{\partial y}\) 是损失 \(L\) 对节点输出 \(y\) 的梯度,由下游传回。
2. 局部梯度:\(\frac{\partial y}{\partial x}\) 是节点输出对输入的导数,只由当前机器的表达式决定。
3. 梯度合成:上游梯度乘局部梯度,得到继续往上游传的梯度。
看,这张图上的每个节点只需要关心自己“输入怎么变、输出怎么变”,不需要知道整条线的全局细节,然后靠着相邻节点之间的接力,梯度就能一路传到最前端。这种“各管一段、全局联通”的思想,正是现代深度学习框架自动求导的底层设计。可以说,链式法则给了工程师一张可以照着施工的流水线图纸。
反向传播应用
现在把流水线放大到极致——一个神经网络。输入是数据,隐藏层的每个神经元是一道工序,输出是预测值,损失函数是最终的质检报告。训练网络的基本目标就是:让质检报告的误差尽量小,于是要沿着流水线逆流而上,算每个旋钮(权重参数)该往哪个方向拧、拧多大。这个逆流而上的算法,就是反向传播,它本质上是链式法则的工程化应用。
假设某条通路是:输入 \(x\) 经过权重 \(w\) 得到 \(z = wx + b\),再经过激活函数得到 \(a\),最后参与损失 \(L\) 的计算。我们要问的是:权重 \(w\) 变一点,损失 \(L\) 变多少?答案是沿着通路把三段变化率乘起来。这跟糖果流水线里问“第一站机器调一下,成品变化多少”是同一个问题,只是工序变成了矩阵乘法和激活函数。
1. 损失对激活输出求导:算出最终质检误差对激活值的敏感度。
2. 激活函数局部梯度:激活输出 \(a\) 对加权和 \(z\) 的导数,如 Sigmoid 或 ReLU 的导数。
3. 加权和对权重求导:\(z = wx + b\) 对 \(w\) 的导数正好是输入 \(x\)。
4. 三项相乘:三段局部变化率相乘,得到权重 \(w\) 的最终梯度。
得到梯度后,优化器让权重沿着梯度的反方向迈一小步:\(w \leftarrow w - \eta \frac{\partial L}{\partial w}\),其中 \(\eta\) 是学习率。整条流水线每周转一次,就是一轮训练。所以,链式法则不仅是一道考试题,它根本就是深度学习引擎的燃油管道——每一滴梯度信号,都是沿着这条链条从最终误差倒灌回每个权重旋钮的。
AI 应用场景
深度学习框架的自动求导引擎
阶段:模型训练(反向传播)。
解决的问题:手写神经网络时,每层权重都要手动推导梯度公式,层数一多极易出错。PyTorch、TensorFlow 等框架利用计算图和链式法则,自动把损失对每个参数的梯度计算出来,让研究者只需关心前向逻辑。
具体案例:你定义了一个三层全连接网络,调用 loss.backward() 时,框架自动从损失节点沿计算图回传梯度,每一层的权重参数都拿到各自的梯度值。这个过程就是可视化演示中红色小球走过的路径,只是节点更多、维度更高。
物理仿真中的敏感性分析
阶段:物理信息神经网络(PINN)或机器人控制。
解决的问题:机器人关节角度变化时,末端执行器位置变化多少?这类复合运动链的求导,传统上靠手推雅可比矩阵,复杂且易错。用链式法则的自动微分,可以精确得到每一个关节角度对末端位置的梯度。
具体案例:机械臂由三个旋转关节串联组成,末端坐标是关节角度的复合函数。工程师用自动微分算出末端位置对每个关节角度的偏导,从而规划出平滑的轨迹。就像在糖果流水线上精确知道每个旋钮对成品形状的影响。
金融衍生品定价的希腊值计算
阶段:量化建模与风险度量。
解决的问题:期权价格是标的价格、波动率、时间等多个变量的复合函数,银行需要计算 Delta、Gamma 等敏感度指标。用链式法则从定价公式逐层求导,比数值差分更快更准。
具体案例:一个包含分红、利率调整的期权定价模型,价格是若干中间变量的嵌套组合。量化团队用自动微分计算出每个风险因子的敏感度,就像沿着定价流水线逐站测算变化率,为风控提供实时数据。
Python 演示
def forward(x): u = 3 * x + 1 # 内层工序 y = u ** 5 # 外层工序 return y def chain_rule(x): u = 3 * x + 1 dy_du = 5 * (u ** 4) # 外层局部梯度 du_dx = 3 # 内层局部梯度 dy_dx = dy_du * du_dx # 链式法则相乘 return dy_dx def numerical_derivative(f, x, h=1e-6): # 中心差分做数值验证 return (f(x + h) - f(x - h)) / (2 * h) def backward_demo(x, target): w = 2.0 # 初始权重 b = 1.0 # 初始偏置 pred = w * x + b # 前向传播 loss = (pred - target) ** 2 dloss_dpred = 2 * (pred - target) # 损失局部梯度 dpred_dw = x # 加权和对权重的梯度 dw = dloss_dpred * dpred_dw # 链式法则求权重梯度 return loss, dw, pred if __name__ == "__main__": x = 2.0 analytic = chain_rule(x) numeric = numerical_derivative(forward, x) print("解析链式法则:", analytic) print("数值微分验证:", numeric) loss, dw, pred = backward_demo(x=2.0, target=100.0) print("预测值:", pred) print("损失:", loss) print("权重梯度:", dw)
u = 3 * x + 1定义内层工序,等价于流水线的第一站。dy_du = 5 * (u ** 4)外层求导,得到第二站的局部放大率。dy_dx = dy_du * du_dx两个局部梯度相乘,正是链式法则的核心。(f(x + h) - f(x - h)) / (2 * h)中心差分,用数值方式近似导数,用来验证解析解。dloss_dpred = 2 * (pred - target)损失函数对预测输出的局部梯度。dw = dloss_dpred * dpred_dw把损失梯度与输入信号相乘,就是权重梯度。
常见误区
误区求 \(y=(3x+1)^5\) 的导数时,直接写下 \(5(3x+1)^4\),觉得幂函数求导完就结束了,没意识到里面还有个 \(3x+1\) 需要继续求导。
正解链式法则说得很清楚:外层导必须乘内层导。流水线上第一站的放大率漏掉了,总产能一定算错。正确结果是 \(5(3x+1)^4 \times 3\)。可以这样自我检查:对内层做个微小的数值变化,用差分估算一下,看自己的解析答案是否吻合。
为何常见:初学时习惯了“求导是对整个表达式操作”的单一视角,忽视了函数内部还有变量在变化。
误区有的同学记住了“外层导加上内层导”,把 \(dy/dx = dy/du + du/dx\) 当成链式法则,觉得变化率可以叠加。
正解复合函数是串联结构,不是并联。串联流水线的总放大率是各站放大率的乘积,而不是相加。加法对应的是“两条独立路径汇合”的场景(如多变量函数的偏导),而这在链式法则里并不适用。
为何常见:高中物理里学过的“合速度等于各速度之和”等加法直觉被错误迁移到了这个场景。
误区遇到 \(y=\sin((x^2+1)^2)\),写到 \(\cos((x^2+1)^2)\times 2(x^2+1)\) 就停了,觉得最里面只是个二次多项式,不用再导。
正解只要最里层还包含变量 \(x\),就必须继续求导,直到最内层的自变量是真正独立的输入变量为止。这道题还有第三层 \(x^2+1\) 的导数 \(2x\),所以完整答案有三个因子。可以想象剥洋葱,只要里面还有洋葱瓣,就要继续剥。
为何常见:人的注意力资源有限,套了多层括号后容易在视觉上忽略最内层的小结构。
误区在计算图里做反向传播时,只计算当前节点的局部梯度就直接回传,没有把它乘以上游传来的梯度,导致梯度值越来越小或直接错误。
正解反向传播的精髓是“梯度沿边相乘”。每个节点的回传梯度 = 上游梯度 × 局部梯度。上游梯度是下游所有通路传上来的累积贡献,丢掉它等于切断了流水线的下游反馈,机器调整必然失真。
为何常见:习惯了一次性求导的思维,忽略了反向传播是逐步接力而非独立计算。
面试题
Q1. 对复合函数 y=f(g(x)) 求导,链式法则说的是?
- A.外层导乘以内层导← 正确答案
- B.外层导加内层导
- C.外层导除以内层导
- D.外层导减以内层导
答案:A。复合函数是串联流水线,总变化率是各层局部变化率的乘积。A 选项正是“外层导乘内层导”,B、C、D 分别是加、除、减,都不符合串联系统的放大规律。
Q2. 设 y=(3x+1)^5,令 u=3x+1,则 dy/dx 等于?
- A.15 乘以 u 的四次方← 正确答案
- B.5 乘以 u 的四次方
- C.3 乘以 u 的五次方
- D.15 乘以 u 的三次方
答案:A。外层是五次幂,导数为 5u^4;内层 u=3x+1 对 x 求导为 3。两者相乘得 15u^4,选 A。B 漏了内层导数 3,C 把内层当成了外层,D 指数算错。
Q3. 链式法则的莱布尼茨记号形式是?
- A.dy/dx = dy/du + du/dx
- B.dy/dx = dy/du × du/dx← 正确答案
- C.dy/dx = dy/du ÷ du/dx
- D.dy/dx = du/dy × dx/du
答案:B。莱布尼茨记号把中间变量 u 的微分在分子分母各出现一次,相乘后“约分”得到 dy/dx,这对应 B 选项。A 是加法,C 是除法,D 把分子分母写反了。
Q4. 求 y=sin(x²) 的导数 dy/dx?
- A.cos(x²) 乘以 2x← 正确答案
- B.sin(x²) 乘以 2x
- C.cos(x²) 加上 2x
- D.cos(2x) 乘以 x²
答案:A。外层是正弦,导数为 cos(x²);内层是 x²,导数为 2x。两者相乘得 cos(x²)·2x。B 混淆了正弦与余弦,C 把乘法写成加法,D 对内层求导有误。
Q5. 多层嵌套 y=e^(x²+1) 求导时,正确的顺序是?
- A.先求 x²+1 再求 e^u
- B.先求 e^u 再求 x²+1← 正确答案
- C.先求 e 的导数再求 x²
- D.所有层同时求导
答案:B。链式法则强调由外向内逐层求导。先处理最外层指数函数,得到 e^(x²+1),再乘内层 x²+1 的导数 2x。由内向外或同时求导都会漏因子或搞乱顺序。
Q6. 关于计算图的反向传播,下列哪些说法正确?
- A.梯度由输出流向输入← 正确答案
- B.梯度由输入流向输出
- C.局部梯度沿途相乘← 正确答案
- D.局部梯度沿途相加
答案:AC。反向传播的方向与正向计算相反,从损失(输出端)逆流回输入,A 对 B 错。回传过程中每个节点的梯度等于上游梯度乘局部梯度,C 对 D 错。这就像红色小球逆着传送带走回原料端。
Q7. 计算图中“局部梯度”指的是什么?
- A.该边的输出对输入之导数← 正确答案
- B.该边的输入对输出之导数
- C.整体损失对该边输出之导数
- D.整体损失对输入之导数
答案:A。局部梯度只由当前节点函数本身决定,是输出对输入的导数,如 z=wx+b 对 w 的局部梯度是 x。C、D 描述的是“上游梯度”或“最终梯度”,不是局部量。
Q8. 已知 y=f(g(h(x))),则 dy/dx 的正确展开是?
- A.f'(g)·g'(h)·h'(x)← 正确答案
- B.f'(g)·g'(x)·h'(x)
- C.f'(x)·g'(x)·h'(x)
- D.f'(g)·g'(x)·h'(g)
答案:A。三层嵌套要写三个因子,每层的“输入”是下一层的输出。A 中 f' 以 g 为输入,g' 以 h 为输入,h' 以 x 为输入,完全对应由外向内逐层求导。B、C 搞错了各层的输入变量,D 最后一项写错。
Q9. 神经网络反向传播中,权重 w 的梯度由哪些量相乘得到?
- A.损失对输出的梯度← 正确答案
- B.激活函数局部梯度← 正确答案
- C.该层的输入信号← 正确答案
- D.训练用的学习率
答案:ABC。权重梯度的链式展开为:损失对激活输出梯度 × 激活函数对加权和的导数 × 加权和对权重的导数(即输入信号),A、B、C 都对。学习率是更新参数时的步长,不参与梯度本身的计算,D 错。
Q10. ReLU 函数 y=max(0,x),当 x>0 时其局部梯度为?
- A.恒等于 1← 正确答案
- B.恒等于 0
- C.等于输入 x
- D.等于负一
答案:A。ReLU 在 x>0 时是恒等映射 y=x,斜率为 1,所以局部梯度恒为 1;在 x<0 时斜率为 0。C 是把函数值当成了梯度,B、D 都不符合正区间的斜率。