Skip to content

知识点卡片:矩阵微分

基本信息

属性内容
知识点矩阵微分 (Matrix Calculus)
掌握程度★★★★☆
学习优先级P1
预估时间6小时
面试频率★★★☆☆

核心原理

矩阵微分是反向传播的数学基础。在深度学习中,我们需要计算标量损失对矩阵参数的梯度。

布局约定

  • 分母布局(Denominator layout):∂y/∂x 的形状与 x^T 相同
  • 分子布局(Numerator layout):∂y/∂x 的形状与 y 相同

深度学习中通常使用分母布局


核心公式速查

标量对向量:
∂(a^T x)/∂x = a
∂(x^T A x)/∂x = (A + A^T)x
∂‖x‖²/∂x = 2x

标量对矩阵:
∂(a^T X b)/∂X = a b^T
∂(tr(AX))/∂X = A^T
∂(tr(X^T A X))/∂X = (A + A^T)X
∂(log|X|)/∂X = (X^{-1})^T

向量对向量(雅可比矩阵):
∂(Ax)/∂x = A^T (分母布局)
∂(softmax(x))/∂x = diag(p) - p p^T

代码实现

手写关键梯度推导

python
import numpy as np

# 1. MSE损失对W的梯度
# L = ‖XW - y‖² / (2n)
# ∂L/∂W = X^T (XW - y) / n
def mse_gradient(X, y, W):
    n = len(y)
    pred = X @ W
    error = pred - y
    return X.T @ error / n

# 2. 交叉熵 + softmax 对logits的梯度
# L = -Σ y log(softmax(z))
# ∂L/∂z = softmax(z) - y
def softmax(x):
    exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True))
    return exp_x / exp_x.sum(axis=-1, keepdims=True)

def cross_entropy_gradient(logits, targets):
    probs = softmax(logits)
    return probs - targets  # 简洁形式!

# 3. 验证数值梯度
def numerical_gradient(f, x, eps=1e-5):
    grad = np.zeros_like(x)
    for i in range(x.size):
        x_flat = x.flatten()
        x_flat[i] += eps
        f_plus = f(x_flat.reshape(x.shape))
        x_flat[i] -= 2 * eps
        f_minus = f(x_flat.reshape(x.shape))
        grad.flat[i] = (f_plus - f_minus) / (2 * eps)
    return grad

深度学习中的关键梯度

python
import torch
import torch.nn.functional as F

# 1. Linear层梯度
# y = x @ W^T + b
# ∂L/∂W = ∂L/∂y^T @ x
# ∂L/∂x = ∂L/∂y @ W

# 2. BatchNorm梯度(简化)
# y = γ * (x - μ) / √(σ² + ε) + β
# ∂L/∂γ = Σ ∂L/∂y * (x - μ) / √(σ² + ε)
# ∂L/∂β = Σ ∂L/∂y

# 3. Attention梯度
# scores = Q @ K^T / √d_k
# attn = softmax(scores)
# ∂L/∂Q = (∂L/∂attn @ V^T) 的复杂形式

# 验证PyTorch自动微分
x = torch.randn(3, 4, requires_grad=True)
W = torch.randn(4, 2, requires_grad=True)
y = x @ W
loss = y.sum()
loss.backward()

print(f"∂L/∂x shape: {x.grad.shape}")   # (3, 4)
print(f"∂L/∂W shape: {W.grad.shape}")   # (4, 2)
# 解析解:∂L/∂x = ∂L/∂y @ W^T
# torch.allclose(x.grad, torch.ones(3, 2) @ W.T)  # True

softmax梯度完整推导

python
"""
关键推导:∂softmax(z_i) / ∂z_j

设 p_i = softmax(z)_i = exp(z_i) / Σ_k exp(z_k)

情况1: i = j
∂p_i/∂z_i = p_i * (1 - p_i)

情况2: i ≠ j
∂p_i/∂z_j = -p_i * p_j

统一形式:
∂p/∂z = diag(p) - p p^T

交叉熵梯度:
L = -Σ y_k log(p_k)
∂L/∂z = p - y  (极简形式!)
"""

链式法则在矩阵上的应用

python
# 反向传播的核心是链式法则
# 设 L = f(g(h(x, W)))
# 则 ∂L/∂W = ∂L/∂f · ∂f/∂g · ∂g/∂h · ∂h/∂W

# 神经网络中的链式法则
class Layer:
    def forward(self, x):
        self.x = x  # 保存输入
        return self._forward(x)

    def backward(self, grad_output):
        # grad_output = ∂L/∂(本层输出)
        # 需要计算:
        #   1. ∂L/∂(本层参数) = grad_output * ∂output/∂param
        #   2. ∂L/∂(本层输入) = grad_output * ∂output/∂input
        return self._backward(grad_output)

# 示例: Linear层反向传播
class Linear:
    def __init__(self, in_features, out_features):
        self.W = np.random.randn(in_features, out_features) * 0.01
        self.b = np.zeros(out_features)

    def forward(self, x):
        self.x = x
        return x @ self.W + self.b

    def backward(self, grad_output):
        # grad_output: ∂L/∂y, shape (batch, out_features)
        self.grad_W = self.x.T @ grad_output      # (in, out)
        self.grad_b = grad_output.sum(axis=0)      # (out,)
        grad_input = grad_output @ self.W.T        # (batch, in)
        return grad_input

面试高频问题

Q1: 推导softmax + cross_entropy对logits的梯度

设 z = logits, p = softmax(z), L = -Σ y_k log(p_k)

∂L/∂z_i = -Σ_k y_k * ∂log(p_k)/∂z_i
         = -Σ_k y_k * (1/p_k) * ∂p_k/∂z_i

当 k = i: ∂p_i/∂z_i = p_i(1-p_i)
当 k ≠ i: ∂p_k/∂z_i = -p_k p_i

代入:
∂L/∂z_i = -y_i(1-p_i) + Σ_{k≠i} y_k p_i
         = -y_i + p_i(y_i + Σ_{k≠i} y_k)
         = -y_i + p_i * 1
         = p_i - y_i

结论:∂L/∂z = p - y(梯度=预测-标签)

Q2: 矩阵微分为什么重要?

  1. 反向传播基础:所有参数的梯度计算都是矩阵微分
  2. 优化器设计:理解梯度方向才能设计更好的优化器
  3. 架构设计:理解梯度流动才能避免梯度消失/爆炸
  4. 数值稳定性:正确的微分公式保证数值稳定

Q3: PyTorch的自动微分原理?

: PyTorch使用计算图+链式法则自动计算梯度:

  • Forward时构建动态计算图
  • Backward时通过拓扑排序从后向前计算梯度
  • 每个节点只需知道其局部梯度(∂output/∂input)
  • 使用链式法则将局部梯度与上游梯度相乘

常见矩阵微分公式表

表达式对x求导条件
b^T xb-
x^T x2x-
x^T A x(A + A^T)xA是矩阵
‖Ax - b‖²2A^T(Ax - b)-
-log p(y|x)p - ysoftmax+CE
log|X|(X^{-1})^TX可逆

练习题

python
# 1. 手推线性回归梯度
# L = (1/2n) * ‖XW - y‖²
# ∂L/∂W = (1/n) * X^T(XW - y)

# 2. 手推逻辑回归梯度
# L = -Σ[y log(σ(z)) + (1-y)log(1-σ(z))]
# ∂L/∂W = X^T(σ(z) - y)

# 3. 验证自动微分与手算一致
import torch
x = torch.randn(3, 5, requires_grad=True)
W = torch.randn(5, 2, requires_grad=True)
y = torch.randn(3, 2)

loss = ((x @ W - y) ** 2).sum()
loss.backward()
analytical = 2 * x.T @ (x @ W - y)
print(torch.allclose(W.grad, analytical, atol=1e-5))  # True

相关知识点