Skip to content

필사 모드: AI/ML 数学完全指南:线性代数、微积分与概率统计

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

AI/ML 数学完全指南

要真正理解机器学习和深度学习,就必须掌握其背后的数学。很多开发者在使用框架时,其实并不清楚"这个公式为什么会这样起作用"。这篇文章正是为了填补这个空白而写的。

它并不只是罗列公式,而是重点讲解每个概念为什么重要、又在深度学习的哪个环节如何被使用。文中配有可运行的 Python/NumPy 代码,方便你亲自验证这些公式。


1. 线性代数(Linear Algebra)

线性代数是深度学习最基础的语言。神经网络的前向传播(Forward Pass)本质上是一连串矩阵乘法,而嵌入(embedding)则是高维向量空间中的一个点。

1.1 向量(Vector)

向量的定义与几何意义

向量是同时具有大小(magnitude)与方向(direction)的量。数学上它是一列有序的数,几何上则可以看作指向 nn 维空间中某一点的箭头。

v=[v1v2vn]\mathbf{v} = \begin{bmatrix} v_1 \\ v_2 \\ \vdots \\ v_n \end{bmatrix}

在深度学习中,向量无处不在——输入数据、隐藏层的激活值、嵌入表示,全部都是向量。

向量加法与标量乘法

两个向量相加是按分量(element-wise)进行的。

a+b=[a1+b1a2+b2an+bn]\mathbf{a} + \mathbf{b} = \begin{bmatrix} a_1 + b_1 \\ a_2 + b_2 \\ \vdots \\ a_n + b_n \end{bmatrix}

标量 cc 与向量相乘,是把每个分量都乘以 cc

cv=[cv1cv2cvn]c \cdot \mathbf{v} = \begin{bmatrix} c \cdot v_1 \\ c \cdot v_2 \\ \vdots \\ c \cdot v_n \end{bmatrix}

内积(Dot Product)

内积是衡量两个向量"相似度"的运算。

ab=i=1naibi=a1b1+a2b2++anbn\mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_i = a_1 b_1 + a_2 b_2 + \cdots + a_n b_n

从几何上看,内积也可以表示为两个向量的模长与它们夹角 θ\theta 的余弦之积。

ab=abcosθ\mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\| \|\mathbf{b}\| \cos\theta

内积为正时,两个向量大致指向同一方向;为负时指向相反方向;为零时两者正交(垂直)。

余弦相似度(Cosine Similarity)

如果只想衡量两个向量的方向相似性(与大小无关),可以用它们各自的模长做归一化。

cosine similarity(a,b)=abab\text{cosine similarity}(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\| \|\mathbf{b}\|}

其取值范围是 [1,1][-1, 1],1 表示方向完全相同,-1 表示方向完全相反。自然语言处理中衡量词嵌入相似度时经常用到它。

向量范数(Vector Norm)

范数是衡量向量"大小(长度)"的函数。

  • L1L_1 范数(曼哈顿距离):v1=ivi\|\mathbf{v}\|_1 = \sum_i |v_i|
  • L2L_2 范数(欧几里得距离):v2=ivi2\|\mathbf{v}\|_2 = \sqrt{\sum_i v_i^2}
  • LL_\infty 范数(最大值范数):v=maxivi\|\mathbf{v}\|_\infty = \max_i |v_i|

在正则化(Regularization)中,L1L_1 会诱导稀疏性(sparsity),L2L_2 则会让权重整体上更小。

import numpy as np

a = np.array([3.0, 4.0])
b = np.array([1.0, 2.0])

# 内积
dot_product = np.dot(a, b)  # 3*1 + 4*2 = 11
print(f"内积: {dot_product}")

# 范数
l2_norm_a = np.linalg.norm(a)  # sqrt(9+16) = 5
print(f"L2 范数: {l2_norm_a}")

# 余弦相似度
cosine_sim = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
print(f"余弦相似度: {cosine_sim:.4f}")

# 各种范数
v = np.array([3.0, -4.0, 1.0])
print(f"L1 范数: {np.linalg.norm(v, ord=1)}")   # 8.0
print(f"L2 范数: {np.linalg.norm(v, ord=2)}")   # 5.099...
print(f"Linf 范数: {np.linalg.norm(v, ord=np.inf)}")  # 4.0

1.2 矩阵(Matrix)

矩阵表示法

矩阵是把数排列成矩形的结构。m×nm \times n 矩阵有 mm 行(row)和 nn 列(column)。

A=[a11a12a1na21a22a2nam1am2amn]A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix}

在深度学习中,权重矩阵 WW 表示层与层之间的线性变换。

矩阵乘法(Matrix Multiplication)

AAm×km \times k 矩阵、BBk×nk \times n 矩阵时,乘积 C=ABC = AB 是一个 m×nm \times n 矩阵:

Cij=p=1kAipBpjC_{ij} = \sum_{p=1}^{k} A_{ip} B_{pj}

关键规则是前一个矩阵的列数必须等于后一个矩阵的行数。结果矩阵的 shape 是 (m,n)(m, n)

矩阵乘法不满足交换律:ABBAAB \neq BA(一般情况下)。

转置矩阵(Transpose)

把行和列互换得到的矩阵。

(AT)ij=Aji(A^T)_{ij} = A_{ji}

性质:(AB)T=BTAT(AB)^T = B^T A^T

逆矩阵(Inverse Matrix)

方阵 AA 的逆矩阵 A1A^{-1} 满足 AA1=A1A=IAA^{-1} = A^{-1}A = I。逆矩阵存在的前提是行列式不为零。

行列式(Determinant)

2×22 \times 2 矩阵的行列式:

det(abcd)=adbc\det\begin{pmatrix} a & b \\ c & d \end{pmatrix} = ad - bc

行列式表示该矩阵所代表的线性变换把空间"拉伸或压缩"了多少。det(A)=0\det(A) = 0 意味着维度被压缩,逆矩阵不存在。

秩(Rank)

矩阵的秩是线性无关的行(或列)的最大数量。秩越低,该矩阵所代表的线性变换的输出空间维度就越低。低秩近似(Low-rank approximation)是 LoRA 等模型压缩技术的核心概念。

import numpy as np

A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])

B = np.array([[9, 8, 7],
              [6, 5, 4],
              [3, 2, 1]])

# 矩阵乘法
C = np.dot(A, B)
print("矩阵乘法结果:\n", C)

# 转置矩阵
print("A 的转置矩阵:\n", A.T)

# 行列式
A2 = np.array([[3.0, 1.0],
               [2.0, 4.0]])
print(f"行列式: {np.linalg.det(A2):.2f}")  # 3*4 - 1*2 = 10

# 逆矩阵
A_inv = np.linalg.inv(A2)
print("逆矩阵:\n", A_inv)
print("A * A_inv (应为单位矩阵):\n", np.round(A2 @ A_inv))

# 秩
print(f"A 的秩: {np.linalg.matrix_rank(A)}")  # 2 (存在线性相关的行)

1.3 特征值与特征向量(Eigenvalues & Eigenvectors)

定义

对于方阵 AA,满足下列方程的非零向量 v\mathbf{v} 称为特征向量(eigenvector),标量 λ\lambda 称为特征值(eigenvalue)

Av=λvA\mathbf{v} = \lambda \mathbf{v}

这个式子的含义非常强大:当矩阵 AA 变换向量 v\mathbf{v} 时,方向不变,只有大小按 λ\lambda 倍缩放。

特征值分解(Eigendecomposition)

如果 AA 是对称矩阵,就可以用相互正交的特征向量将其分解。

A=QΛQTA = Q \Lambda Q^T

其中 QQ 是以特征向量为列的正交矩阵,Λ\Lambda 是以特征值为对角元的对角矩阵。

与 PCA(主成分分析)的关系

数据矩阵 XX 的协方差矩阵 Σ=1nXTX\Sigma = \frac{1}{n} X^T X 的特征向量就是主成分(Principal Components)。最大特征值所对应的特征向量,就是数据方差最大的方向,也就是最重要的特征方向。

SVD(奇异值分解, Singular Value Decomposition)

特征值分解只适用于方阵,但 SVD 适用于任意矩阵。

A=UΣVTA = U \Sigma V^T

  • UUm×mm \times m 正交矩阵(左奇异向量)
  • Σ\Sigmam×nm \times n 对角矩阵(奇异值,均不小于 0)
  • VTV^Tn×nn \times n 正交矩阵(右奇异向量)

SVD 是矩阵近似、去噪、推荐系统、自然语言处理中 LSA 等技术的核心。LoRA(Low-Rank Adaptation)也利用了 SVD 的低秩近似思想。

import numpy as np

# 特征值与特征向量
A = np.array([[4.0, 2.0],
              [1.0, 3.0]])

eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues)
print("特征向量 (列向量):\n", eigenvectors)

# 验证: A*v = lambda*v
v0 = eigenvectors[:, 0]
lam0 = eigenvalues[0]
print("A*v:", A @ v0)
print("lambda*v:", lam0 * v0)

# SVD
M = np.array([[1, 2, 3],
              [4, 5, 6]])

U, S, Vt = np.linalg.svd(M, full_matrices=False)
print(f"U shape: {U.shape}")
print(f"S (奇异值): {S}")
print(f"Vt shape: {Vt.shape}")

# 低秩近似 (rank-1 近似)
rank1_approx = np.outer(S[0] * U[:, 0], Vt[0, :])
print("原始矩阵:\n", M)
print("rank-1 近似:\n", rank1_approx)

# PCA 示例
from numpy.linalg import eig

# 生成数据
np.random.seed(42)
data = np.random.randn(100, 2)
data[:, 1] = data[:, 0] * 0.8 + data[:, 1] * 0.2  # 添加相关性

# 协方差矩阵
cov = np.cov(data.T)
eigenvals, eigenvecs = eig(cov)

# 第一主成分
idx = np.argsort(eigenvals)[::-1]
principal_component = eigenvecs[:, idx[0]]
print("第一主成分:", principal_component)
print("解释方差比例:", eigenvals[idx[0]] / eigenvals.sum())

1.4 深度学习与线性代数

作为线性变换的层

神经网络的全连接层(Fully Connected Layer)本质上是一个线性变换。

y=Wx+b\mathbf{y} = W\mathbf{x} + \mathbf{b}

其中:

  • xRn\mathbf{x} \in \mathbb{R}^n:输入向量
  • WRm×nW \in \mathbb{R}^{m \times n}:权重矩阵
  • bRm\mathbf{b} \in \mathbb{R}^m:偏置向量
  • yRm\mathbf{y} \in \mathbb{R}^m:输出向量

多个层的堆叠,本质上是连续的线性变换。如果没有激活函数,堆叠再多层也等价于单一的线性变换,因此非线性激活函数(ReLU、Sigmoid 等)是必不可少的。

批处理与矩阵乘法

同时处理 BB 个样本时:

Y=XWT+bY = XW^T + \mathbf{b}

其中 XRB×nX \in \mathbb{R}^{B \times n}YRB×mY \in \mathbb{R}^{B \times m}。GPU 正是针对这种大规模矩阵乘法的并行计算做了优化。


2. 微积分(Calculus)

微积分负责回答深度学习中"如何学习"这个问题。用来最小化损失函数的梯度下降法,完全依赖于微分。

2.1 微分(Differentiation)

极限与导数的定义

函数 f(x)f(x)xx 处的导数,用极限来定义。

f(x)=limh0f(x+h)f(x)hf'(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}

它表示函数在 xx 处的瞬时变化率,也就是该点切线的斜率。

基本求导法则

  • 幂法则:(xn)=nxn1(x^n)' = nx^{n-1}
  • 和法则:(f+g)=f+g(f+g)' = f' + g'
  • 积法则:(fg)=fg+fg(fg)' = f'g + fg'
  • 商法则:(f/g)=(fgfg)/g2(f/g)' = (f'g - fg') / g^2
  • 链式法则(Chain Rule):[f(g(x))]=f(g(x))g(x)[f(g(x))]' = f'(g(x)) \cdot g'(x)

深度学习中常用函数的导数:

  • ddx(ex)=ex\frac{d}{dx}(e^x) = e^x
  • ddx(lnx)=1x\frac{d}{dx}(\ln x) = \frac{1}{x}
  • ddx(σ(x))=σ(x)(1σ(x))\frac{d}{dx}(\sigma(x)) = \sigma(x)(1 - \sigma(x)) (Sigmoid)
  • ddx(tanh(x))=1tanh2(x)\frac{d}{dx}(\tanh(x)) = 1 - \tanh^2(x)
  • ddx(ReLU(x))={1x>00x0\frac{d}{dx}(\text{ReLU}(x)) = \begin{cases} 1 & x > 0 \\ 0 & x \leq 0 \end{cases}

偏导数(Partial Derivative)

对多元函数中的某一个变量求导,其余变量都当作常数处理。

fxi\frac{\partial f}{\partial x_i}

例如,f(x,y)=x2+3xy+y2f(x, y) = x^2 + 3xy + y^2 时:

fx=2x+3y,fy=3x+2y\frac{\partial f}{\partial x} = 2x + 3y, \quad \frac{\partial f}{\partial y} = 3x + 2y

梯度(Gradient)

把所有偏导数收集在一起构成的向量。

f=[fx1fx2fxn]\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}

梯度指向函数值增长最快的方向。因此要最小化损失函数,就要沿着梯度的反方向移动(梯度下降法)。

雅可比(Jacobian)矩阵

向量函数 f:RnRm\mathbf{f}: \mathbb{R}^n \to \mathbb{R}^m 的所有一阶偏导数构成的矩阵。

J=[f1x1f1xnfmx1fmxn]J = \begin{bmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_1}{\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_m}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_n} \end{bmatrix}

海森(Hessian)矩阵

标量函数二阶偏导数构成的方阵。

Hij=2fxixjH_{ij} = \frac{\partial^2 f}{\partial x_i \partial x_j}

海森矩阵的特征值反映了函数的曲率。全部为正表示极小值,全部为负表示极大值,正负混合则表示鞍点(Saddle Point)。

import numpy as np

# 数值微分 (用于验证梯度)
def numerical_gradient(f, x, h=1e-5):
    grad = np.zeros_like(x)
    for i in range(len(x)):
        x_plus = x.copy()
        x_plus[i] += h
        x_minus = x.copy()
        x_minus[i] -= h
        grad[i] = (f(x_plus) - f(x_minus)) / (2 * h)
    return grad

# 示例函数: f(x, y) = x^2 + 2y^2
def f(x):
    return x[0]**2 + 2 * x[1]**2

x0 = np.array([3.0, 4.0])
grad = numerical_gradient(f, x0)
print(f"数值梯度: {grad}")  # [6.0, 16.0]
print(f"解析梯度: [{2*x0[0]}, {4*x0[1]}]")

# 使用 PyTorch 的自动微分
try:
    import torch
    x = torch.tensor([3.0, 4.0], requires_grad=True)
    y = x[0]**2 + 2 * x[1]**2
    y.backward()
    print(f"PyTorch 梯度: {x.grad}")
except ImportError:
    print("未安装 PyTorch")

2.2 链式法则与反向传播(Backpropagation)

链式法则(Chain Rule)

用来计算复合函数导数的法则。

dzdx=dzdydydx\frac{dz}{dx} = \frac{dz}{dy} \cdot \frac{dy}{dx}

推广到多元变量:

zxi=jzyjyjxi\frac{\partial z}{\partial x_i} = \sum_j \frac{\partial z}{\partial y_j} \cdot \frac{\partial y_j}{\partial x_i}

反向传播算法

在神经网络训练中,需要把损失函数 LL 对每一个权重 ww 求导。由于网络是多层复合函数,所以要反复应用链式法则。

以一个 2 层神经网络为例:

L=(softmax(W2ReLU(W1x+b1)+b2),y)L = \ell(\text{softmax}(W_2 \cdot \text{ReLU}(W_1 \mathbf{x} + \mathbf{b}_1) + \mathbf{b}_2), \mathbf{y})

要求 LW1\frac{\partial L}{\partial W_1},需要:

LW1=La2a2hhW1\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial \mathbf{a}_2} \cdot \frac{\partial \mathbf{a}_2}{\partial \mathbf{h}} \cdot \frac{\partial \mathbf{h}}{\partial W_1}

反向传播就是从输出方向朝输入方向,高效地计算这条链。

import numpy as np

# 简单神经网络的反向传播示例
class SimpleNet:
    def __init__(self):
        self.W1 = np.random.randn(4, 3) * 0.1
        self.b1 = np.zeros(4)
        self.W2 = np.random.randn(2, 4) * 0.1
        self.b2 = np.zeros(2)

    def relu(self, x):
        return np.maximum(0, x)

    def relu_grad(self, x):
        return (x > 0).astype(float)

    def forward(self, x):
        self.x = x
        self.z1 = self.W1 @ x + self.b1
        self.h = self.relu(self.z1)
        self.z2 = self.W2 @ self.h + self.b2
        return self.z2

    def backward(self, dL_dz2):
        # 第 2 层梯度
        dL_dW2 = np.outer(dL_dz2, self.h)
        dL_db2 = dL_dz2
        dL_dh = self.W2.T @ dL_dz2

        # ReLU 梯度
        dL_dz1 = dL_dh * self.relu_grad(self.z1)

        # 第 1 层梯度
        dL_dW1 = np.outer(dL_dz1, self.x)
        dL_db1 = dL_dz1

        return dL_dW1, dL_db1, dL_dW2, dL_db2

net = SimpleNet()
x = np.array([1.0, 2.0, 3.0])
output = net.forward(x)
dL_dout = np.array([1.0, -1.0])  # 损失的梯度
grads = net.backward(dL_dout)
print(f"W1 梯度 shape: {grads[0].shape}")
print(f"W2 梯度 shape: {grads[2].shape}")

2.3 优化理论

极值条件

  • 一阶条件(必要条件):在极值点处 f=0\nabla f = \mathbf{0}
  • 二阶条件(充分条件):由海森矩阵 HH 的符号判断极小/极大

凸函数(Convex Function)

如果函数 ff 是凸的,那么函数值总是小于等于两点连线的值。

f(λx+(1λ)y)λf(x)+(1λ)f(y),λ[0,1]f(\lambda x + (1-\lambda)y) \leq \lambda f(x) + (1-\lambda) f(y), \quad \lambda \in [0,1]

凸函数的极小值必然是全局最小值。深度学习的损失函数一般都不是凸的,因此无法保证全局最小值。

梯度下降法(Gradient Descent)

θt+1=θtαθL(θt)\theta_{t+1} = \theta_t - \alpha \nabla_\theta L(\theta_t)

其中 α\alpha 是学习率(learning rate)。学习率过大会发散,过小则收敛缓慢。

常见变体:

  • 随机梯度下降法(SGD):每一步使用一个随机样本(或一个小批量)
  • 动量(Momentum):累积此前的梯度方向以加速收敛
  • Adam:自适应学习率,目前深度学习中使用最广泛的方法

mt=β1mt1+(1β1)gtm_t = \beta_1 m_{t-1} + (1-\beta_1) g_t vt=β2vt1+(1β2)gt2v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2 θt+1=θtαv^t+ϵm^t\theta_{t+1} = \theta_t - \frac{\alpha}{\sqrt{\hat{v}_t} + \epsilon} \hat{m}_t

import numpy as np
import matplotlib.pyplot as plt

# 梯度下降法实现
def gradient_descent(grad_f, init_x, learning_rate=0.1, steps=100):
    x = init_x.copy()
    history = [x.copy()]
    for _ in range(steps):
        grad = grad_f(x)
        x -= learning_rate * grad
        history.append(x.copy())
    return x, np.array(history)

# 示例: f(x, y) = x^2 + 4y^2 求最小值
def f(x):
    return x[0]**2 + 4 * x[1]**2

def grad_f(x):
    return np.array([2*x[0], 8*x[1]])

init_x = np.array([3.0, 3.0])
final_x, history = gradient_descent(grad_f, init_x, learning_rate=0.1, steps=50)
print(f"起始点: {init_x}")
print(f"收敛点: {final_x}")
print(f"最小值: {f(final_x):.6f}")

# Adam 优化器实现
def adam(grad_f, init_x, alpha=0.01, beta1=0.9, beta2=0.999, eps=1e-8, steps=100):
    x = init_x.copy()
    m = np.zeros_like(x)
    v = np.zeros_like(x)
    for t in range(1, steps + 1):
        g = grad_f(x)
        m = beta1 * m + (1 - beta1) * g
        v = beta2 * v + (1 - beta2) * g**2
        m_hat = m / (1 - beta1**t)
        v_hat = v / (1 - beta2**t)
        x -= alpha * m_hat / (np.sqrt(v_hat) + eps)
    return x

final_adam = adam(grad_f, init_x)
print(f"Adam 收敛点: {final_adam}")

3. 概率与统计(Probability & Statistics)

概率与统计是处理深度学习中不确定性的语言。损失函数的设计、正则化、模型评估,全都建立在概率思维之上。

3.1 概率基础

概率公理(Kolmogorov Axioms)

  1. P(A)0P(A) \geq 0 (非负性)
  2. P(Ω)=1P(\Omega) = 1 (全概率为 1)
  3. 对于互斥事件,P(AB)=P(A)+P(B)P(A \cup B) = P(A) + P(B) (可加性)

条件概率

在事件 BB 已经发生的条件下,事件 AA 发生的概率:

P(AB)=P(AB)P(B),P(B)>0P(A|B) = \frac{P(A \cap B)}{P(B)}, \quad P(B) > 0

贝叶斯定理(Bayes' Theorem)

P(AB)=P(BA)P(A)P(B)P(A|B) = \frac{P(B|A) \cdot P(A)}{P(B)}

贝叶斯定理描述的是"基于证据更新信念"的原理。

  • P(A)P(A):先验概率(Prior)——见到证据之前的信念
  • P(BA)P(B|A):似然(Likelihood)——在假设 A 成立的前提下,证据 B 出现的概率
  • P(AB)P(A|B):后验概率(Posterior)——看到证据之后被更新的信念

它被广泛用于分类模型评估、朴素贝叶斯分类器、贝叶斯神经网络等场景。

全概率公式

P(B)=iP(BAi)P(Ai)P(B) = \sum_i P(B|A_i) P(A_i)

3.2 概率分布

离散概率分布

伯努利分布(Bernoulli Distribution)

结果只有 0 或 1 的单次试验:

P(X=k)=pk(1p)1k,k{0,1}P(X=k) = p^k (1-p)^{1-k}, \quad k \in \{0, 1\}

E[X]=pE[X] = pVar(X)=p(1p)Var(X) = p(1-p)

二项分布(Binomial Distribution)

nn 次伯努利试验中成功的次数:

P(X=k)=(nk)pk(1p)nkP(X=k) = \binom{n}{k} p^k (1-p)^{n-k}

泊松分布(Poisson Distribution)

单位时间/空间内事件发生的次数:

P(X=k)=λkeλk!P(X=k) = \frac{\lambda^k e^{-\lambda}}{k!}

E[X]=Var(X)=λE[X] = Var(X) = \lambda

连续概率分布

均匀分布(Uniform Distribution)

在区间 [a,b][a, b] 上,所有值的概率密度都相同:

f(x)=1ba,axbf(x) = \frac{1}{b-a}, \quad a \leq x \leq b

正态分布(Normal/Gaussian Distribution)

f(x)=1σ2πexp((xμ)22σ2)f(x) = \frac{1}{\sigma\sqrt{2\pi}} \exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)

用均值 μ\mu 和标准差 σ\sigma 来刻画。根据中心极限定理(Central Limit Theorem),许多自然现象都近似服从正态分布。深度学习中的权重初始化、噪声建模等都经常用到它。

多元正态分布(Multivariate Normal Distribution)

f(x)=1(2π)d/2Σ1/2exp(12(xμ)TΣ1(xμ))f(\mathbf{x}) = \frac{1}{(2\pi)^{d/2}|\Sigma|^{1/2}} \exp\left(-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^T \Sigma^{-1} (\mathbf{x}-\boldsymbol{\mu})\right)

其中 μ\boldsymbol{\mu} 是均值向量,Σ\Sigma 是协方差矩阵。它是 VAE(Variational Autoencoder)对潜在空间建模的核心工具。

import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# 正态分布
mu, sigma = 0, 1
x = np.linspace(-4, 4, 100)
pdf = stats.norm.pdf(x, mu, sigma)

print(f"P(-1 < X < 1) = {stats.norm.cdf(1) - stats.norm.cdf(-1):.4f}")  # 68.27%
print(f"P(-2 < X < 2) = {stats.norm.cdf(2) - stats.norm.cdf(-2):.4f}")  # 95.45%
print(f"P(-3 < X < 3) = {stats.norm.cdf(3) - stats.norm.cdf(-3):.4f}")  # 99.73%

# 多元正态分布采样
mean = np.array([0, 0])
cov = np.array([[1, 0.7],
                [0.7, 1]])
samples = np.random.multivariate_normal(mean, cov, size=1000)
print(f"样本形状: {samples.shape}")
print(f"样本均值: {samples.mean(axis=0)}")
print(f"样本协方差:\n{np.cov(samples.T)}")

# 二项分布
n, p = 10, 0.5
k = np.arange(0, n+1)
pmf = stats.binom.pmf(k, n, p)
print(f"\n二项分布 B(10, 0.5):")
print(f"P(X=5) = {stats.binom.pmf(5, n, p):.4f}")

3.3 期望值与方差

期望值(Expected Value)

E[X]=xxP(X=x)(离散)E[X] = \sum_x x \cdot P(X=x) \quad \text{(离散)} E[X]=xf(x)dx(连续)E[X] = \int_{-\infty}^{\infty} x \cdot f(x) dx \quad \text{(连续)}

期望值的线性性质:E[aX+b]=aE[X]+bE[aX + b] = aE[X] + b

方差(Variance)

Var(X)=E[(Xμ)2]=E[X2](E[X])2Var(X) = E[(X - \mu)^2] = E[X^2] - (E[X])^2

标准差:σ=Var(X)\sigma = \sqrt{Var(X)}

协方差(Covariance)

衡量两个随机变量之间的线性关系。

Cov(X,Y)=E[(XμX)(YμY)]=E[XY]E[X]E[Y]Cov(X, Y) = E[(X - \mu_X)(Y - \mu_Y)] = E[XY] - E[X]E[Y]

相关系数(Correlation)

ρXY=Cov(X,Y)σXσY\rho_{XY} = \frac{Cov(X, Y)}{\sigma_X \sigma_Y}

其取值范围是 [1,1][-1, 1],只衡量线性关系的强度,与量纲无关。

协方差矩阵(Covariance Matrix)

nn 维随机向量中所有两两组合的协方差:

Σij=Cov(Xi,Xj)\Sigma_{ij} = Cov(X_i, X_j)

它是 PCA 的核心输入,承载着数据的方差结构。

3.4 最大似然估计(Maximum Likelihood Estimation, MLE)

似然函数(Likelihood Function)

给定参数 θ\theta,观测到数据 D={x1,...,xn}\mathcal{D} = \{x_1, ..., x_n\} 的概率:

L(θ;D)=P(Dθ)=i=1nP(xiθ)L(\theta; \mathcal{D}) = P(\mathcal{D}|\theta) = \prod_{i=1}^n P(x_i|\theta)

MLE 要找的是使这个似然最大化的 θ\theta

θ^MLE=argmaxθL(θ;D)\hat{\theta}_{MLE} = \arg\max_\theta L(\theta; \mathcal{D})

对数似然(Log-Likelihood)

把乘法转换成加法,让计算更简单。

logL(θ)=i=1nlogP(xiθ)\log L(\theta) = \sum_{i=1}^n \log P(x_i|\theta)

由于对数是单调递增函数,使对数似然最大化的 θ\theta 与使似然最大化的 θ\theta 是同一个。

MLE 推导示例:正态分布

假设数据 {x1,...,xn}\{x_1, ..., x_n\} 服从 N(μ,σ2)\mathcal{N}(\mu, \sigma^2)

logL(μ,σ2)=n2log(2πσ2)12σ2i=1n(xiμ)2\log L(\mu, \sigma^2) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum_{i=1}^n (x_i - \mu)^2

μ\mu 求导并令其为 0:μ^MLE=xˉ=1nxi\hat{\mu}_{MLE} = \bar{x} = \frac{1}{n}\sum x_i (样本均值)

σ2\sigma^2 求导:σ^MLE2=1n(xixˉ)2\hat{\sigma}^2_{MLE} = \frac{1}{n}\sum (x_i - \bar{x})^2 (样本方差)

深度学习中的 Cross-Entropy 与 MLE

在分类问题中,最小化 Cross-Entropy 损失等价于 MLE。

LCE=1ni=1nc=1Cyiclogp^ic\mathcal{L}_{CE} = -\frac{1}{n}\sum_{i=1}^n \sum_{c=1}^C y_{ic} \log \hat{p}_{ic}

这等价于在真实数据分布下最大化模型的对数似然。

import numpy as np
from scipy.optimize import minimize_scalar

# MLE 示例: 伯努利分布
data = np.array([1, 0, 1, 1, 0, 1, 1, 1, 0, 1])  # 抛硬币
n = len(data)
k = data.sum()

# 解析 MLE: p_hat = k/n
p_mle = k / n
print(f"MLE 估计值: p = {p_mle:.2f}")  # 0.7

# 对数似然函数
def neg_log_likelihood(p):
    if p <= 0 or p >= 1:
        return np.inf
    return -(k * np.log(p) + (n - k) * np.log(1 - p))

result = minimize_scalar(neg_log_likelihood, bounds=(0.01, 0.99), method='bounded')
print(f"数值优化 MLE: p = {result.x:.4f}")

# Cross-Entropy 损失实现
def cross_entropy(y_true, y_pred, eps=1e-15):
    y_pred = np.clip(y_pred, eps, 1 - eps)
    return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))

# 二分类示例
y_true = np.array([1, 0, 1, 1, 0])
y_pred = np.array([0.9, 0.1, 0.8, 0.7, 0.2])
loss = cross_entropy(y_true, y_pred)
print(f"\nCross-Entropy 损失: {loss:.4f}")

3.5 信息论(Information Theory)

熵(Entropy)

概率分布 PP 的不确定性或信息量:

H(X)=xP(x)logP(x)=E[logP(X)]H(X) = -\sum_{x} P(x) \log P(x) = -E[\log P(X)]

在均匀分布下熵最大,只有一种结果可能时熵为 0。

KL 散度(KL Divergence)

两个分布 PPQQ 之间的"距离"(注意,非对称):

DKL(PQ)=xP(x)logP(x)Q(x)=EP[logP(X)Q(X)]D_{KL}(P \| Q) = \sum_x P(x) \log \frac{P(x)}{Q(x)} = E_P\left[\log \frac{P(X)}{Q(X)}\right]

DKL(PQ)0D_{KL}(P \| Q) \geq 0,且仅当 P=QP = Q 时为 0。用于 VAE 的损失函数、策略优化(PPO 等)。

交叉熵(Cross-Entropy)

真实分布 PP 与模型分布 QQ 之间的交叉熵:

H(P,Q)=xP(x)logQ(x)=H(P)+DKL(PQ)H(P, Q) = -\sum_x P(x) \log Q(x) = H(P) + D_{KL}(P \| Q)

由于 H(P)H(P) 是常数,最小化 Cross-Entropy 等价于最小化 KL 散度。

互信息(Mutual Information)

两个随机变量共享的信息量:

I(X;Y)=H(X)H(XY)=H(Y)H(YX)I(X; Y) = H(X) - H(X|Y) = H(Y) - H(Y|X)

它是特征选择、表示学习的理论基础。

import numpy as np

def entropy(p):
    """计算离散分布的熵"""
    p = np.array(p)
    p = p[p > 0]  # 去掉 0 (0*log(0) 按 0 处理)
    return -np.sum(p * np.log2(p))

def kl_divergence(p, q, eps=1e-15):
    """计算 KL 散度 D_KL(P||Q)"""
    p = np.array(p) + eps
    q = np.array(q) + eps
    p = p / p.sum()
    q = q / q.sum()
    return np.sum(p * np.log(p / q))

def cross_entropy_distributions(p, q, eps=1e-15):
    """计算分布间的 Cross-Entropy"""
    p = np.array(p)
    q = np.array(q) + eps
    return -np.sum(p * np.log(q))

# 均匀分布 (最大熵)
uniform = [0.25, 0.25, 0.25, 0.25]
print(f"均匀分布的熵: {entropy(uniform):.4f} bits")  # 2.0 bits

# 集中分布 (低熵)
concentrated = [0.97, 0.01, 0.01, 0.01]
print(f"集中分布的熵: {entropy(concentrated):.4f} bits")

# KL 散度
true_dist = [0.4, 0.3, 0.2, 0.1]
model_dist = [0.35, 0.35, 0.15, 0.15]
kl = kl_divergence(true_dist, model_dist)
print(f"\nKL 散度: {kl:.4f}")

# Cross-Entropy = H(P) + KL(P||Q)
ce = cross_entropy_distributions(true_dist, model_dist)
h_p = entropy(true_dist) * np.log(2)  # 转换为 nats
print(f"Cross-Entropy: {ce:.4f}")
print(f"H(P) + KL: {h_p + kl:.4f}")

4. 数值方法(Numerical Methods)

在深度学习的实现中,理解数学理论与实际计算机运算之间的差距非常重要。

4.1 浮点数表示

计算机中的实数用浮点数表示。

FP32 (单精度)

  • 32 位:符号位 1 位、指数位 8 位、尾数位 23 位
  • 精度:约 7 位十进制有效数字
  • 范围:约 ±3.4×1038\pm 3.4 \times 10^{38}

FP16 (半精度)

  • 16 位:符号位 1 位、指数位 5 位、尾数位 10 位
  • 精度:约 3 位十进制有效数字
  • 节省 GPU 内存、提升速度 (Mixed Precision Training)
  • 缺点:存在上溢/下溢的风险

BF16 (Brain Float 16)

  • 16 位:符号位 1 位、指数位 8 位、尾数位 7 位
  • 与 FP32 相同的指数范围 (上溢风险较低)
  • 由 Google TPU 引入,目前在 AI 训练中广泛使用
import numpy as np

# 浮点数精度问题
a = np.float32(0.1)
b = np.float32(0.2)
print(f"0.1 + 0.2 = {a + b}")  # 可能不精确等于 0.3

# 数值上溢
x_large = np.float16(65000)
print(f"FP16 大数值: {x_large}")
overflow = np.float16(70000)
print(f"FP16 上溢: {overflow}")  # inf

# numpy dtype 比较
for dtype in [np.float16, np.float32, np.float64]:
    info = np.finfo(dtype)
    print(f"{dtype.__name__}: max={info.max:.3e}, min_pos={info.tiny:.3e}")

4.2 数值稳定性

Softmax 的数值不稳定性及其解决方案

Softmax 函数:

softmax(xi)=exijexj\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}

如果输入的值很大,exie^{x_i} 会导致上溢。

数值稳定的 Softmax 实现

softmax(xi)=eximax(x)jexjmax(x)\text{softmax}(x_i) = \frac{e^{x_i - \max(x)}}{\sum_j e^{x_j - \max(x)}}

数学上二者等价,但数值上要稳定得多。

import numpy as np

def naive_softmax(x):
    """不稳定的 Softmax"""
    return np.exp(x) / np.sum(np.exp(x))

def stable_softmax(x):
    """数值稳定的 Softmax"""
    x_shifted = x - np.max(x)  # 减去最大值以保证稳定
    return np.exp(x_shifted) / np.sum(np.exp(x_shifted))

# 常规情况
x_normal = np.array([1.0, 2.0, 3.0])
print("常规输入:")
print(f"  Naive: {naive_softmax(x_normal)}")
print(f"  Stable: {stable_softmax(x_normal)}")

# 大数值情况
x_large = np.array([1000.0, 2000.0, 3000.0])
print("\n大数值输入:")
try:
    result = naive_softmax(x_large)
    print(f"  Naive: {result}")
except RuntimeWarning as e:
    print(f"  Naive: 出现上溢警告!")
print(f"  Stable: {stable_softmax(x_large)}")

# Log-Softmax (与 Cross-Entropy 搭配使用)
def log_softmax(x):
    x_shifted = x - np.max(x)
    return x_shifted - np.log(np.sum(np.exp(x_shifted)))

logits = np.array([2.0, 1.0, 0.1])
print(f"\nLog-Softmax: {log_softmax(logits)}")

5. 线性回归的数学分析

线性回归是深度学习最基本的构成模块。彻底从数学上理解它,是理解更复杂模型的基础。

5.1 最小二乘法(Ordinary Least Squares)

针对数据 {(xi,yi)}i=1n\{(\mathbf{x}_i, y_i)\}_{i=1}^n,训练一个线性模型 y^=wTx+b\hat{y} = \mathbf{w}^T \mathbf{x} + b

损失函数(Mean Squared Error)

L(w)=1ni=1n(yiy^i)2=1nyXw2L(\mathbf{w}) = \frac{1}{n} \sum_{i=1}^n (y_i - \hat{y}_i)^2 = \frac{1}{n} \|y - X\mathbf{w}\|^2

正规方程(Normal Equation)

以矩阵形式对损失函数求导并令其为 0:

wL=2nXT(yXw)=0\nabla_\mathbf{w} L = -\frac{2}{n} X^T (y - X\mathbf{w}) = 0

XTXw=XTy\Rightarrow X^T X \mathbf{w} = X^T y

w^=(XTX)1XTy\Rightarrow \hat{\mathbf{w}} = (X^T X)^{-1} X^T y

这就是最小二乘解。矩阵 XTXX^T X 必须是可逆(invertible)的,这在各特征线性无关时成立。

5.2 Ridge 回归与 Lasso 回归

Ridge 回归(L2 正则化)

Lridge(w)=yXw2+λw22L_{ridge}(\mathbf{w}) = \|y - X\mathbf{w}\|^2 + \lambda \|\mathbf{w}\|_2^2

正规方程:w^=(XTX+λI)1XTy\hat{\mathbf{w}} = (X^T X + \lambda I)^{-1} X^T y

加上 λI\lambda I 后,XTXX^T X 总是可逆的。权重会被保持在接近于零的水平,从而防止过拟合。

Lasso 回归(L1 正则化)

Llasso(w)=yXw2+λw1L_{lasso}(\mathbf{w}) = \|y - X\mathbf{w}\|^2 + \lambda \|\mathbf{w}\|_1

L1 正则化会诱导出稀疏解(sparse solution),让部分权重精确地变为 0,从而具有自动特征选择(feature selection)的效果。

import numpy as np
from sklearn.linear_model import LinearRegression, Ridge, Lasso

# 生成数据
np.random.seed(42)
n, d = 100, 10
X = np.random.randn(n, d)
true_w = np.array([1.0, -2.0, 3.0, 0.0, 0.0, 0.0, 0.5, -0.5, 0.0, 0.0])
y = X @ true_w + np.random.randn(n) * 0.5

# OLS (正规方程)
X_b = np.column_stack([np.ones(n), X])  # 添加偏置项
w_ols = np.linalg.lstsq(X_b, y, rcond=None)[0]
print("OLS 系数 (不含偏置):", w_ols[1:].round(2))

# Ridge
ridge = Ridge(alpha=1.0)
ridge.fit(X, y)
print("Ridge 系数:", ridge.coef_.round(2))

# Lasso (稀疏解)
lasso = Lasso(alpha=0.1)
lasso.fit(X, y)
print("Lasso 系数:", lasso.coef_.round(2))
print("变为 0 的系数数量:", (np.abs(lasso.coef_) < 0.01).sum())

# 直接实现正规方程
def ridge_normal_equation(X, y, lam=1.0):
    n, d = X.shape
    A = X.T @ X + lam * np.eye(d)
    b = X.T @ y
    return np.linalg.solve(A, b)

w_ridge = ridge_normal_equation(X, y, lam=1.0)
print("\n正规方程 Ridge:", w_ridge.round(2))

5.3 梯度的几何意义

等高线与梯度的关系

梯度 f(x)\nabla f(\mathbf{x}) 总是与等高线垂直(正交)。在梯度下降法中,沿这个方向的反方向移动,可以最快地减小函数值。

正则化的几何解释

Ridge 回归等价于在 w22t\|\mathbf{w}\|_2^2 \leq t 这个球形约束内最小化 MSE。由于约束条件是圆形的,所以不会产生稀疏解。

Lasso 则是在 w1t\|\mathbf{w}\|_1 \leq t 这个菱形约束内最小化 MSE。解经常出现在菱形的顶点上,因此会出现稀疏解。


6. 综合:深度学习数学的整合

6.1 神经网络的数学视角

LL 层的全连接神经网络:

h(0)=x\mathbf{h}^{(0)} = \mathbf{x} z(l)=W(l)h(l1)+b(l)\mathbf{z}^{(l)} = W^{(l)} \mathbf{h}^{(l-1)} + \mathbf{b}^{(l)} h(l)=σ(z(l))\mathbf{h}^{(l)} = \sigma(\mathbf{z}^{(l)}) y^=h(L)\hat{y} = \mathbf{h}^{(L)}

前向传播:线性代数(矩阵乘法) + 激活函数

损失计算:信息论(Cross-Entropy) 或 统计学(MSE)

反向传播:微积分(链式法则) → 计算梯度

参数更新:优化理论(梯度下降法、Adam)

6.2 Attention 机制与矩阵运算

Transformer 的 Attention:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V

  • Q,K,VQ, K, V:查询、键、值矩阵(线性代数)
  • 1dk\frac{1}{\sqrt{d_k}} 缩放:数值稳定性(数值方法)
  • Softmax:转换为概率分布(概率论)
  • 内积 QKTQK^T:相似度衡量(向量内积)
import numpy as np

def attention(Q, K, V, mask=None):
    """
    Scaled Dot-Product Attention
    Q, K, V: (seq_len, d_k) 或 (batch, heads, seq_len, d_k)
    """
    d_k = Q.shape[-1]

    # 缩放后的内积相似度
    scores = Q @ K.T / np.sqrt(d_k)  # (seq_len, seq_len)

    # 掩码 (可选)
    if mask is not None:
        scores = np.where(mask, scores, -1e9)

    # Softmax 转换为概率分布
    attention_weights = stable_softmax_2d(scores)

    # 加权求和
    output = attention_weights @ V

    return output, attention_weights

def stable_softmax_2d(x):
    x_max = x.max(axis=-1, keepdims=True)
    x_shifted = x - x_max
    exp_x = np.exp(x_shifted)
    return exp_x / exp_x.sum(axis=-1, keepdims=True)

# 示例: 3 个 token, d_k=4
seq_len, d_k = 3, 4
Q = np.random.randn(seq_len, d_k)
K = np.random.randn(seq_len, d_k)
V = np.random.randn(seq_len, d_k)

output, weights = attention(Q, K, V)
print(f"Attention 输出 shape: {output.shape}")
print(f"Attention 权重 (每行之和 = 1):\n{weights.round(3)}")
print(f"每行之和: {weights.sum(axis=-1)}")

结语:接下来的学习方向

这篇指南梳理了 AI/ML 的核心数学基础。总结一下:

  1. 线性代数:表示与变换数据、模型参数的语言
  2. 微积分:解释模型"如何学习"的工具
  3. 概率与统计:处理不确定性,为损失函数提供理论依据
  4. 数值方法:让理论在真实计算机上稳定实现的知识

推荐接下来的学习步骤:

  • Gilbert Strang 的线性代数课程:MIT OCW 免费提供
  • Pattern Recognition and Machine Learning (Bishop):从概率论视角讲解 ML
  • Deep Learning (Goodfellow et al.):深度学习理论的圣经
  • 动手实践:用 NumPy 从零实现一个神经网络

数学是理解的工具。不必背下每一个公式,但如果能理解每个概念为什么存在、又在深度学习的哪个环节如何起作用,就能获得远比死记硬背更强大的实战能力。


参考资料

  • Gilbert Strang, Introduction to Linear Algebra, 6th Edition
  • Ian Goodfellow et al., Deep Learning, MIT Press (2016)
  • Christopher Bishop, Pattern Recognition and Machine Learning, Springer (2006)
  • 3Blue1Brown YouTube - Essence of Linear Algebra, Essence of Calculus
  • fast.ai - Practical Deep Learning for Coders (数学直观讲解)

현재 단락 (1/595)

要真正理解机器学习和深度学习,就必须掌握其背后的数学。很多开发者在使用框架时,其实并不清楚"这个公式为什么会这样起作用"。这篇文章正是为了填补这个空白而写的。

작성 글자: 0원문 글자: 21,195작성 단락: 0/595