Skip to content

手动实现链式法则

构造复合函数,手动逐层计算局部梯度并相乘,再用 sympy 验证。

学完本案例你将理解:反向传播的核心就是链式法则——每一层只算自己的局部梯度,最终梯度是各层梯度的乘积。


生活引入

多米诺骨牌的生产线

一个工厂有三道工序:原料 → 半成品 A → 半成品 B → 成品。你想知道「原料多用 1 公斤,最终成品多几个?」

你不需要从头推导整个流程的公式。每道工序只算自己的「局部比例」:半成品 A 增产 1 个 → 半成品 B 多几个?半成品 B 多 1 个 → 成品多几个?三个比例相乘就是答案。

这就是链式法则——每层只关心自己,最终影响 = 各层影响的乘积。


直观理解

构造一个三层复合函数:

x

u = g(x)
x^2+1

v = f(u)
3*sin(u)

y = h(v)
v^2

dydx=dydv_h(v)dvdu_f(u)dudx_g(x)

Python 动手实践

实例

python

import sympy as sp

import numpy as np

def g(x):    return x ** 2 + 1

def f(u):    return 3 * np.sin(u)

def g_prime(x): return 2 * x

def f_prime(u): return 3 * np.cos(u)

x0 = 1.5

# ---- 手动链式法则 ----

u0 = g(x0)

dy_du = f_prime(u0)    # 第2层局部梯度

du_dx = g_prime(x0)    # 第1层局部梯度

manual_grad = dy_du * du_dx

print("=" * 55)

print("RUNOOB 手动链式法则")

print(f"x0 = {x0}, u = g(x0) = {u0:.4f}")

print(f"dy/du = 3*cos(u) = {dy_du:.4f}")

print(f"du/dx = 2*x0     = {du_dx:.4f}")

print(f"链式相乘: dy/dx = {manual_grad:.4f}")

# ---- sympy 自动求导(标准答案) ----

x = sp.Symbol('x')

y_expr = 3 * sp.sin(x**2 + 1)

auto_grad = float(sp.diff(y_expr, x).subs(x, x0))

print(f"\nRUNOOB sympy 自动求导 = {auto_grad:.4f}")

print(f"两种方法一致: {np.isclose(manual_grad, auto_grad)}")

# ---- 拓展:三层复合 ----

def h(v):     return v ** 2

def h_prime(v): return 2 * v

v0 = f(u0)

dy_dv = h_prime(v0)

grad_3layer = dy_dv * dy_du * du_dx

print(f"\nRUNOOB 三层梯度传递:")

print(f"  第3层: {dy_dv:.4f} x 第2层: {dy_du:.4f} x 第1层: {du_dx:.4f} = {grad_3layer:.4f}")
python
=======================================================
RUNOOB 手动链式法则
x0 = 1.5, u = g(x0) = 3.2500
dy/du = 3*cos(u) = -2.9838
du/dx = 2*x0     = 3.0000
链式相乘: dy/dx = -8.9514

RUNOOB sympy 自动求导 = -8.9514
两种方法一致: True

RUNOOB 三层梯度传递:
  第3层: 6.5000 x 第2层: -2.9838 x 第1层: 3.0000 = -58.1841

AI 中的应用场景

场景与链式法则的关系
反向传播神经网络每层只计算自己的局部梯度,然后传给上一层
PyTorch autograd自动追踪每个操作构建计算图,反向时自动应用链式法则
梯度检查手动实现反向传播后,用数值梯度验证——就是本案的方法一 vs 方法二

AI 思考中...

可视化不同学习率的影响

抛硬币模拟贝叶斯更新

基于 VitePress 构建,部署于 GitHub Pages