偏导数 -- 多变量函数逐个求导
之前的导数针对一元函数 f(x)。神经网络有数百万参数,需要对每个参数求导。
偏导数 = 多变量函数中,只对其中一个变量求导,其余视为常数。
概念解析
之前我们只处理了一元函数 f(x) 的导数。但真实世界中,事物的结果通常由 多个因素 共同决定。
比如:房价取决于面积、地段、楼层、房龄等多个因素。我们想知道「面积增加 1 平方米,房价涨多少」,就需要把其他因素固定住。
这就是偏导数的核心思想:一次只改变一个变量,观察它对结果的影响,其余变量暂时冻结。
对于 $ f(x, y) = x^2 + xy + y^2 $:
- 对 x 求偏导(y 当常数,y² 当常数后导数为 0,xy 中 y 当常数,x 的导数为 1):$ \frac{\partial f}{\partial x} = 2x + y + 0 $
- 对 y 求偏导(x 当常数,同理):$ \frac{\partial f}{\partial y} = 0 + x + 2y $
记号 $ \partial $(读作"round d"或"partial")表示偏导数,区别于普通导数中的 d。
二阶偏导数
对偏导数再求偏导,得到二阶偏导数:
- $ \frac{\partial^2 f}{\partial x^2} $:对 x 求偏导后,再对 x 求偏导(衡量 x 方向上的曲率)
- $ \frac{\partial^2 f}{\partial x \partial y} $:先对 x 求偏导,再对 y 求偏导(交叉偏导,衡量两变量的交互影响)
神经网络训练的本质:对损失函数关于
每一个参数求偏导,然后沿负梯度方向更新。一个百万参数的模型,梯度就是一百万个偏导数的向量。
生活例子
一锅汤的味道
汤的味道取决于盐、酱油、醋等多种调料。你想知道「多放一勺盐,味道变化多大」?
把其他调料用量固定,只看盐的影响——这就是偏导数的思维:一次只改变一个变量。
数学定义
y 保持不变,只让 x 变化。
Python 动手实践
实例
import sympy as sp
x, y = sp.symbols('x y')
f = x**2 + x*y + y**2
print(f"f(x,y) = {f}")
print(f"∂f/∂x = {sp.diff(f, x)}") # 2x + y
print(f"∂f/∂y = {sp.diff(f, y)}") # x + 2y
# 二阶偏导
print(f"∂²f/∂x² = {sp.diff(f, x, 2)}") # 2
print(f"∂²f/∂x∂y = {sp.diff(f, x, y)}") # 1
# 线性模型损失对参数的偏导
w, b, xi, yi = sp.symbols('w b x_i y_i')
loss = (w*xi + b - yi)**2
print(f"\nloss=(w·xi+b-yi)^2")
print(f"∂L/∂w = {sp.diff(loss, w)}")
print(f"∂L/∂b = {sp.diff(loss, b)}")输出为:
f(x,y) = x**2 + x*y + y**2
∂f/∂x = 2*x + y
∂f/∂y = x + 2*y
∂²f/∂x² = 2
∂²f/∂x∂y = 1
loss=(w·xi+b-yi)^2
∂L/∂w = 2*x_i*(b + w*x_i - y_i)
∂L/∂b = 2*b + 2*w*x_i - 2*y_iAI 中的应用场景
神经网络训练 = 百万次偏导计算
一个百万参数的模型,损失是关于百万个变量的多元函数。每轮训练,自动微分引擎对每一个参数求偏导,得到百万个偏导数值拼成梯度向量,沿负梯度方向更新所有参数。
反向传播中的局部偏导
计算图中每个节点都需要计算局部偏导:加法节点 $ \partial/\partial x = 1 $(梯度原样传回),乘法节点 $ \partial(xy)/\partial x = y $(梯度乘对方值传回)。这些局部偏导沿计算图链式相乘,得到最终参数梯度。
冻结参数的迁移学习
迁移学习中常「冻结」预训练层——这些层的参数不求偏导、不更新。PyTorch 中设置 requires_grad=False,对应参数的偏导计算被跳过,大幅节省显存和计算量。
AI 思考中...