梯度、链式法则、优化基础

前言

微积分是机器学习优化的核心工具。理解导数、梯度和链式法则,才能真正理解神经网络的反向传播是如何工作的。本文将聚焦于机器学习中最实用的微积分概念。


导数基础

导数的定义

导数表示函数在某点的瞬时变化率:

\[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

本文最后一次更新为 天前,文章中的某些内容可能已过时!