梯度、链式法则、优化基础
前言
微积分是机器学习优化的核心工具。理解导数、梯度和链式法则,才能真正理解神经网络的反向传播是如何工作的。本文将聚焦于机器学习中最实用的微积分概念。
导数基础
导数的定义
导数表示函数在某点的瞬时变化率:
\[f'(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}\]常用导数公式
| 函数 | 导数 |
|---|---|
| $c$(常数) | $0$ |
| $x^n$ | $nx^{n-1}$ |
| $e^x$ | $e^x$ |
| $\ln x$ | $1/x$ |
| $\sin x$ | $\cos x$ |
| $\cos x$ | $-\sin x$ |
数值求导
import numpy as np
def numerical_derivative(f, x, h=1e-5):
"""数值求导(中心差分法)"""
return (f(x + h) - f(x - h)) / (2 * h)
# 示例:f(x) = x^2
f = lambda x: x ** 2
x = 3
derivative = numerical_derivative(f, x)
print(f"f'({x}) ≈ {derivative:.4f}") # 约为 6
偏导数与梯度
偏导数
对于多元函数 $f(x_1, x_2, …, x_n)$,偏导数是固定其他变量,对单个变量求导:
\[\frac{\partial f}{\partial x_i}\]梯度
梯度是所有偏导数组成的向量:
\[\nabla f = \begin{bmatrix} \frac{\partial f}{\partial x_1} \\ \frac{\partial f}{\partial x_2} \\ \vdots \\ \frac{\partial f}{\partial x_n} \end{bmatrix}\]关键性质:梯度指向函数增长最快的方向。
def gradient(f, x, h=1e-5):
"""计算梯度"""
grad = np.zeros_like(x)
for i in range(len(x)):
x_plus = x.copy()
x_minus = x.copy()
x_plus[i] += h
x_minus[i] -= h
grad[i] = (f(x_plus) - f(x_minus)) / (2 * h)
return grad
# 示例:f(x, y) = x^2 + y^2
f = lambda x: x[0]**2 + x[1]**2
point = np.array([3.0, 4.0])
grad = gradient(f, point)
print(f"梯度: {grad}") # [6, 8]
使用自动微分
import torch
# 定义变量
x = torch.tensor([3.0, 4.0], requires_grad=True)
# 前向计算
y = x[0]**2 + x[1]**2
# 反向传播
y.backward()
print(f"梯度: {x.grad}") # tensor([6., 8.])
链式法则
单变量链式法则
如果 $y = f(g(x))$,则:
\[\frac{dy}{dx} = \frac{dy}{dg} \cdot \frac{dg}{dx}\]多变量链式法则
如果 $z = f(x, y)$,其中 $x = g(t)$,$y = h(t)$:
\[\frac{dz}{dt} = \frac{\partial z}{\partial x} \cdot \frac{dx}{dt} + \frac{\partial z}{\partial y} \cdot \frac{dy}{dt}\]示例:复合函数求导
# f(x) = (x^2 + 1)^3
# 令 u = x^2 + 1, f = u^3
# df/dx = df/du * du/dx = 3u^2 * 2x = 6x(x^2 + 1)^2
def f(x):
return (x**2 + 1)**3
def df_analytical(x):
"""解析导数"""
return 6 * x * (x**2 + 1)**2
x = 2.0
print(f"数值导数: {numerical_derivative(f, x):.4f}")
print(f"解析导数: {df_analytical(x):.4f}") # 150
计算图与反向传播
计算图
计算图将计算过程表示为有向图:
- 节点:操作或变量
- 边:数据流向
反向传播示例
考虑 $L = (wx + b - y)^2$:
# 前向传播
w, x, b, y = 2.0, 3.0, 1.0, 10.0
# 计算图节点
z1 = w * x # z1 = 6
z2 = z1 + b # z2 = 7
z3 = z2 - y # z3 = -3
L = z3 ** 2 # L = 9
print(f"损失: {L}")
# 反向传播(链式法则)
dL_dz3 = 2 * z3 # dL/dz3 = -6
dz3_dz2 = 1 # dz3/dz2 = 1
dz2_dz1 = 1 # dz2/dz1 = 1
dz1_dw = x # dz1/dw = 3
# 完整链式
dL_dw = dL_dz3 * dz3_dz2 * dz2_dz1 * dz1_dw
print(f"dL/dw = {dL_dw}") # -18
# 验证
w_tensor = torch.tensor(2.0, requires_grad=True)
L_torch = (w_tensor * x + b - y) ** 2
L_torch.backward()
print(f"PyTorch梯度: {w_tensor.grad}") # -18
向量化反向传播
import torch
# 批量数据
X = torch.tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], requires_grad=False)
W = torch.tensor([[0.1, 0.2], [0.3, 0.4]], requires_grad=True)
y = torch.tensor([[1.0], [2.0], [3.0]])
# 前向传播
pred = X @ W @ torch.ones(2, 1)
loss = ((pred - y) ** 2).mean()
# 反向传播
loss.backward()
print(f"W的梯度:\n{W.grad}")
常用激活函数的导数
Sigmoid
\[\sigma(x) = \frac{1}{1 + e^{-x}}\] \[\sigma'(x) = \sigma(x)(1 - \sigma(x))\]def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_derivative(x):
s = sigmoid(x)
return s * (1 - s)
x = np.linspace(-5, 5, 100)
plt.plot(x, sigmoid(x), label='sigmoid')
plt.plot(x, sigmoid_derivative(x), label='derivative')
plt.legend()
plt.title('Sigmoid及其导数')
plt.show()
ReLU
\[\text{ReLU}(x) = \max(0, x)\] \[\text{ReLU}'(x) = \begin{cases} 1 & x > 0 \\ 0 & x \leq 0 \end{cases}\]def relu(x):
return np.maximum(0, x)
def relu_derivative(x):
return (x > 0).astype(float)
Softmax
\[\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}\]Jacobian 矩阵:
\[\frac{\partial \text{softmax}_i}{\partial x_j} = \text{softmax}_i (\delta_{ij} - \text{softmax}_j)\]def softmax(x):
exp_x = np.exp(x - np.max(x)) # 数值稳定
return exp_x / exp_x.sum()
def softmax_jacobian(x):
s = softmax(x)
return np.diag(s) - np.outer(s, s)
x = np.array([1.0, 2.0, 3.0])
print(f"Softmax: {softmax(x)}")
print(f"Jacobian:\n{softmax_jacobian(x)}")
梯度下降
基本原理
沿着梯度的反方向更新参数:
\[\theta_{t+1} = \theta_t - \eta \nabla_\theta L\]其中 $\eta$ 是学习率。
def gradient_descent(f, grad_f, x0, lr=0.1, n_iters=100):
"""基本梯度下降"""
x = x0.copy()
history = [x.copy()]
for _ in range(n_iters):
g = grad_f(x)
x = x - lr * g
history.append(x.copy())
return x, np.array(history)
# 最小化 f(x,y) = x^2 + y^2
f = lambda x: x[0]**2 + x[1]**2
grad_f = lambda x: np.array([2*x[0], 2*x[1]])
x0 = np.array([5.0, 5.0])
x_min, history = gradient_descent(f, grad_f, x0, lr=0.1, n_iters=50)
print(f"最优解: {x_min}") # 接近 [0, 0]
学习率的影响
learning_rates = [0.01, 0.1, 0.5, 0.9]
x0 = np.array([5.0, 5.0])
for lr in learning_rates:
x_min, history = gradient_descent(f, grad_f, x0, lr=lr, n_iters=20)
print(f"lr={lr}: 最终值={f(x_min):.6f}")
泰勒展开与二阶优化
泰勒展开
\[f(x + \Delta x) \approx f(x) + f'(x)\Delta x + \frac{1}{2}f''(x)\Delta x^2\]海森矩阵
二阶偏导数矩阵:
\[\mathbf{H} = \begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2} & \frac{\partial^2 f}{\partial x_1 \partial x_2} \\ \frac{\partial^2 f}{\partial x_2 \partial x_1} & \frac{\partial^2 f}{\partial x_2^2} \end{bmatrix}\]def hessian(f, x, h=1e-5):
"""数值计算海森矩阵"""
n = len(x)
H = np.zeros((n, n))
for i in range(n):
for j in range(n):
x_pp = x.copy(); x_pp[i] += h; x_pp[j] += h
x_pm = x.copy(); x_pm[i] += h; x_pm[j] -= h
x_mp = x.copy(); x_mp[i] -= h; x_mp[j] += h
x_mm = x.copy(); x_mm[i] -= h; x_mm[j] -= h
H[i, j] = (f(x_pp) - f(x_pm) - f(x_mp) + f(x_mm)) / (4 * h * h)
return H
# 示例
f = lambda x: x[0]**2 + 2*x[1]**2 + x[0]*x[1]
x = np.array([1.0, 1.0])
H = hessian(f, x)
print(f"海森矩阵:\n{H}")
牛顿法
\[x_{t+1} = x_t - \mathbf{H}^{-1} \nabla f\]def newton_method(f, grad_f, hess_f, x0, n_iters=10):
x = x0.copy()
for _ in range(n_iters):
g = grad_f(x)
H = hess_f(x)
x = x - np.linalg.solve(H, g)
return x
常见问题
Q1: 为什么梯度指向增长最快的方向?
考虑方向导数 $D_{\mathbf{v}}f = \nabla f \cdot \mathbf{v}$。当 $\mathbf{v}$ 与 $\nabla f$ 方向相同时,点积最大,增长最快。
Q2: 梯度消失和梯度爆炸是什么?
- 梯度消失:深层网络中梯度越来越小,权重几乎不更新(常见于sigmoid)
- 梯度爆炸:梯度越来越大,导致数值溢出
解决方案:ReLU激活、残差连接、梯度裁剪、适当初始化
Q3: 为什么用随机梯度下降而不是批量梯度下降?
- 计算效率高
- 引入噪声有助于跳出局部最优
- 更好的泛化性能
Q4: 学习率如何选择?
- 太大:震荡、发散
- 太小:收敛慢
- 实践中常用学习率调度(warmup、decay)或自适应优化器(Adam)
总结
| 概念 | 公式 | 重要性 |
|---|---|---|
| 梯度 | $\nabla f$ | 指示优化方向 |
| 链式法则 | $\frac{dy}{dx} = \frac{dy}{du}\frac{du}{dx}$ | 反向传播核心 |
| 梯度下降 | $\theta = \theta - \eta\nabla L$ | 基本优化算法 |
| 海森矩阵 | 二阶导数矩阵 | 二阶优化 |
参考资料
- 《深度学习》花书第4章
- 3Blue1Brown《微积分的本质》
- CS231n 反向传播讲义
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:《 机器学习基础系列——数学基础:微积分 》
本文链接:http://localhost:3015/ai/%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80-%E5%BE%AE%E7%A7%AF%E5%88%86.html
本文最后一次更新为 天前,文章中的某些内容可能已过时!