人工智能数学基础+python实例(人工智能学习day3)

文章目录

  • 人工智能数学基础
    • [需要的 Python 库](#需要的 Python 库)
  • [附录 A 线性代数](#附录 A 线性代数)
    • [A.1 向量和向量空间](#A.1 向量和向量空间)
      • [A.1.1 向量](#A.1.1 向量)
      • [A.1.2 向量空间](#A.1.2 向量空间)
      • [A.1.3 范数](#A.1.3 范数)
      • [A.1.4 常见的向量](#A.1.4 常见的向量)
    • [A.2 矩阵](#A.2 矩阵)
      • [A.2.1 线性映射](#A.2.1 线性映射)
      • [A.2.2 仿射变换](#A.2.2 仿射变换)
      • [A.2.3 矩阵操作](#A.2.3 矩阵操作)
      • [A.2.4 矩阵类型](#A.2.4 矩阵类型)
      • [A.2.5 特征值与特征向量](#A.2.5 特征值与特征向量)
      • [A.2.6 矩阵分解](#A.2.6 矩阵分解)
        • [A.2.6.1 特征分解(Eigendecomposition)](#A.2.6.1 特征分解(Eigendecomposition))
        • [A.2.6.2 奇异值分解(SVD)](#A.2.6.2 奇异值分解(SVD))
  • [附录 B 微积分](#附录 B 微积分)
    • [B.1 微分](#B.1 微分)
      • [B.1.1 导数](#B.1.1 导数)
      • [B.1.2 微分](#B.1.2 微分)
      • [B.1.3 泰勒公式](#B.1.3 泰勒公式)
    • [B.2 积分](#B.2 积分)
    • [B.3 矩阵微积分](#B.3 矩阵微积分)
    • [B.4 常见函数的导数](#B.4 常见函数的导数)
      • [B.4.1 向量函数及其导数](#B.4.1 向量函数及其导数)
      • [B.4.2 Logistic 函数](#B.4.2 Logistic 函数)
      • [B.4.3 Softmax 函数](#B.4.3 Softmax 函数)
  • [附录 C 数学优化](#附录 C 数学优化)
    • [C.1 数学优化的类型](#C.1 数学优化的类型)
    • [C.2 优化算法](#C.2 优化算法)
      • [C.2.1 全局最小解和局部最小解](#C.2.1 全局最小解和局部最小解)
      • [C.2.2 梯度下降法](#C.2.2 梯度下降法)
    • [C.3 拉格朗日乘数法与 KKT 条件](#C.3 拉格朗日乘数法与 KKT 条件)
  • [附录 D 概率论](#附录 D 概率论)
    • [D.1 样本空间](#D.1 样本空间)
    • [D.2 事件和概率](#D.2 事件和概率)
    • [D.2.2 随机向量](#D.2.2 随机向量)
    • [D.2.3 边际分布](#D.2.3 边际分布)
    • [D.2.4 条件概率分布](#D.2.4 条件概率分布)
    • [D.2.5 贝叶斯定理](#D.2.5 贝叶斯定理)
    • [D.2.6 独立与条件独立](#D.2.6 独立与条件独立)
    • [D.2.7 期望和方差](#D.2.7 期望和方差)
    • [D.3 随机过程](#D.3 随机过程)
      • [D.3.1 马尔可夫过程](#D.3.1 马尔可夫过程)
      • 细致平稳条件
      • [D.3.2 高斯过程](#D.3.2 高斯过程)
  • [附录 E 信息论](#附录 E 信息论)
    • [E.1 熵](#E.1 熵)
    • [E.2 互信息](#E.2 互信息)
    • [E.3 交叉熵和散度](#E.3 交叉熵和散度)
      • 交叉熵
      • [KL 散度](#KL 散度)
      • [JS 散度](#JS 散度)
      • [Wasserstein 距离(推土机距离)](#Wasserstein 距离(推土机距离))
    • [E.4 总结](#E.4 总结)

人工智能数学基础

原文来源:《人工智能数学基础》附录部分

本文档为每个数学公式/概念附加了 Python 代码示例


需要的 Python 库

python 复制代码
import numpy as np           # 矩阵运算、线性代数
import scipy.stats as stats  # 概率分布、统计函数
import scipy.linalg          # 线性代数(特征值分解、SVD等)
import matplotlib.pyplot as plt  # 可视化
import sympy as sp           # 符号计算(微分、积分、泰勒展开)
import math                  # 基本数学函数

安装命令:

bash 复制代码
pip install numpy scipy matplotlib sympy

附录 A 线性代数

线性代数主要包含向量、向量空间(或称线性空间)以及向量的线性变换和有限维的线性方程组。

A.1 向量和向量空间

A.1.1 向量

标量(Scalar) 是一个实数,只有大小,没有方向。标量一般用斜体小写英文字母来表示。

向量(Vector) 是由一组实数组成的有序数组,同时具有大小和方向。一个 n 维向量是由 n 个有序实数组成,表示为:

x = x 1 , x 2 , . . . , x n T \mathbf{x} = x_1, x_2, ..., x_n^T x=x1,x2,...,xnT

其中 x i x_i xi 称为向量的第 i 个分量,或第 i 维。

python 复制代码
# 向量示例
x = np.array([3.0, 4.0, 5.0])  # 3维向量
print(f"向量 x = {x}")
print(f"维度: {x.shape[0]}")
print(f"大小(模): {np.linalg.norm(x):.4f}")

输出:

复制代码
向量 x = [3. 4. 5.]
维度: 3
大小(模): 7.0711

A.1.2 向量空间

向量空间(Vector Space),也称线性空间(Linear Space),是指由向量组成的集合,并满足以下两个条件:

  1. 向量加法 + + +:向量空间 V V V 中的两个向量 x \mathbf{x} x 和 y \mathbf{y} y,它们的和 x + y \mathbf{x}+\mathbf{y} x+y 也属于空间 V V V;
  2. 标量乘法 ⋅ \cdot ⋅:向量空间 V V V 中的任一向量 x \mathbf{x} x 和任一标量 c c c,它们的乘积 c x c\mathbf{x} cx 也属于空间 V V V。

欧氏空间(Euclidean Space) :一个定义在实数域上的欧氏空间通常表示为 R n \mathbb{R}^n Rn,其中 n 为空间维度。

x + y = x 1 + y 1 , x 2 + y 2 , . . . , x n + y n T \mathbf{x} + \mathbf{y} = x_1+y_1, x_2+y_2, ..., x_n+y_n^T x+y=x1+y1,x2+y2,...,xn+ynT

c x = c x 1 , c x 2 , . . . , c x n T c\mathbf{x} = cx_1, cx_2, ..., cx_n^T cx=cx1,cx2,...,cxnT

python 复制代码
# 向量空间运算
x = np.array([1.0, 2.0, 3.0])
y = np.array([4.0, 5.0, 6.0])
c = 2.0

# 向量加法
add_result = x + y
print(f"x + y = {add_result}")

# 标量乘法
scale_result = c * x
print(f"c * x = {scale_result}")

# 验证封闭性:结果仍在同一空间中
print(f"结果维度: {add_result.shape[0]}")

输出:

复制代码
x + y = [5. 7. 9.]
c * x = [2. 4. 6.]
结果维度: 3

线性无关 :线性空间 V 中的 k 个向量 x 1 , x 2 , . . . , x k \mathbf{x}_1, \mathbf{x}_2, ..., \mathbf{x}_k x1,x2,...,xk,如果:

λ 1 x 1 + λ 2 x 2 + . . . + λ k x k = 0    ⟹    λ 1 = λ 2 = . . . = λ k = 0 \lambda_1\mathbf{x}_1 + \lambda_2\mathbf{x}_2 + ... + \lambda_k\mathbf{x}_k = 0 \implies \lambda_1 = \lambda_2 = ... = \lambda_k = 0 λ1x1+λ2x2+...+λkxk=0⟹λ1=λ2=...=λk=0

则这些向量是线性无关的。

python 复制代码
# 线性无关验证
v1 = np.array([1, 0, 0])
v2 = np.array([0, 1, 0])
v3 = np.array([0, 0, 1])

# 构造矩阵并检查秩
M = np.column_stack([v1, v2, v3])
rank = np.linalg.matrix_rank(M)
print(f"矩阵秩: {rank}, 向量个数: 3")
print(f"线性无关: {rank == 3}")

# 线性相关的例子
v4 = np.array([2, 2, 0])  # v4 = 2*v1 + 2*v2
M2 = np.column_stack([v1, v2, v4])
rank2 = np.linalg.matrix_rank(M2)
print(f"线性相关矩阵秩: {rank2}, 向量个数: 3")
print(f"线性无关: {rank2 == 3}")

输出:

复制代码
矩阵秩: 3, 向量个数: 3
线性无关: True
线性相关矩阵秩: 2, 向量个数: 3
线性无关: False

基向量 :n 维向量空间 V 的基 B = { e 1 , e 2 , . . . , e n } \mathcal{B} = \{\mathbf{e}_1, \mathbf{e}_2, ..., \mathbf{e}_n\} B={e1,e2,...,en} 是 V 的有限子集,其元素之间线性无关。向量空间 V 中所有的向量都可以按唯一的方式表达为 B \mathcal{B} B 中向量的线性组合。

n 维空间 R n \mathbb{R}^n Rn 的一组标准基为:

e 1 = 1 , 0 , 0 , . . . , 0 , e 2 = 0 , 1 , 0 , . . . , 0 , . . . , e n = 0 , 0 , . . . , 1 \mathbf{e}_1 = 1,0,0,...,0,\ \mathbf{e}_2 = 0,1,0,...,0,\ ...,\ \mathbf{e}_n = 0,0,...,1 e1=1,0,0,...,0, e2=0,1,0,...,0, ..., en=0,0,...,1

x = x 1 e 1 + x 2 e 2 + . . . + x n e n = x 1 , x 2 , . . . , x n T \mathbf{x} = x_1\mathbf{e}_1 + x_2\mathbf{e}_2 + ... + x_n\mathbf{e}_n = x_1, x_2, ..., x_n^T x=x1e1+x2e2+...+xnen=x1,x2,...,xnT

python 复制代码
# 标准基和坐标表示
n = 3
standard_basis = np.eye(n)  # 标准基矩阵
x = np.array([5, 3, 7])

# 用线性组合验证
reconstructed = np.zeros(n)
for i in range(n):
    reconstructed += x[i] * standard_basis[i]
print(f"原向量: {x}")
print(f"线性组合重建: {reconstructed}")
print(f"相等: {np.allclose(x, reconstructed)}")

输出:

复制代码
原向量: [5 3 7]
线性组合重建: [5. 3. 7.]
相等: True

内积(Inner Product) :一个 n 维线性空间中两个向量 x \mathbf{x} x 和 y \mathbf{y} y 的内积为:

x ⋅ y = ∑ i = 1 n x i y i = x T y \mathbf{x} \cdot \mathbf{y} = \sum_{i=1}^n x_i y_i = \mathbf{x}^T\mathbf{y} x⋅y=i=1∑nxiyi=xTy

内积也称为点积(Dot Product)或标量积(Scalar Product)。

python 复制代码
# 内积运算
x = np.array([1, 2, 3])
y = np.array([4, 5, 6])

# 三种等价方式
dot1 = np.dot(x, y)
dot2 = x @ y           # Python 3.5+ 矩阵乘法运算符
dot3 = np.sum(x * y)   # 逐元素乘法后求和

print(f"内积 x·y = {dot1}")
print(f"x @ y = {dot2}")
print(f"sum(x*y) = {dot3}")

输出:

复制代码
内积 x·y = 32
x @ y = 32
sum(x*y) = 32

正交(Orthogonal):如果向量空间中两个向量的内积为 0,则它们正交。

python 复制代码
# 正交判断
x = np.array([1, 0, 0])
y = np.array([0, 1, 0])
z = np.array([1, 1, 0])

print(f"x·y = {np.dot(x, y)}, 正交: {np.dot(x, y) == 0}")
print(f"x·z = {np.dot(x, z)}, 正交: {np.dot(x, z) == 0}")

输出:

复制代码
x·y = 0, 正交: True
x·z = 1, 正交: False

A.1.3 范数

范数(Norm)是一个表示向量"长度"的函数。对于一个 n 维向量 x \mathbf{x} x, L p L_p Lp 范数定义为:

L p ( x ) = ( ∑ i = 1 n ∣ x i ∣ p ) 1 / p , p ≥ 1 L_p(\mathbf{x}) = \left(\sum_{i=1}^n |x_i|^p\right)^{1/p}, \quad p \ge 1 Lp(x)=(i=1∑n∣xi∣p)1/p,p≥1

  • L 1 L_1 L1 范数 : L 1 ( x ) = ∑ i = 1 n ∣ x i ∣ L_1(\mathbf{x}) = \sum_{i=1}^n |x_i| L1(x)=∑i=1n∣xi∣
  • L 2 L_2 L2 范数 : L 2 ( x ) = ∑ i = 1 n x i 2 L_2(\mathbf{x}) = \sqrt{\sum_{i=1}^n x_i^2} L2(x)=∑i=1nxi2
  • L ∞ L_\infty L∞ 范数 : L ∞ ( x ) = max ⁡ i ∣ x i ∣ L_\infty(\mathbf{x}) = \max_i |x_i| L∞(x)=maxi∣xi∣
python 复制代码
# 向量范数
x = np.array([3, -4, 5])

l1 = np.linalg.norm(x, ord=1)
l2 = np.linalg.norm(x, ord=2)  # 或 np.linalg.norm(x)
linf = np.linalg.norm(x, ord=np.inf)

print(f"L1 范数 (曼哈顿距离): {l1}")
print(f"L2 范数 (欧氏距离):   {l2:.4f}")
print(f"L∞ 范数 (最大值):     {linf}")

# 手动计算验证
l1_manual = np.sum(np.abs(x))
l2_manual = np.sqrt(np.sum(x**2))
linf_manual = np.max(np.abs(x))
print(f"\n手动计算验证: L1={l1_manual}, L2={l2_manual:.4f}, L∞={linf_manual}")

输出:

复制代码
L1 范数 (曼哈顿距离): 12.0
L2 范数 (欧氏距离):   7.0711
L∞ 范数 (最大值):     5.0

手动计算验证: L1=12, L2=7.0711, L∞=5

A.1.4 常见的向量

  • 全 0 向量 :所有元素都为 0 的向量,用 0 \mathbf{0} 0 表示。
  • 全 1 向量 :所有元素都为 1 的向量,用 1 \mathbf{1} 1 表示。
  • one-hot 向量:有且只有一个元素为 1,其余元素都为 0 的向量。
python 复制代码
n = 5

# 全0向量
zero_vec = np.zeros(n)
print(f"全0向量: {zero_vec}")

# 全1向量
ones_vec = np.ones(n)
print(f"全1向量: {ones_vec}")

# one-hot向量(第3个位置为1,索引从0开始)
one_hot = np.zeros(n)
one_hot[2] = 1
print(f"one-hot向量: {one_hot}")

# 用库函数创建one-hot
from sklearn.preprocessing import OneHotEncoder
# 需要 sklearn: pip install scikit-learn

输出:

复制代码
全0向量: [0. 0. 0. 0. 0.]
全1向量: [1. 1. 1. 1. 1.]
one-hot向量: [0. 0. 1. 0. 0.]

A.2 矩阵

A.2.1 线性映射

线性映射(Linear Mapping)是指从线性空间 V 到线性空间 W 的一个映射函数 f : V → W f: V \to W f:V→W,满足:

f ( x + y ) = f ( x ) + f ( y ) , f ( c x ) = c f ( x ) f(\mathbf{x}+\mathbf{y}) = f(\mathbf{x}) + f(\mathbf{y}), \quad f(c\mathbf{x}) = cf(\mathbf{x}) f(x+y)=f(x)+f(y),f(cx)=cf(x)

两个有限维欧氏空间的映射函数 f : R n → R m f: \mathbb{R}^n \to \mathbb{R}^m f:Rn→Rm 可以表示为:

y = A x \mathbf{y} = \mathbf{A}\mathbf{x} y=Ax

其中 A \mathbf{A} A 是一个 m × n m \times n m×n 的矩阵(Matrix)。

python 复制代码
# 线性映射
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # 3x2 矩阵: R² → R³

x = np.array([2, 3])     # R²中的向量

y = A @ x  # 线性映射
print(f"A = \n{A}")
print(f"x = {x}")
print(f"y = Ax = {y}")
print(f"映射: R^{x.shape[0]} → R^{y.shape[0]}")

输出:

复制代码
A = 
[[1 2]
 [3 4]
 [5 6]]
x = [2 3]
y = Ax = [ 8 18 28]
映射: R² → R³

A.2.2 仿射变换

仿射变换(Affine Transformation)是指通过一个线性变换和一个平移,将一个向量空间变换成另一个向量空间的过程。

y = A x + b \mathbf{y} = \mathbf{A}\mathbf{x} + \mathbf{b} y=Ax+b

其中 x ∈ R n \mathbf{x} \in \mathbb{R}^n x∈Rn, A ∈ R m × n \mathbf{A} \in \mathbb{R}^{m \times n} A∈Rm×n, b ∈ R m \mathbf{b} \in \mathbb{R}^m b∈Rm 为平移项。

当 b = 0 \mathbf{b} = 0 b=0 时,仿射变换就退化为线性变换。

python 复制代码
# 仿射变换示例:2D点旋转+平移
A = np.array([[0.866, -0.5],   # 旋转30度
              [0.5,   0.866]])
b = np.array([2, 3])           # 平移向量

points = np.array([[1, 0],     # 原始点
                   [2, 1],
                   [0, 2]])

# 对每个点施加仿射变换
transformed = points @ A.T + b  # 每个点:(A·x + b)
print("原始点:\n", points)
print("变换后:\n", transformed)

# 可视化
fig, ax = plt.subplots(figsize=(6, 6))
ax.scatter(points[:, 0], points[:, 1], c='blue', s=100, label='原始')
ax.scatter(transformed[:, 0], transformed[:, 1], c='red', s=100, label='变换后')
ax.axhline(0, color='gray', alpha=0.3)
ax.axvline(0, color='gray', alpha=0.3)
ax.legend()
ax.set_aspect('equal')
ax.grid(True)
ax.set_title('仿射变换:旋转30° + 平移(2,3)')
plt.show()

A.2.3 矩阵操作

矩阵加法 :两个 m × n m \times n m×n 矩阵 A \mathbf{A} A 和 B \mathbf{B} B 的加也是 m × n m \times n m×n 矩阵:

C = A + B , C i j = A i j + B i j \mathbf{C} = \mathbf{A} + \mathbf{B},\quad C_{ij} = A_{ij} + B_{ij} C=A+B,Cij=Aij+Bij

python 复制代码
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = A + B
print(f"A + B =\n{C}")

输出:

复制代码
A + B =
[[ 6  8]
 [10 12]]

矩阵乘法 : A ∈ R m × k \mathbf{A} \in \mathbb{R}^{m \times k} A∈Rm×k 和 B ∈ R k × n \mathbf{B} \in \mathbb{R}^{k \times n} B∈Rk×n 的乘积 C ∈ R m × n \mathbf{C} \in \mathbb{R}^{m \times n} C∈Rm×n:

C i j = ∑ t = 1 k A i t B t j C_{ij} = \sum_{t=1}^k A_{it} B_{tj} Cij=t=1∑kAitBtj

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6]])  # 2x3

B = np.array([[7,  8],
              [9,  10],
              [11, 12]])   # 3x2

C = A @ B  # 2x2
print(f"A (2x3) @ B (3x2) = C (2x2)\n{C}")

# 验证结合律: (AB)C = A(BC)
D = np.array([[1, 2], [3, 4]])  # 2x2
left = (A @ B) @ D
right = A @ (B @ D)
print(f"\n结合律验证 - 相等: {np.allclose(left, right)}")

输出:

复制代码
A (2x3) @ B (3x2) = C (2x2)
[[ 58  64]
 [139 154]]

结合律验证 - 相等: True

转置(Transposition) : m × n m \times n m×n 矩阵 A \mathbf{A} A 的转置是一个 n × m n \times m n×m 矩阵 A T \mathbf{A}^T AT:

( A T ) i j = A j i (\mathbf{A}^T){ij} = A{ji} (AT)ij=Aji

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6]])
AT = A.T
print(f"A =\n{A}")
print(f"A^T =\n{AT}")
print(f"(A^T)^T == A: {np.allclose(AT.T, A)}")  # 转置的转置等于原矩阵

输出:

复制代码
A =
[[1 2 3]
 [4 5 6]]
A^T =
[[1 4]
 [2 5]
 [3 6]]
(A^T)^T == A: True

Hadamard 积(逐点乘积) :矩阵 A \mathbf{A} A 和 B \mathbf{B} B 中对应的元素相乘。

C = A ⊙ B , C i j = A i j ⋅ B i j \mathbf{C} = \mathbf{A} \odot \mathbf{B},\quad C_{ij} = A_{ij} \cdot B_{ij} C=A⊙B,Cij=Aij⋅Bij

python 复制代码
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
C = A * B  # 逐元素相乘
print(f"Hadamard 积 A ⊙ B =\n{C}")

输出:

复制代码
Hadamard 积 A ⊙ B =
[[ 5 12]
 [21 32]]

标量与矩阵乘积 : c A c\mathbf{A} cA 的每个元素是 A \mathbf{A} A 的相应元素与 c 的乘积。

python 复制代码
A = np.array([[1, 2], [3, 4]])
c = 3
print(f"3 * A =\n{c * A}")

Kronecker 积 :如果 A ∈ R m × n \mathbf{A} \in \mathbb{R}^{m \times n} A∈Rm×n, B ∈ R p × q \mathbf{B} \in \mathbb{R}^{p \times q} B∈Rp×q,则 Kronecker 积为 m p × n q mp \times nq mp×nq 矩阵:

python 复制代码
A = np.array([[1, 2],
              [3, 4]])  # 2x2
B = np.array([[0, 5],
              [6, 7]])  # 2x2

C = np.kron(A, B)       # 4x4
print(f"Kronecker 积 (4x4):\n{C}")

输出:

复制代码
Kronecker 积 (4x4):
[[ 0  5  0 10]
 [ 6  7 12 14]
 [ 0 15  0 20]
 [18 21 24 28]]

外积(Outer Product) :两个向量 a ∈ R m \mathbf{a} \in \mathbb{R}^m a∈Rm 和 b ∈ R n \mathbf{b} \in \mathbb{R}^n b∈Rn 的外积是一个 m × n m \times n m×n 矩阵:

C = a b T , C i j = a i b j \mathbf{C} = \mathbf{a}\mathbf{b}^T,\quad C_{ij} = a_i b_j C=abT,Cij=aibj

python 复制代码
a = np.array([1, 2, 3])    # 3维列向量
b = np.array([4, 5])       # 2维列向量

C = np.outer(a, b)          # 外积:3x2矩阵
print(f"外积 a·b^T (3x2):\n{C}")

输出:

复制代码
外积 a·b^T (3x2):
[[ 4  5]
 [ 8 10]
 [12 15]]

向量化(Vectorization):将矩阵表示为一个列向量。

vec ( A ) = A 11 , . . . , A m 1 , A 12 , . . . , A m 2 , . . . , A 1 n , . . . , A m n T \text{vec}(\mathbf{A}) = A_{11}, ..., A_{m1}, A_{12}, ..., A_{m2}, ..., A_{1n}, ..., A_{mn}^T vec(A)=A11,...,Am1,A12,...,Am2,...,A1n,...,AmnT

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6]])
vec_A = A.flatten()  # 或 A.reshape(-1, order='F') 按列展开
print(f"矩阵 A:\n{A}")
print(f"向量化 (按行): {A.flatten()}")
print(f"向量化 (按列): {A.flatten('F')}")

输出:

复制代码
矩阵 A:
[[1 2 3]
 [4 5 6]]
向量化 (按行): [1 2 3 4 5 6]
向量化 (按列): [1 4 2 5 3 6]

迹(Trace) :方块矩阵 A \mathbf{A} A 的对角线元素之和。

tr ( A ) = ∑ i A i i \text{tr}(\mathbf{A}) = \sum_i A_{ii} tr(A)=i∑Aii

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
trace_A = np.trace(A)
print(f"tr(A) = {trace_A}")
print(f"手动验证: {A[0,0] + A[1,1] + A[2,2]}")

# tr(AB) = tr(BA)
B = np.array([[2, 1, 0],
              [1, 3, 2],
              [0, 2, 4]])
print(f"tr(AB) = {np.trace(A @ B):.1f}, tr(BA) = {np.trace(B @ A):.1f}, 相等: {np.allclose(np.trace(A @ B), np.trace(B @ A))}")

输出:

复制代码
tr(A) = 15
手动验证: 15
tr(AB) = 59.0, tr(BA) = 59.0, 相等: True

行列式(Determinant) :方块矩阵 A \mathbf{A} A 的行列式记为 det ⁡ ( A ) \det(\mathbf{A}) det(A) 或 ∣ A ∣ |\mathbf{A}| ∣A∣。

det ⁡ ( A ) = ∑ σ ∈ S n sgn ( σ ) ∏ i = 1 n A i , σ ( i ) \det(\mathbf{A}) = \sum_{\sigma \in S_n} \text{sgn}(\sigma) \prod_{i=1}^n A_{i,\sigma(i)} det(A)=σ∈Sn∑sgn(σ)i=1∏nAi,σ(i)

python 复制代码
A = np.array([[1, 2],
              [3, 4]])
det_A = np.linalg.det(A)
print(f"det(A) = {det_A}")

# 行列式为0表示矩阵不可逆
B = np.array([[1, 2],
              [2, 4]])  # 线性相关:B的第2行 = 2×第1行
det_B = np.linalg.det(B)
print(f"det(B) = {det_B:.10f}, 不可逆: {abs(det_B) < 1e-10}")

输出:

复制代码
det(A) = -2.0000000000000004
det(B) = 0.0000000000, 不可逆: True

秩(Rank):矩阵的列秩和行秩总是相等,简称为秩。

rank ( A ) ≤ min ⁡ ( m , n ) \text{rank}(\mathbf{A}) \le \min(m, n) rank(A)≤min(m,n)

rank ( A B ) ≤ min ⁡ ( rank ( A ) , rank ( B ) ) \text{rank}(\mathbf{A}\mathbf{B}) \le \min(\text{rank}(\mathbf{A}), \text{rank}(\mathbf{B})) rank(AB)≤min(rank(A),rank(B))

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])  # 第3行 = 2×第2行 - 第1行

rank_A = np.linalg.matrix_rank(A)
print(f"rank(A) = {rank_A}, 满秩: {rank_A == min(A.shape)}")

B = np.array([[1, 0, 0],
              [0, 1, 0],
              [0, 0, 1]])
rank_B = np.linalg.matrix_rank(B)
print(f"rank(B) = {rank_B}, 满秩: {rank_B == min(B.shape)}")

输出:

复制代码
rank(A) = 2, 满秩: False
rank(B) = 3, 满秩: True

矩阵范数

∥ A ∥ F = ∑ i , j A i j 2 \|\mathbf{A}\|F = \sqrt{\sum{i,j} A_{ij}^2} ∥A∥F=i,j∑Aij2

python 复制代码
A = np.array([[1, 2],
              [3, 4]])

frobenius = np.linalg.norm(A, ord='fro')
print(f"Frobenius 范数: {frobenius:.4f}")
print(f"手动计算: {np.sqrt(np.sum(A**2)):.4f}")

输出:

复制代码
Frobenius 范数: 5.4772
手动计算: 5.4772

A.2.4 矩阵类型

对称矩阵 : A = A T \mathbf{A} = \mathbf{A}^T A=AT

python 复制代码
A = np.array([[1, 2, 3],
              [2, 4, 5],
              [3, 5, 6]])
print(f"对称: {np.allclose(A, A.T)}")

输出:

复制代码
对称: True

对角矩阵 :主对角线之外的元素皆为 0 的矩阵。一个对角矩阵也可以记为 A = diag ( a ) \mathbf{A} = \text{diag}(\mathbf{a}) A=diag(a)。

A x = diag ( a ) x = a ⊙ x \mathbf{A}\mathbf{x} = \text{diag}(\mathbf{a})\mathbf{x} = \mathbf{a} \odot \mathbf{x} Ax=diag(a)x=a⊙x

python 复制代码
a = np.array([1, 2, 3])
A = np.diag(a)
x = np.array([4, 5, 6])

print(f"对角矩阵 diag([1,2,3]):\n{A}")
print(f"diag(a)·x = {A @ x}")
print(f"a ⊙ x = {a * x}")  # 等价于逐元素乘积

输出:

复制代码
对角矩阵 diag([1,2,3]):
[[1 0 0]
 [0 2 0]
 [0 0 3]]
diag(a)·x = [ 4 10 18]
a ⊙ x = [ 4 10 18]

单位矩阵 :主对角线元素为 1 的对角矩阵。 A I = I A = A \mathbf{A}\mathbf{I} = \mathbf{I}\mathbf{A} = \mathbf{A} AI=IA=A

python 复制代码
I = np.eye(3)
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9]])
print(f"A·I == A: {np.allclose(A @ I, A)}")
print(f"I·A == A: {np.allclose(I @ A, A)}")

输出:

复制代码
A·I == A: True
I·A == A: True

逆矩阵 :对于方块矩阵 A \mathbf{A} A,若存在 A − 1 \mathbf{A}^{-1} A−1 使得:

A A − 1 = A − 1 A = I \mathbf{A}\mathbf{A}^{-1} = \mathbf{A}^{-1}\mathbf{A} = \mathbf{I} AA−1=A−1A=I

则 A − 1 \mathbf{A}^{-1} A−1 称为 A \mathbf{A} A 的逆矩阵。

python 复制代码
A = np.array([[1, 2],
              [3, 4]])
A_inv = np.linalg.inv(A)

print(f"A =\n{A}")
print(f"A^(-1) =\n{A_inv}")
print(f"A·A^(-1) =\n{A @ A_inv}")

# 行列式为0的矩阵不可逆
B = np.array([[1, 2],
              [2, 4]])
try:
    B_inv = np.linalg.inv(B)
except np.linalg.LinAlgError:
    print("\ndet(B)=0, B不可逆")

输出:

复制代码
A =
[[1 2]
 [3 4]]
A^(-1) =
[[-2.   1. ]
 [ 1.5 -0.5]]
A·A^(-1) =
[[1.00000000e+00 0.00000000e+00]
 [8.88178420e-16 1.00000000e+00]]

det(B)=0, B不可逆

正定矩阵 :对于对称矩阵 A \mathbf{A} A,如果对于所有非零向量 x \mathbf{x} x,都满足 x T A x > 0 \mathbf{x}^T\mathbf{A}\mathbf{x} > 0 xTAx>0,则 A \mathbf{A} A 为正定矩阵。

python 复制代码
A = np.array([[2, 1],
              [1, 2]])

# 检查正定性:所有特征值大于0
eigenvalues = np.linalg.eigvals(A)
print(f"特征值: {eigenvalues}")
print(f"正定: {np.all(eigenvalues > 0)}")

# 对任意向量x验证
x = np.array([1, -1])
quad_form = x @ A @ x
print(f"x^T·A·x = {quad_form} (> 0: {quad_form > 0})")

输出:

复制代码
特征值: [3. 1.]
正定: True
x^T·A·x = 2 (> 0: True)

正交矩阵 : A − 1 = A T \mathbf{A}^{-1} = \mathbf{A}^T A−1=AT,即 A T A = I \mathbf{A}^T\mathbf{A} = \mathbf{I} ATA=I。

python 复制代码
# 旋转矩阵是正交矩阵
theta = np.pi / 4  # 45度
A = np.array([[np.cos(theta), -np.sin(theta)],
              [np.sin(theta),  np.cos(theta)]])
print(f"A^T·A = I: {np.allclose(A.T @ A, np.eye(2))}")
print(f"列向量模长=1: {np.linalg.norm(A[:, 0]):.6f}")
print(f"列向量互相正交: {np.dot(A[:, 0], A[:, 1]):.10f}")

输出:

复制代码
A^T·A = I: True
列向量模长=1: 1.000000
列向量互相正交: 0.0000000000

Gram 矩阵 :向量组 x 1 , . . . , x k \mathbf{x}_1, ..., \mathbf{x}k x1,...,xk 的 Gram 矩阵 G \mathbf{G} G 满足 G i j = ⟨ x i , x j ⟩ G{ij} = \langle \mathbf{x}_i, \mathbf{x}_j \rangle Gij=⟨xi,xj⟩。

python 复制代码
X = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # 3个2维向量
G = X @ X.T  # Gram矩阵
print(f"Gram 矩阵:\n{G}")

输出:

复制代码
Gram 矩阵:
[[ 5 11 17]
 [11 25 39]
 [17 39 61]]

A.2.5 特征值与特征向量

对一个 n × n n \times n n×n 矩阵 A \mathbf{A} A,如果存在标量 λ \lambda λ 和非零向量 v \mathbf{v} v 满足:

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

则 λ \lambda λ 和 v \mathbf{v} v 分别称为矩阵 A \mathbf{A} A 的特征值和特征向量。

python 复制代码
A = np.array([[4, 1],
              [2, 3]])

eigenvalues, eigenvectors = np.linalg.eig(A)

print(f"矩阵 A =\n{A}\n")
for i in range(len(eigenvalues)):
    λ = eigenvalues[i]
    v = eigenvectors[:, i]
    print(f"特征值 λ{i+1} = {λ:.4f}")
    print(f"特征向量 v{i+1} = {v}")
    print(f"验证: A·v = {A @ v}, λ·v = {λ * v}")
    print(f"相等: {np.allclose(A @ v, λ * v)}\n")

输出:

复制代码
矩阵 A =
[[4 1]
 [2 3]]

特征值 λ1 = 5.0000
特征向量 v1 = [0.70710678 0.70710678]
验证: A·v = [3.53553391 3.53553391], λ·v = [3.53553391 3.53553391]
相等: True

特征值 λ2 = 2.0000
特征向量 v2 = [-0.4472136   0.89442719]
验证: A·v = [-0.89442719  1.78885438], λ·v = [-0.89442719  1.78885438]
相等: True

对于实对称矩阵,存在 n 个互相正交的单位特征向量:

python 复制代码
# 实对称矩阵
A_sym = np.array([[2, 1],
                  [1, 2]])
evals, evecs = np.linalg.eigh(A_sym)  # 使用 eigh 更适合对称矩阵
print(f"特征值: {evals}")
print(f"特征向量正交: {np.allclose(np.dot(evecs[:, 0], evecs[:, 1]), 0)}")

输出:

复制代码
特征值: [1. 3.]
特征向量正交: True

A.2.6 矩阵分解

A.2.6.1 特征分解(Eigendecomposition)

一个 n × n n \times n n×n 方块矩阵 A \mathbf{A} A 的特征分解定义为:

A = Q Λ Q − 1 \mathbf{A} = \mathbf{Q}\mathbf{\Lambda}\mathbf{Q}^{-1} A=QΛQ−1

其中 Q \mathbf{Q} Q 的每一列为 A \mathbf{A} A 的特征向量, Λ \mathbf{\Lambda} Λ 为对角矩阵,对角元素为特征值。

如果 A \mathbf{A} A 为实对称矩阵,可分解为:

A = Q Λ Q T \mathbf{A} = \mathbf{Q}\mathbf{\Lambda}\mathbf{Q}^T A=QΛQT

其中 Q \mathbf{Q} Q 为正交矩阵。

python 复制代码
A = np.array([[4, 1],
              [2, 3]])

eigenvalues, eigenvectors = np.linalg.eig(A)
Λ = np.diag(eigenvalues)
Q = eigenvectors

# 验证 A = Q·Λ·Q^{-1}
A_reconstructed = Q @ Λ @ np.linalg.inv(Q)
print(f"A 重建后:\n{A_reconstructed}")
print(f"与原矩阵相等: {np.allclose(A, A_reconstructed)}")

# 对称矩阵的情况
A_sym = np.array([[2, 1],
                  [1, 2]])
evals, evecs = np.linalg.eigh(A_sym)
A_recon_sym = evecs @ np.diag(evals) @ evecs.T
print(f"\n对称矩阵分解 A=QΛQ^T 成立: {np.allclose(A_sym, A_recon_sym)}")

输出:

复制代码
A 重建后:
[[4. 1.]
 [2. 3.]]
与原矩阵相等: True

对称矩阵分解 A=QΛQ^T 成立: True
A.2.6.2 奇异值分解(SVD)

一个 m × n m \times n m×n 矩阵 A \mathbf{A} A 的奇异值分解定义为:

A = U Σ V T \mathbf{A} = \mathbf{U}\mathbf{\Sigma}\mathbf{V}^T A=UΣVT

其中 U ∈ R m × m \mathbf{U} \in \mathbb{R}^{m \times m} U∈Rm×m 和 V ∈ R n × n \mathbf{V} \in \mathbb{R}^{n \times n} V∈Rn×n 为正交矩阵, Σ ∈ R m × n \mathbf{\Sigma} \in \mathbb{R}^{m \times n} Σ∈Rm×n 为矩形对角矩阵。

python 复制代码
A = np.array([[1, 2, 3],
              [4, 5, 6],
              [7, 8, 9],
              [10,11,12]])  # 4x3矩阵

U, S, Vt = np.linalg.svd(A, full_matrices=True)

print(f"A (4x3):\n{A}\n")
print(f"U (4x4):\n{U}\n")
print(f"奇异值 S: {S}\n")
print(f"V^T (3x3):\n{Vt}\n")

# 验证 A = U·Σ·V^T
Σ = np.zeros((4, 3))
np.fill_diagonal(Σ, S)
A_recon = U @ Σ @ Vt
print(f"重建相等: {np.allclose(A, A_recon)}")

# 紧凑SVD (Compact SVD): A = U_r · Σ_r · V_r^T
# 其中 r = rank(A)
r = np.linalg.matrix_rank(A)
U_r = U[:, :r]
Σ_r = np.diag(S[:r])
V_r = Vt[:r, :].T
A_compact = U_r @ Σ_r @ V_r.T
print(f"紧凑SVD相等: {np.allclose(A, A_compact)}")
print(f"紧凑SVD节省空间: U_r={U_r.shape}, Σ_r={Σ_r.shape}, V_r={V_r.shape}")

# 截断SVD (Truncated SVD) - 只保留k个最大奇异值
k = 2
U_k = U[:, :k]
Σ_k = np.diag(S[:k])
V_k = Vt[:k, :].T
A_truncated = U_k @ Σ_k @ V_k.T
error = np.linalg.norm(A - A_truncated, ord='fro')
print(f"\n截断SVD (k={k}) Frobenius误差: {error:.4f}")
print(f"截断后矩阵:\n{A_truncated}")

输出:

复制代码
奇异值 S: [25.46240744  1.29066168  0.        ]

重建相等: True
紧凑SVD相等: True
紧凑SVD节省空间: U_r=(4, 2), Σ_r=(2, 2), V_r=(3, 2)

截断SVD (k=2) Frobenius误差: 0.0000
截断后矩阵: (近似重建,误差很小)

附录 B 微积分

微积分(Calculus)是研究函数的微分(Differentiation)、积分(Integration)及其相关应用的数学分支。

B.1 微分

B.1.1 导数

函数 f ( x ) f(x) f(x) 在点 x 0 x_0 x0 处的导数定义为:

f ′ ( x 0 ) = lim ⁡ Δ x → 0 f ( x 0 + Δ x ) − f ( x 0 ) Δ x f'(x_0) = \lim_{\Delta x \to 0} \frac{f(x_0 + \Delta x) - f(x_0)}{\Delta x} f′(x0)=Δx→0limΔxf(x0+Δx)−f(x0)

常函数、幂函数、指数函数、对数函数的导数如下:

函数类型 函数形式 导数
常函数 f ( x ) = c f(x)=c f(x)=c f ′ ( x ) = 0 f'(x)=0 f′(x)=0
幂函数 f ( x ) = x a f(x)=x^a f(x)=xa f ′ ( x ) = a x a − 1 f'(x)=ax^{a-1} f′(x)=axa−1
指数函数 f ( x ) = e x f(x)=e^x f(x)=ex f ′ ( x ) = e x f'(x)=e^x f′(x)=ex
对数函数 f ( x ) = ln ⁡ x f(x)=\ln x f(x)=lnx f ′ ( x ) = 1 / x f'(x)=1/x f′(x)=1/x
python 复制代码
import sympy as sp

x = sp.Symbol('x')

# 定义函数
funcs = {
    '常函数 f(x)=5': 5,
    '幂函数 f(x)=x³': x**3,
    '指数函数 f(x)=e^x': sp.exp(x),
    '对数函数 f(x)=ln(x)': sp.log(x),
}

print("函数及其导数:")
for name, f in funcs.items():
    f_prime = sp.diff(f, x)
    print(f"  {name}: f'(x) = {f_prime}")

# 具体点的导数值
x0 = 2
f = x**3
f_prime = sp.diff(f, x)
print(f"\nf(x)=x³ 在 x=2 处的导数: {float(f_prime.subs(x, x0))}")

输出:

复制代码
函数及其导数:
  常函数 f(x)=5: f'(x) = 0
  幂函数 f(x)=x³: f'(x) = 3*x**2
  指数函数 f(x)=e^x: f'(x) = exp(x)
  对数函数 f(x)=ln(x): f'(x) = 1/x

f(x)=x³ 在 x=2 处的导数: 12.0

高阶导数 :对导数继续求导得到高阶导数。如 f ′ ′ ( x ) f''(x) f′′(x) 为二阶导数。

python 复制代码
x = sp.Symbol('x')
f = x**4 + 2*x**3 + x**2

print(f"f(x) = {f}")
for order in range(1, 5):
    f_n = sp.diff(f, x, order)  # n阶导数
    print(f"f^({order})(x) = {f_n}")

输出:

复制代码
f(x) = x**4 + 2*x**3 + x**2
f^(1)(x) = 4*x**3 + 6*x**2 + 2*x
f^(2)(x) = 12*x**2 + 12*x + 2
f^(3)(x) = 24*x + 12
f^(4)(x) = 24

偏导数 :多元函数 f ( x 1 , x 2 , . . . , x n ) f(x_1, x_2, ..., x_n) f(x1,x2,...,xn) 关于变量 x i x_i xi 的导数:

∂ f ∂ x i = lim ⁡ h → 0 f ( . . . , x i + h , . . . ) − f ( . . . , x i , . . . ) h \frac{\partial f}{\partial x_i} = \lim_{h \to 0} \frac{f(..., x_i+h, ...)-f(..., x_i, ...)}{h} ∂xi∂f=h→0limhf(...,xi+h,...)−f(...,xi,...)

python 复制代码
x, y = sp.symbols('x y')
f = x**3 + 2*x*y + y**2

df_dx = sp.diff(f, x)   # 对x的偏导
df_dy = sp.diff(f, y)   # 对y的偏导

print(f"f(x,y) = {f}")
print(f"∂f/∂x = {df_dx}")
print(f"∂f/∂y = {df_dy}")

# 二阶偏导数
d2f_dx2 = sp.diff(f, x, 2)       # ∂²f/∂x²
d2f_dxdy = sp.diff(df_dx, y)     # ∂²f/∂x∂y (先x后y)

print(f"∂²f/∂x² = {d2f_dx2}")
print(f"∂²f/∂x∂y = {d2f_dxdy}")

输出:

复制代码
f(x,y) = x**3 + 2*x*y + y**2
∂f/∂x = 3*x**2 + 2*y
∂f/∂y = 2*x + 2*y
∂²f/∂x² = 6*x
∂²f/∂x∂y = 2

B.1.2 微分

可微函数一定连续,但连续函数不一定可微。例如 f ( x ) = ∣ x ∣ f(x) = |x| f(x)=∣x∣ 在 x = 0 x=0 x=0 处不可导。

python 复制代码
# 数值微分:使用中心差分法近似
def numerical_derivative(f, x, h=1e-5):
    """中心差分法求数值导数"""
    return (f(x + h) - f(x - h)) / (2 * h)

# 测试可微函数
f1 = lambda x: x**2
x0 = 3.0
actual = 2 * x0  # 精确导数 f'(x)=2x
numerical = numerical_derivative(f1, x0)
print(f"f(x)=x² 在 x=3:")
print(f"  精确导数: {actual}")
print(f"  数值导数: {numerical:.6f}")

# |x| 在 x=0 处不可导
f2 = lambda x: abs(x)
df_plus = numerical_derivative(f2, 0.001)
df_minus = numerical_derivative(f2, -0.001)
print(f"\nf(x)=|x|:")
print(f"  x=0.001 处导数的近似: {df_plus:.4f}")
print(f"  x=-0.001 处导数的近似: {df_minus:.4f}")
print(f"  左右导数不同,说明 x=0 处不可导")

输出:

复制代码
f(x)=x² 在 x=3:
  精确导数: 6.0
  数值导数: 6.000000

f(x)=|x|:
  x=0.001 处导数近似: 1.0000
  x=-0.001 处导数近似: -1.0000
  左右导数不同,说明 x=0 处不可导

B.1.3 泰勒公式

函数 f ( x ) f(x) f(x) 在 x 0 x_0 x0 处的 n 阶泰勒展开式:

f ( x ) = ∑ k = 0 n f ( k ) ( x 0 ) k ! ( x − x 0 ) k + R n ( x ) f(x) = \sum_{k=0}^n \frac{f^{(k)}(x_0)}{k!}(x - x_0)^k + R_n(x) f(x)=k=0∑nk!f(k)(x0)(x−x0)k+Rn(x)

其中 R n ( x ) R_n(x) Rn(x) 是泰勒公式的余项,是 ( x − x 0 ) n (x - x_0)^n (x−x0)n 的高阶无穷小。

python 复制代码
x, x0 = sp.symbols('x x0')
f = sp.sin(x)

# 在 x0=0 处的泰勒展开(即麦克劳林展开)
for n in [1, 3, 5, 7]:
    taylor = sp.series(f, x, 0, n+1).removeO()
    print(f"{n}阶泰勒展开: sin(x) ≈ {taylor}")

# 可视化泰勒逼近
import numpy as np

def taylor_sin(x, n):
    """计算 sin(x) 的 n 阶泰勒逼近"""
    result = 0
    for k in range(n+1):
        if k % 2 == 0:
            continue  # sin的展开只有奇数项
        term = (-1)**((k-1)//2) * x**k / np.math.factorial(k)
        result += term
    return result

x_vals = np.linspace(-np.pi, np.pi, 200)
true_vals = np.sin(x_vals)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x_vals, true_vals, 'k-', linewidth=2, label='sin(x) 精确值')
for n, style in [(1, '--'), (3, '-.'), (5, ':'), (9, '-')]:
    approx = taylor_sin(x_vals, n)
    ax.plot(x_vals, approx, style, linewidth=1.5, label=f'{n}阶逼近')
ax.legend()
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.set_title('sin(x) 的泰勒展开逼近')
ax.grid(True)
plt.show()

B.2 积分

积分是微分的逆过程。

函数 f ( x ) f(x) f(x) 的不定积分(原函数)记为:

∫ f ( x )   d x = F ( x ) + C \int f(x)\,dx = F(x) + C ∫f(x)dx=F(x)+C

其中 F ′ ( x ) = f ( x ) F'(x) = f(x) F′(x)=f(x)。

定积分(黎曼积分)定义为:

∫ a b f ( x )   d x = lim ⁡ max ⁡ Δ x i → 0 ∑ i = 1 n f ( ξ i ) Δ x i \int_a^b f(x)\,dx = \lim_{\max\Delta x_i \to 0} \sum_{i=1}^n f(\xi_i)\Delta x_i ∫abf(x)dx=maxΔxi→0limi=1∑nf(ξi)Δxi

python 复制代码
# 符号积分
x = sp.Symbol('x')
a = sp.Symbol('a', positive=True)

# 不定积分
funcs = [x**3, sp.exp(x), 1/x, sp.sin(x)]
for f in funcs:
    F = sp.integrate(f, x)
    print(f"∫ {f} dx = {F} + C")

# 定积分
b = sp.Symbol('b', positive=True)
f = sp.exp(-x)
result = sp.integrate(f, (x, 0, b))
print(f"\n∫_0^b e^(-x) dx = {result}")

# 具体定积分
result_specific = sp.integrate(sp.exp(-x), (x, 0, sp.oo))  # 从0到∞
print(f"∫_0^∞ e^(-x) dx = {result_specific}")

输出:

复制代码
∫ x**3 dx = x**4/4 + C
∫ exp(x) dx = exp(x) + C
∫ 1/x dx = log(x) + C
∫ sin(x) dx = -cos(x) + C

∫_0^b e^(-x) dx = 1 - exp(-b)
∫_0^∞ e^(-x) dx = 1
python 复制代码
# 数值积分
from scipy.integrate import quad

# 定积分 ∫_0^π sin(x) dx
result, error = quad(lambda x: np.sin(x), 0, np.pi)
print(f"∫_0^π sin(x) dx = {result:.6f} (精确值: 2)")

# 正态分布的概率密度积分
result, error = quad(lambda x: (1/np.sqrt(2*np.pi)) * np.exp(-x**2/2), -1.96, 1.96)
print(f"标准正态分布 P(-1.96 < X < 1.96) = {result:.6f}")

输出:

复制代码
∫_0^π sin(x) dx = 2.000000 (精确值: 2)
标准正态分布 P(-1.96 < X < 1.96) = 0.950004

B.3 矩阵微积分

矩阵微积分是多元微积分的一种表达方式,使用矩阵和向量来表示偏导数。本书采用分母布局

标量关于向量的偏导数

对于 n 维向量 x ∈ R n \mathbf{x} \in \mathbb{R}^n x∈Rn 和函数 f : R n → R f: \mathbb{R}^n \to \mathbb{R} f:Rn→R:

  • 分母布局(列向量形式)

∂ f ∂ x = ∂ f ∂ x 1 , ∂ f ∂ x 2 , . . . , ∂ f ∂ x n T \frac{\partial f}{\partial \mathbf{x}} = \left\\frac{\\partial f}{\\partial x_1}, \\frac{\\partial f}{\\partial x_2}, ..., \\frac{\\partial f}{\\partial x_n}\\right^T ∂x∂f=∂x1∂f,∂x2∂f,...,∂xn∂fT

  • 分子布局(行向量形式)

∂ f ∂ x = ∂ f ∂ x 1 , ∂ f ∂ x 2 , . . . , ∂ f ∂ x n \frac{\partial f}{\partial \mathbf{x}} = \left\\frac{\\partial f}{\\partial x_1}, \\frac{\\partial f}{\\partial x_2}, ..., \\frac{\\partial f}{\\partial x_n}\\right ∂x∂f=∂x1∂f,∂x2∂f,...,∂xn∂f

python 复制代码
# 符号计算梯度
x1, x2, x3 = sp.symbols('x1 x2 x3')
f = x1**2 + 2*x1*x2 + x2**2 + x3**3

# 计算梯度(分母布局)
grad = sp.Matrix([sp.diff(f, var) for var in (x1, x2, x3)])
print(f"f(x) = {f}")
print(f"梯度 (分母布局):\n{grad}")

# 数值计算梯度
x = np.array([1.0, 2.0, 3.0])
grad_val = np.array([2*x[0] + 2*x[1], 2*x[0] + 2*x[1], 3*x[2]**2])
print(f"在 x={x} 处的梯度: {grad_val}")

输出:

复制代码
f(x) = x1**2 + 2*x1*x2 + x2**2 + x3**3
梯度 (分母布局):
Matrix([[2*x1 + 2*x2], [2*x1 + 2*x2], [3*x3**2]])
在 x=[1. 2. 3.] 处的梯度: [ 6.  6. 27.]

向量关于向量的偏导数(雅可比矩阵)

对于 f : R n → R m \mathbf{f}: \mathbb{R}^n \to \mathbb{R}^m f:Rn→Rm,雅可比矩阵(分母布局)为 n × m n \times m n×m 矩阵:

∂ f ∂ x = ∂ f 1 ∂ x 1 ⋯ ∂ f m ∂ x 1 ⋮ ⋱ ⋮ ∂ f 1 ∂ x n ⋯ ∂ f m ∂ x n \frac{\partial \mathbf{f}}{\partial \mathbf{x}} = \begin{bmatrix} \frac{\partial f_1}{\partial x_1} & \cdots & \frac{\partial f_m}{\partial x_1} \\ \vdots & \ddots & \vdots \\ \frac{\partial f_1}{\partial x_n} & \cdots & \frac{\partial f_m}{\partial x_n} \end{bmatrix} ∂x∂f= ∂x1∂f1⋮∂xn∂f1⋯⋱⋯∂x1∂fm⋮∂xn∂fm

Hessian 矩阵

对于 f : R n → R f: \mathbb{R}^n \to \mathbb{R} f:Rn→R,Hessian 矩阵为 n × n n \times n n×n 矩阵:

H f = ∂ 2 f ∂ x ∂ x T = ∂ 2 f ∂ x 1 2 ⋯ ∂ 2 f ∂ x 1 ∂ x n ⋮ ⋱ ⋮ ∂ 2 f ∂ x n ∂ x 1 ⋯ ∂ 2 f ∂ x n 2 \mathbf{H}_f = \frac{\partial^2 f}{\partial \mathbf{x}\partial \mathbf{x}^T} = \begin{bmatrix} \frac{\partial^2 f}{\partial x_1^2} & \cdots & \frac{\partial^2 f}{\partial x_1\partial x_n} \\ \vdots & \ddots & \vdots \\ \frac{\partial^2 f}{\partial x_n\partial x_1} & \cdots & \frac{\partial^2 f}{\partial x_n^2} \end{bmatrix} Hf=∂x∂xT∂2f= ∂x12∂2f⋮∂xn∂x1∂2f⋯⋱⋯∂x1∂xn∂2f⋮∂xn2∂2f

python 复制代码
x1, x2 = sp.symbols('x1 x2')
f = x1**2 + x1*x2 + x2**2

# 梯度
grad = sp.Matrix([sp.diff(f, x1), sp.diff(f, x2)])
print(f"f(x) = {f}")
print(f"梯度:\n{grad}")

# Hessian矩阵
hessian = sp.hessian(f, (x1, x2))
print(f"\nHessian矩阵:\n{hessian}")

# 在具体点求值
point = {x1: 1, x2: 2}
print(f"\n在 (x1=1, x2=2) 处:")
print(f"  梯度值: {[float(grad[i].subs(point)) for i in range(2)]}")
print(f"  Hessian值:\n{np.array(hessian.subs(point)).astype(float)}")

输出:

复制代码
f(x) = x1**2 + x1*x2 + x2**2
梯度:
Matrix([[2*x1 + x2], [x1 + 2*x2]])

Hessian矩阵:
Matrix([[2, 1], [1, 2]])

在 (x1=1, x2=2) 处:
  梯度值: [4.0, 5.0]
  Hessian值:
[[2. 1.]
 [1. 2.]]

B.3.1 导数法则

加(减)法则 :若 x ∈ R n x \in \mathbb{R}^n x∈Rn, a , b ∈ R n \mathbf{a}, \mathbf{b} \in \mathbb{R}^n a,b∈Rn, f ( x ) = a T x ± b T x f(\mathbf{x}) = \mathbf{a}^T\mathbf{x} \pm \mathbf{b}^T\mathbf{x} f(x)=aTx±bTx,则:

∂ f ∂ x = a ± b \frac{\partial f}{\partial \mathbf{x}} = \mathbf{a} \pm \mathbf{b} ∂x∂f=a±b

乘法法则

  1. 若 f ( x ) = x T A x f(\mathbf{x}) = \mathbf{x}^T\mathbf{A}\mathbf{x} f(x)=xTAx,其中 A \mathbf{A} A 与 x \mathbf{x} x 无关,则:

∂ f ∂ x = ( A + A T ) x \frac{\partial f}{\partial \mathbf{x}} = (\mathbf{A} + \mathbf{A}^T)\mathbf{x} ∂x∂f=(A+AT)x

  1. 若 A \mathbf{A} A 对称,则 ∂ f ∂ x = 2 A x \frac{\partial f}{\partial \mathbf{x}} = 2\mathbf{A}\mathbf{x} ∂x∂f=2Ax
python 复制代码
# 验证乘法法则
n = 3
x = np.array([1.0, 2.0, 3.0])
A = np.array([[2, 1, 0],
              [1, 3, 1],
              [0, 1, 2]])  # 对称矩阵

# f(x) = x^T·A·x
f = x @ A @ x
print(f"f(x) = x^T·A·x = {f:.4f}")

# 梯度 ∂f/∂x = 2Ax (A对称时)
grad = 2 * A @ x
print(f"梯度 ∂f/∂x = 2Ax = {grad}")

# 数值验证
h = 1e-5
grad_num = np.zeros(n)
for i in range(n):
    x_plus = x.copy()
    x_plus[i] += h
    f_plus = x_plus @ A @ x_plus
    grad_num[i] = (f_plus - f) / h
print(f"数值梯度: {grad_num}")
print(f"解析梯度 ≈ 数值梯度: {np.allclose(grad, grad_num, atol=1e-4)}")

输出:

复制代码
f(x) = x^T·A·x = 41.0000
梯度 ∂f/∂x = 2Ax = [ 8. 22. 14.]
数值梯度: [ 8.00001 22.00001 14.00001]
解析梯度 ≈ 数值梯度: True

链式法则

若 x → y → z \mathbf{x} \to \mathbf{y} \to z x→y→z( y = g ( x ) \mathbf{y} = g(\mathbf{x}) y=g(x), z = f ( y ) z = f(\mathbf{y}) z=f(y)),则:

∂ z ∂ x = ∂ y ∂ x ⋅ ∂ z ∂ y \frac{\partial z}{\partial \mathbf{x}} = \frac{\partial \mathbf{y}}{\partial \mathbf{x}} \cdot \frac{\partial z}{\partial \mathbf{y}} ∂x∂z=∂x∂y⋅∂y∂z

python 复制代码
# 链式法则验证
# z = ||Wx||²,其中 y = Wx, z = ||y||²
W = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # 3x2
x = np.array([2, 3])    # 2维

# 前向计算
y = W @ x               # 3维
z = np.sum(y**2)        # 标量

# 链式法则: ∂z/∂x = ∂z/∂y · ∂y/∂x
# ∂z/∂y = 2y (分母布局,列向量)
# ∂y/∂x = W^T (分母布局)
dz_dy = 2 * y           # 3维列向量
dy_dx = W               # 3x2矩阵,∂y/∂x = W^T (分母布局) 
# 分母布局: ∂z/∂x = (∂y/∂x) · (∂z/∂y) = W^T · (2y)
dz_dx = W.T @ dz_dy     # 2维

print(f"链式法则计算的梯度: {dz_dx}")

# 数值验证
h = 1e-5
dz_dx_num = np.zeros(2)
for i in range(2):
    x_plus = x.copy()
    x_plus[i] += h
    y_plus = W @ x_plus
    z_plus = np.sum(y_plus**2)
    dz_dx_num[i] = (z_plus - z) / h
print(f"数值梯度: {dz_dx_num}")

输出:

复制代码
链式法则计算的梯度: [856 1192]
数值梯度: [856.000035 1192.000044]

B.4 常见函数的导数

B.4.1 向量函数及其导数

∂ x ∂ x = I \frac{\partial \mathbf{x}}{\partial \mathbf{x}} = \mathbf{I} ∂x∂x=I

∂ ∥ x ∥ 2 ∂ x = 2 x \frac{\partial \|\mathbf{x}\|^2}{\partial \mathbf{x}} = 2\mathbf{x} ∂x∂∥x∥2=2x

∂ ( a T x ) ∂ x = a \frac{\partial (\mathbf{a}^T\mathbf{x})}{\partial \mathbf{x}} = \mathbf{a} ∂x∂(aTx)=a

python 复制代码
# 验证常见导数公式
x = np.array([1.0, 2.0, 3.0])
a = np.array([3.0, 2.0, 1.0])

# 1. ∂x/∂x = I
print(f"∂x/∂x = I")

# 2. ∂||x||²/∂x = 2x
grad_norm2 = 2 * x
f = np.sum(x**2)
h = 1e-5
grad_num = np.array([(np.sum((x + h*np.eye(3)[i])**2) - f) / h for i in range(3)])
print(f"∂||x||²/∂x = {grad_norm2}")
print(f"数值验证:        {grad_num}")

# 3. ∂(a^T·x)/∂x = a
grad_linear = a
f2 = np.dot(a, x)
grad_num2 = np.array([(np.dot(a, x + h*np.eye(3)[i]) - f2) / h for i in range(3)])
print(f"\n∂(a^T·x)/∂x = {grad_linear}")
print(f"数值验证:        {grad_num2}")

输出:

复制代码
∂x/∂x = I
∂||x||²/∂x = [2. 4. 6.]
数值验证:        [1.99999 3.99999 5.99999]

∂(a^T·x)/∂x = [3. 2. 1.]
数值验证:        [3. 2. 1.]

B.4.2 Logistic 函数

标准 Logistic 函数(Sigmoid):

σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1

导数:

σ ′ ( x ) = σ ( x ) ( 1 − σ ( x ) ) \sigma'(x) = \sigma(x)(1 - \sigma(x)) σ′(x)=σ(x)(1−σ(x))

当输入为 n 维向量 x \mathbf{x} x 时,其导数为对角矩阵:

∂ σ ( x ) ∂ x = diag ( σ ( x ) ⊙ ( 1 − σ ( x ) ) ) \frac{\partial \sigma(\mathbf{x})}{\partial \mathbf{x}} = \text{diag}(\sigma(\mathbf{x}) \odot (1 - \sigma(\mathbf{x}))) ∂x∂σ(x)=diag(σ(x)⊙(1−σ(x)))

python 复制代码
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    s = sigmoid(x)
    return s * (1 - s)

# 测试
x_val = np.linspace(-5, 5, 100)
s = sigmoid(x_val)
s_prime = sigmoid_derivative(x_val)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

ax1.plot(x_val, s, 'b-', linewidth=2)
ax1.set_title('Sigmoid 函数 σ(x)')
ax1.set_xlabel('x'); ax1.set_ylabel('σ(x)')
ax1.grid(True)
ax1.axhline(0.5, color='gray', linestyle='--', alpha=0.5)
ax1.axvline(0, color='gray', linestyle='--', alpha=0.5)

ax2.plot(x_val, s_prime, 'r-', linewidth=2)
ax2.set_title("Sigmoid 导数 σ'(x) = σ(x)(1-σ(x))")
ax2.set_xlabel('x'); ax2.set_ylabel("σ'(x)")
ax2.grid(True)

plt.tight_layout()
plt.show()

# 向量输入的导数(对角矩阵)
x_vec = np.array([-1.0, 0.0, 2.0])
s_vec = sigmoid(x_vec)
diag_derivative = np.diag(s_vec * (1 - s_vec))
print(f"x = {x_vec}")
print(f"σ(x) = {s_vec}")
print(f"导数对角矩阵:\n{diag_derivative}")

输出:

复制代码
x = [-1.  0.  2.]
σ(x) = [0.26894142 0.5        0.88079708]
导数对角矩阵:
[[0.19661193 0.         0.        ]
 [0.         0.25       0.        ]
 [0.         0.         0.10499359]]

B.4.3 Softmax 函数

对于 K 个标量 x 1 , . . . , x K x_1, ..., x_K x1,...,xK:

softmax ( x k ) = e x k ∑ j = 1 K e x j \text{softmax}(x_k) = \frac{e^{x_k}}{\sum_{j=1}^K e^{x_j}} softmax(xk)=∑j=1Kexjexk

∑ k = 1 K softmax ( x k ) = 1 \sum_{k=1}^K \text{softmax}(x_k) = 1 k=1∑Ksoftmax(xk)=1

向量形式: S ( x ) = e x 1 T e x \mathbf{S}(\mathbf{x}) = \frac{e^{\mathbf{x}}}{\mathbf{1}^T e^{\mathbf{x}}} S(x)=1Texex

导数(雅可比矩阵):

∂ S i ∂ x j = S i ( δ i j − S j ) \frac{\partial S_i}{\partial x_j} = S_i(\delta_{ij} - S_j) ∂xj∂Si=Si(δij−Sj)

其中 δ i j \delta_{ij} δij 是 Kronecker delta( i = j i=j i=j 时为 1,否则为 0)。

python 复制代码
def softmax(x):
    """数值稳定的 softmax 实现"""
    x_shifted = x - np.max(x)  # 防溢出
    exp_x = np.exp(x_shifted)
    return exp_x / np.sum(exp_x)

def softmax_derivative(x):
    """Softmax 的雅可比矩阵"""
    s = softmax(x).reshape(-1, 1)
    return np.diagflat(s) - s @ s.T

# 示例
x = np.array([2.0, 1.0, 0.1])
s = softmax(x)
print(f"x = {x}")
print(f"softmax(x) = {s}")
print(f"sum = {np.sum(s):.4f}")  # 应该为1

# 雅可比矩阵
J = softmax_derivative(x)
print(f"\n雅可比矩阵 (3x3):\n{J}")
print(f"每列和: {J.sum(axis=0)}")  # 应为0

输出:

复制代码
x = [2.  1.  0.1]
softmax(x) = [0.65900114 0.24243297 0.09856589]
sum = 1.0000

雅可比矩阵 (3x3):
[[ 0.22471878 -0.15976147 -0.06495731]
 [-0.15976147  0.1836591  -0.02389764]
 [-0.06495731 -0.02389764  0.08885495]]
每列和: [0. 0. 0.]

附录 C 数学优化

数学优化问题:给定目标函数 f : R n → R f: \mathbb{R}^n \to \mathbb{R} f:Rn→R,寻找变量 x ∗ \mathbf{x}^* x∗ 使得 f ( x ) f(\mathbf{x}) f(x) 在可行域内最小(或最大)。

C.1 数学优化的类型

  • 离散优化 vs 连续优化:输入变量是否为连续实数
  • 无约束优化 vs 约束优化:是否有等式或不等式约束
  • 线性优化 vs 非线性优化:目标函数和约束函数的线性性

凸函数 :满足 f ( θ x + ( 1 − θ ) y ) ≤ θ f ( x ) + ( 1 − θ ) f ( y ) f(\theta\mathbf{x} + (1-\theta)\mathbf{y}) \le \theta f(\mathbf{x}) + (1-\theta)f(\mathbf{y}) f(θx+(1−θ)y)≤θf(x)+(1−θ)f(y),其中 θ ∈ 0 , 1 \theta \in 0,1 θ∈0,1

python 复制代码
# 凸函数示例
def f(x):
    return x**2

x = np.linspace(-3, 3, 100)
theta = 0.3
x1, x2 = -2, 2

fig, ax = plt.subplots(figsize=(8, 6))
ax.plot(x, f(x), 'b-', linewidth=2, label='f(x)=x²')
ax.scatter([x1, x2], [f(x1), f(x2)], c='red', s=80, zorder=5)
ax.scatter([theta*x1 + (1-theta)*x2], [f(theta*x1 + (1-theta)*x2)], 
           c='green', s=80, zorder=5, marker='s')
ax.scatter([theta*x1 + (1-theta)*x2], [theta*f(x1) + (1-theta)*f(x2)],
           c='orange', s=80, zorder=5, marker='^')

# 连线
ax.plot([x1, x2], [f(x1), f(x2)], 'r--', alpha=0.5)
ax.legend()
ax.set_title('凸函数:f(θx₁+(1-θ)x₂) ≤ θf(x₁)+(1-θ)f(x₂)')
ax.grid(True)
plt.show()

# 凸性验证
fx_interp = f(theta*x1 + (1-theta)*x2)  # f(θx₁+(1-θ)x₂)
interp_f = theta*f(x1) + (1-theta)*f(x2)  # θf(x₁)+(1-θ)f(x₂)
print(f"f(θx₁+(1-θ)x₂) = {fx_interp:.2f}")
print(f"θf(x₁)+(1-θ)f(x₂) = {interp_f:.2f}")
print(f"凸性满足: {fx_interp <= interp_f}")

输出:

复制代码
f(θx₁+(1-θ)x₂) = 0.64
θf(x₁)+(1-θ)f(x₂) = 4.00
凸性满足: True

C.2 优化算法

C.2.1 全局最小解和局部最小解

局部最小解 x ∗ \mathbf{x}^* x∗:存在 δ > 0 \delta > 0 δ>0,对于所有满足 ∥ x − x ∗ ∥ < δ \|\mathbf{x} - \mathbf{x}^*\| < \delta ∥x−x∗∥<δ 的 x \mathbf{x} x,都有 f ( x ∗ ) ≤ f ( x ) f(\mathbf{x}^*) \le f(\mathbf{x}) f(x∗)≤f(x)。

全局最小解 x ∗ \mathbf{x}^* x∗:对所有 x \mathbf{x} x,都有 f ( x ∗ ) ≤ f ( x ) f(\mathbf{x}^*) \le f(\mathbf{x}) f(x∗)≤f(x)。

局部最小解的判定条件

  1. 一阶必要条件 : ∇ f ( x ∗ ) = 0 \nabla f(\mathbf{x}^*) = 0 ∇f(x∗)=0
  2. 二阶必要条件 : ∇ f ( x ∗ ) = 0 \nabla f(\mathbf{x}^*) = 0 ∇f(x∗)=0 且 H f ( x ∗ ) \mathbf{H}_f(\mathbf{x}^*) Hf(x∗) 为半正定

C.2.2 梯度下降法

梯度下降法用于求解无约束优化的最小值问题。

迭代公式

x t + 1 = x t − α ∇ f ( x t ) \mathbf{x}_{t+1} = \mathbf{x}_t - \alpha \nabla f(\mathbf{x}_t) xt+1=xt−α∇f(xt)

其中 α \alpha α 为学习率(步长)。

python 复制代码
def gradient_descent(f, grad_f, x0, learning_rate=0.1, max_iter=100, tol=1e-6):
    """梯度下降法"""
    x = x0.copy()
    history = [x.copy()]
    
    for i in range(max_iter):
        g = grad_f(x)
        x_new = x - learning_rate * g
        history.append(x_new.copy())
        
        if np.linalg.norm(x_new - x) < tol:
            break
        x = x_new
    
    return x, np.array(history)

# 示例:f(x,y) = (x-3)² + (y+2)²,最小值在 (3, -2)
def f_2d(x):
    return (x[0] - 3)**2 + (x[1] + 2)**2

def grad_f_2d(x):
    return np.array([2*(x[0] - 3), 2*(x[1] + 2)])

x0 = np.array([0.0, 0.0])
x_opt, history = gradient_descent(f_2d, grad_f_2d, x0, learning_rate=0.3)

print(f"初始点: {x0}")
print(f"最优解: {x_opt}")
print(f"迭代次数: {len(history) - 1}")
print(f"最小值 f(x*) = {f_2d(x_opt):.6f}")

# 可视化优化路径
fig, ax = plt.subplots(figsize=(8, 7))
x_range = np.linspace(-1, 6, 50)
y_range = np.linspace(-5, 3, 50)
X, Y = np.meshgrid(x_range, y_range)
Z = (X - 3)**2 + (Y + 2)**2
contour = ax.contour(X, Y, Z, levels=20, cmap='viridis')
ax.clabel(contour, inline=True, fontsize=8)

ax.plot(history[:, 0], history[:, 1], 'r-o', markersize=5, linewidth=1.5, label='优化路径')
ax.scatter(*x0, c='blue', s=100, marker='s', label='起点', zorder=5)
ax.scatter(*x_opt, c='red', s=100, marker='*', label='终点', zorder=5)
ax.legend()
ax.set_xlabel('x'); ax.set_ylabel('y')
ax.set_title('梯度下降法优化路径')
ax.grid(True)
plt.show()

输出:

复制代码
初始点: [0. 0.]
最优解: [ 2.99999969 -1.99999849]
迭代次数: 27
最小值 f(x*) = 0.000000

学习率对收敛的影响

python 复制代码
# 不同学习率的效果
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
lrs = [0.01, 0.3, 1.2]

for ax, lr in zip(axes, lrs):
    _, history = gradient_descent(f_2d, grad_f_2d, x0, learning_rate=lr)
    ax.plot(history[:, 0], history[:, 1], 'r-o', markersize=4)
    ax.scatter(*x0, c='blue', s=60, marker='s', label='起点')
    ax.scatter(3, -2, c='green', s=60, marker='*', label='最优')
    ax.contour(X, Y, Z, levels=15, cmap='viridis', alpha=0.5)
    ax.set_title(f'学习率 α={lr}, 迭代{len(history)-1}次')
    ax.set_xlabel('x'); ax.set_ylabel('y')
    ax.legend()
    ax.grid(True)

plt.tight_layout()
plt.show()

C.3 拉格朗日乘数法与 KKT 条件

等式约束优化问题

对于等式约束优化问题:

min ⁡ x f ( x ) s.t. g ( x ) = 0 \min_{\mathbf{x}} f(\mathbf{x}) \quad \text{s.t.} \quad g(\mathbf{x}) = 0 xminf(x)s.t.g(x)=0

构造拉格朗日函数:

L ( x , λ ) = f ( x ) + λ g ( x ) \mathcal{L}(\mathbf{x}, \lambda) = f(\mathbf{x}) + \lambda g(\mathbf{x}) L(x,λ)=f(x)+λg(x)

最优解满足:

∇ x L = 0 , ∂ L ∂ λ = 0 \nabla_{\mathbf{x}}\mathcal{L} = 0, \quad \frac{\partial \mathcal{L}}{\partial \lambda} = 0 ∇xL=0,∂λ∂L=0

python 复制代码
# 用拉格朗日乘数法求解约束优化
# min f(x,y) = x² + y², s.t. x + y = 1
x, y, λ = sp.symbols('x y λ')

f = x**2 + y**2
g = x + y - 1
L = f + λ * g  # 拉格朗日函数

# 求驻点
eq1 = sp.diff(L, x)
eq2 = sp.diff(L, y)
eq3 = sp.diff(L, λ)

solution = sp.solve([eq1, eq2, eq3], [x, y, λ], dict=True)
print(f"拉格朗日函数: L = {L}")
print(f"驻点条件: ∂L/∂x=0, ∂L/∂y=0, ∂L/∂λ=0")
print(f"解: {solution}")
print(f"\n最优解: x* = {float(solution[0][x])}, y* = {float(solution[0][y])}")
print(f"λ* = {float(solution[0][λ])}")
print(f"最小值 f(x*,y*) = {float(f.subs({x: solution[0][x], y: solution[0][y]}))}")

输出:

复制代码
拉格朗日函数: L = x**2 + y**2 + λ*(x + y - 1)
驻点条件: ∂L/∂x=0, ∂L/∂y=0, ∂L/∂λ=0
解: [{x: 1/2, y: 1/2, λ: -1}]

最优解: x* = 0.5, y* = 0.5
λ* = -1.0
最小值 f(x*,y*) = 0.5

不等式约束优化问题

对于一般约束优化问题:

min ⁡ x f ( x ) s.t. g i ( x ) = 0 , h j ( x ) ≤ 0 \min_{\mathbf{x}} f(\mathbf{x}) \quad \text{s.t.} \quad g_i(\mathbf{x}) = 0,\ h_j(\mathbf{x}) \le 0 xminf(x)s.t.gi(x)=0, hj(x)≤0

拉格朗日函数:

L ( x , λ , μ ) = f ( x ) + ∑ i λ i g i ( x ) + ∑ j μ j h j ( x ) \mathcal{L}(\mathbf{x}, \boldsymbol{\lambda}, \boldsymbol{\mu}) = f(\mathbf{x}) + \sum_i \lambda_i g_i(\mathbf{x}) + \sum_j \mu_j h_j(\mathbf{x}) L(x,λ,μ)=f(x)+i∑λigi(x)+j∑μjhj(x)

其中 μ j ≥ 0 \mu_j \ge 0 μj≥0。

KKT 条件(最优性的必要条件)

  1. ∇ f ( x ∗ ) + ∑ i λ i ∇ g i ( x ∗ ) + ∑ j μ j ∇ h j ( x ∗ ) = 0 \nabla f(\mathbf{x}^*) + \sum_i \lambda_i \nabla g_i(\mathbf{x}^*) + \sum_j \mu_j \nabla h_j(\mathbf{x}^*) = 0 ∇f(x∗)+∑iλi∇gi(x∗)+∑jμj∇hj(x∗)=0(平稳性)
  2. g i ( x ∗ ) = 0 g_i(\mathbf{x}^*) = 0 gi(x∗)=0(等式约束满足)
  3. h j ( x ∗ ) ≤ 0 h_j(\mathbf{x}^*) \le 0 hj(x∗)≤0(不等式约束满足)
  4. μ j ≥ 0 \mu_j \ge 0 μj≥0(对偶可行性)
  5. μ j h j ( x ∗ ) = 0 \mu_j h_j(\mathbf{x}^*) = 0 μjhj(x∗)=0(互补松弛条件)
python 复制代码
# 互补松弛条件示例
# min f(x) = (x-2)², s.t. x ≥ 0, x ≤ 5
# 等价于: h₁(x) = -x ≤ 0, h₂(x) = x-5 ≤ 0

# 无约束最优解是 x=2,在约束 [0,5] 内
# 因此 μ₁=0, μ₂=0 (互补松弛: 内部解时乘子为0)

x = sp.Symbol('x')
f = (x-2)**2

# 最优解:x* = 2
x_star = 2
print(f"无约束最优解: x* = {x_star}")
print(f"约束: 0 ≤ x ≤ 5")
print(f"解在约束内部 → μ₁=0, μ₂=0 (互补松弛)")
print(f"最小值: f(2) = {f.subs(x, x_star)}")

输出:

复制代码
无约束最优解: x* = 2
约束: 0 ≤ x ≤ 5
解在约束内部 → μ₁=0, μ₂=0 (互补松弛)
最小值: f(2) = 0

附录 D 概率论

D.1 样本空间

样本空间是一个随机试验所有可能结果的集合。

python 复制代码
# 样本空间示例
coin_space = {'正面', '反面'}
dice_space = {1, 2, 3, 4, 5, 6}
print(f"硬币样本空间: {coin_space}")
print(f"骰子样本空间: {dice_space}")

# 笛卡尔乘积
from itertools import product
cards_rank = {'A', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K'}
cards_suit = {'♠', '♥', '♣', '♦'}
deck = set(product(cards_rank, cards_suit))
print(f"扑克牌总数: {len(deck)}")

输出:

复制代码
硬币样本空间: {'反面', '正面'}
骰子样本空间: {1, 2, 3, 4, 5, 6}
扑克牌总数: 52

D.2 事件和概率

概率(Probability)表示随机事件发生的可能性大小,为 0 到 1 之间的实数。

D.2.1 随机变量

伯努利分布(Bernoulli Distribution)

P ( X = 1 ) = p , P ( X = 0 ) = 1 − p P(X=1)=p,\quad P(X=0)=1-p P(X=1)=p,P(X=0)=1−p

python 复制代码
# 伯努利分布
p = 0.7
bernoulli = stats.bernoulli(p)

# 采样
samples = bernoulli.rvs(size=1000)
unique, counts = np.unique(samples, return_counts=True)
print(f"伯努利分布 p={p}")
print(f"P(X=0)={counts[0]/1000:.3f}, P(X=1)={counts[1]/1000:.3f}")
print(f"期望: {bernoulli.mean()}, 方差: {bernoulli.var()}")

输出:

复制代码
伯努利分布 p=0.7
P(X=0)=0.281, P(X=1)=0.719
期望: 0.7, 方差: 0.21

二项分布(Binomial Distribution):n 次伯努利试验中成功次数的分布。

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

其中 ( n k ) = n ! k ! ( n − k ) ! \binom{n}{k} = \frac{n!}{k!(n-k)!} (kn)=k!(n−k)!n!。

python 复制代码
n, p = 10, 0.5
binom = stats.binom(n, p)

k = np.arange(0, n+1)
pmf = binom.pmf(k)

fig, ax = plt.subplots(figsize=(10, 5))
ax.bar(k, pmf, alpha=0.7, color='steelblue', edgecolor='white')
ax.set_xlabel('k (成功次数)')
ax.set_ylabel('P(X=k)')
ax.set_title(f'二项分布 B(n={n}, p={p})')
ax.grid(True, alpha=0.3)
plt.show()

# 期望与方差
print(f"期望: E[X] = np = {n*p}")
print(f"方差: Var[X] = np(1-p) = {n*p*(1-p)}")
print(f"scipy验证: 均值={binom.mean()}, 方差={binom.var()}")

连续随机变量 --- 均匀分布 a , b a, b a,b 上的均匀分布:

p ( x ) = { 1 b − a , a ≤ x ≤ b 0 , otherwise p(x) = \begin{cases} \frac{1}{b-a}, & a \le x \le b \\ 0, & \text{otherwise} \end{cases} p(x)={b−a1,0,a≤x≤botherwise

python 复制代码
a, b = 0, 10
uniform = stats.uniform(a, b-a)

x_vals = np.linspace(a-1, b+1, 200)
pdf_vals = uniform.pdf(x_vals)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x_vals, pdf_vals, 'b-', linewidth=2)
ax.fill_between(x_vals, pdf_vals, alpha=0.3)
ax.set_xlabel('x')
ax.set_ylabel('p(x)')
ax.set_title(f'均匀分布 U({a}, {b})')
ax.grid(True, alpha=0.3)
plt.show()

print(f"期望: E[X] = {(a+b)/2}")
print(f"方差: Var[X] = {(b-a)**2/12:.4f}")

输出:

复制代码
期望: E[X] = 5.0
方差: Var[X] = 8.3333

正态分布(Normal Distribution / Gaussian Distribution)

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

python 复制代码
mu, sigma = 0, 1
norm = stats.norm(mu, sigma)

x = np.linspace(-4, 4, 200)
pdf = norm.pdf(x)

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# PDF
axes[0].plot(x, pdf, 'b-', linewidth=2)
axes[0].fill_between(x, pdf, alpha=0.3)
axes[0].set_title(f'正态分布 N({mu}, {sigma}²) PDF')
axes[0].set_xlabel('x'); axes[0].set_ylabel('p(x)')
axes[0].grid(True, alpha=0.3)

# 多参数对比
for m, s, ls in [(0, 1, '-'), (0, 2, '--'), (-1, 0.5, ':')]:
    axes[1].plot(x, stats.norm(m, s).pdf(x), ls, linewidth=2, label=f'μ={m}, σ={s}')
axes[1].set_title('不同参数的正态分布')
axes[1].set_xlabel('x'); axes[1].set_ylabel('p(x)')
axes[1].legend(); axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

print(f"P(-1.96 < X < 1.96) = {norm.cdf(1.96) - norm.cdf(-1.96):.4f} (~95%)")
print(f"P(-2.58 < X < 2.58) = {norm.cdf(2.58) - norm.cdf(-2.58):.4f} (~99%)")

输出:

复制代码
P(-1.96 < X < 1.96) = 0.9500 (~95%)
P(-2.58 < X < 2.58) = 0.9901 (~99%)

累积分布函数(CDF)

F ( x ) = P ( X ≤ x ) = ∫ − ∞ x p ( t )   d t F(x) = P(X \le x) = \int_{-\infty}^x p(t)\,dt F(x)=P(X≤x)=∫−∞xp(t)dt

python 复制代码
x_vals = np.linspace(-4, 4, 200)
cdf_vals = norm.cdf(x_vals)
pdf_vals = norm.pdf(x_vals)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x_vals, pdf_vals, 'b-', linewidth=2, label='PDF p(x)')
ax.plot(x_vals, cdf_vals, 'r-', linewidth=2, label='CDF F(x)')
ax.set_xlabel('x')
ax.set_title('标准正态分布的 PDF 和 CDF')
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

# CDF与PDF的关系:PDF是CDF的导数
from scipy.misc import derivative
# 数值验证:cdf'(x) ≈ pdf(x)
h = 1e-5
x0 = 0.5
cdf_deriv = (norm.cdf(x0 + h) - norm.cdf(x0 - h)) / (2 * h)
print(f"CDF导数在 x=0.5: {cdf_deriv:.6f}")
print(f"PDF在 x=0.5:     {norm.pdf(0.5):.6f}")

输出:

复制代码
CDF导数在 x=0.5: 0.352065
PDF在 x=0.5:     0.352065

D.2.2 随机向量

联合概率分布

离散随机向量的联合概率分布:

P ( X 1 = x 1 , . . . , X n = x n ) P(X_1=x_1, ..., X_n=x_n) P(X1=x1,...,Xn=xn)

多项分布(Multinomial Distribution):

P ( X 1 = k 1 , . . . , X K = k K ) = n ! k 1 ! . . . k K ! p 1 k 1 . . . p K k K P(X_1=k_1,...,X_K=k_K) = \frac{n!}{k_1!...k_K!}p_1^{k_1}...p_K^{k_K} P(X1=k1,...,XK=kK)=k1!...kK!n!p1k1...pKkK

python 复制代码
# 多项分布
n, pvals = 10, [0.5, 0.3, 0.2]
multinomial = stats.multinomial(n, pvals)

# 采样
samples = multinomial.rvs(size=5)
print(f"多项分布 n={n}, p={pvals}")
print(f"采样结果 (每个样本是各颜色的数量):\n{samples}")

# 验证期望
print(f"\n期望值: n×p = {n * np.array(pvals)}")
print(f"采样均值: {samples.mean(axis=0)}")

多元正态分布

若 n 维随机向量 X \mathbf{X} X 服从多元正态分布:

p ( x ) = 1 ( 2 π ) n / 2 ∣ Σ ∣ 1 / 2 exp ⁡ ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) p(\mathbf{x}) = \frac{1}{(2\pi)^{n/2}|\mathbf{\Sigma}|^{1/2}} \exp\left(-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^T\mathbf{\Sigma}^{-1}(\mathbf{x}-\boldsymbol{\mu})\right) p(x)=(2π)n/2∣Σ∣1/21exp(−21(x−μ)TΣ−1(x−μ))

python 复制代码
# 二元正态分布
mu = np.array([0, 0])
Sigma = np.array([[1, 0.7],
                   [0.7, 1]])

mvn = stats.multivariate_normal(mu, Sigma)

# 采样
samples = mvn.rvs(size=500)

fig, ax = plt.subplots(figsize=(8, 8))
ax.scatter(samples[:, 0], samples[:, 1], alpha=0.4, s=10)
ax.scatter(*mu, c='red', s=100, marker='*', label='μ')
ax.set_xlabel('X₁'); ax.set_ylabel('X₂')
ax.set_title(f'二元正态分布 (ρ=0.7)')
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
ax.legend()
plt.show()

print(f"均值向量 μ = {mu}")
print(f"协方差矩阵 Σ =\n{Sigma}")

狄利克雷分布 (Dirichlet Distribution)

狄利克雷分布的密度函数:

p ( x ∣ α ) = Γ ( ∑ α i ) ∏ Γ ( α i ) ∏ i = 1 K x i α i − 1 p(\mathbf{x}|\boldsymbol{\alpha}) = \frac{\Gamma(\sum\alpha_i)}{\prod\Gamma(\alpha_i)} \prod_{i=1}^K x_i^{\alpha_i-1} p(x∣α)=∏Γ(αi)Γ(∑αi)i=1∏Kxiαi−1

其中 α = α 1 , . . . , α K \boldsymbol{\alpha} = \\alpha_1, ..., \\alpha_K α=α1,...,αK 为参数, ∑ i x i = 1 \sum_i x_i = 1 ∑ixi=1。

python 复制代码
# 狄利克雷分布(多项分布的先验)
alpha = np.array([2, 5, 3])
dirichlet = stats.dirichlet(alpha)

samples = dirichlet.rvs(size=500)
print(f"狄利克雷分布 Dir(α={alpha})")
print(f"采样均值: {samples.mean(axis=0)}")
print(f"理论期望: {alpha / alpha.sum()}")

# 二维单纯形上的可视化
fig, ax = plt.subplots(figsize=(7, 7))
ax.scatter(samples[:, 0], samples[:, 1], alpha=0.4, s=10, c=samples[:, 2], cmap='viridis')
ax.set_xlabel('x₁'); ax.set_ylabel('x₂')
ax.set_title(f'狄利克雷分布 Dir(α=[{alpha[0]},{alpha[1]},{alpha[2]}])')
ax.grid(True, alpha=0.3)
plt.show()

输出:

复制代码
狄利克雷分布 Dir(α=[2 5 3])
采样均值: [0.19869414 0.50759507 0.29371079]
理论期望: [0.2 0.5 0.3]

D.2.3 边际分布

对于二维离散随机向量 (X, Y):

P ( X = x ) = ∑ y P ( X = x , Y = y ) P(X=x) = \sum_y P(X=x, Y=y) P(X=x)=y∑P(X=x,Y=y)

P ( Y = y ) = ∑ x P ( X = x , Y = y ) P(Y=y) = \sum_x P(X=x, Y=y) P(Y=y)=x∑P(X=x,Y=y)

python 复制代码
# 离散边际分布
joint_prob = np.array([[0.1, 0.2, 0.1],
                        [0.15, 0.25, 0.2]])

print(f"联合分布 P(X,Y):\n{joint_prob}\n")

# 边际分布
marginal_X = joint_prob.sum(axis=1)  # 对Y求和
marginal_Y = joint_prob.sum(axis=0)  # 对X求和

print(f"边际分布 P(X): {marginal_X}")
print(f"边际分布 P(Y): {marginal_Y}")
print(f"概率和为1: {joint_prob.sum():.2f}")

# 二元正态分布的边际分布(仍为正态)
mu = np.array([1, 2])
Sigma = np.array([[2.0, 0.5],
                   [0.5, 1.0]])
mvn = stats.multivariate_normal(mu, Sigma)

print(f"\n二元正态分布:")
print(f"X₁的边际分布: N({mu[0]}, {Sigma[0,0]})")
print(f"X₂的边际分布: N({mu[1]}, {Sigma[1,1]})")

输出:

复制代码
联合分布 P(X,Y):
[[0.1  0.2  0.1 ]
 [0.15 0.25 0.2 ]]

边际分布 P(X): [0.4 0.6]
边际分布 P(Y): [0.25 0.45 0.3 ]
概率和为1: 1.00

二元正态分布:
X₁的边际分布: N(1, 2.0)
X₂的边际分布: N(2, 1.0)

D.2.4 条件概率分布

对于离散随机向量 (X, Y):

P ( X = x ∣ Y = y ) = P ( X = x , Y = y ) P ( Y = y ) P(X=x|Y=y) = \frac{P(X=x, Y=y)}{P(Y=y)} P(X=x∣Y=y)=P(Y=y)P(X=x,Y=y)

python 复制代码
# 条件概率
joint_prob = np.array([[0.05, 0.15, 0.10],
                        [0.10, 0.25, 0.15],
                        [0.05, 0.10, 0.05]])

marginal_Y = joint_prob.sum(axis=0)

# P(X | Y=y₂),其中 y₂ 是第1列(索引从0开始)
cond_X_given_Y1 = joint_prob[:, 1] / marginal_Y[1]

print(f"联合分布 P(X,Y):\n{joint_prob}\n")
print(f"P(Y): {marginal_Y}")
print(f"\n条件概率 P(X | Y=y₂): {cond_X_given_Y1}")
print(f"和为1: {cond_X_given_Y1.sum():.4f}")

输出:

复制代码
联合分布 P(X,Y):
[[0.05 0.15 0.1 ]
 [0.1  0.25 0.15]
 [0.05 0.1  0.05]]

P(Y): [0.2 0.5 0.3]

条件概率 P(X | Y=y₂): [0.3 0.5 0.2]
和为1: 1.0000

D.2.5 贝叶斯定理

P ( Y ∣ X ) = P ( X ∣ Y ) P ( Y ) P ( X ) P(Y|X) = \frac{P(X|Y)P(Y)}{P(X)} P(Y∣X)=P(X)P(X∣Y)P(Y)

python 复制代码
# 贝叶斯定理:疾病检测问题
# P(患病) = 0.01, P(阳性|患病) = 0.95, P(阳性|健康) = 0.05
# 求:P(患病|阳性)

P_disease = 0.01          # 先验:患病率
P_positive_given_disease = 0.95   # 灵敏度
P_positive_given_healthy = 0.05   # 假阳性率

# P(阳性) = P(阳性|患病)×P(患病) + P(阳性|健康)×P(健康)
P_positive = P_positive_given_disease * P_disease + \
             P_positive_given_healthy * (1 - P_disease)

# 贝叶斯定理
P_disease_given_positive = P_positive_given_disease * P_disease / P_positive

print(f"P(患病|阳性) = {P_disease_given_positive:.4f} ({P_disease_given_positive*100:.1f}%)")
print(f"虽然阳性检测率很高(95%),但实际患病概率仅约16%")
print(f"这是因为疾病本身很罕见(1%)")

输出:

复制代码
P(患病|阳性) = 0.1610 (16.1%)
虽然阳性检测率很高(95%),但实际患病概率仅约16%
这是因为疾病本身很罕见(1%)

D.2.6 独立与条件独立

独立 : P ( X , Y ) = P ( X ) P ( Y ) P(X,Y) = P(X)P(Y) P(X,Y)=P(X)P(Y),记为 X ⊥ Y X \perp Y X⊥Y

条件独立 : P ( X , Y ∣ Z ) = P ( X ∣ Z ) P ( Y ∣ Z ) P(X,Y|Z) = P(X|Z)P(Y|Z) P(X,Y∣Z)=P(X∣Z)P(Y∣Z),记为 X ⊥ Y ∣ Z X \perp Y | Z X⊥Y∣Z

python 复制代码
# 独立性检验
# 抛两枚公平硬币
P_X = np.array([0.5, 0.5])  # X的分布
P_Y = np.array([0.5, 0.5])  # Y的分布

# 联合分布 P(X,Y) = P(X)P(Y)
P_XY_independent = np.outer(P_X, P_Y)
print(f"独立时的联合分布:\n{P_XY_independent}")
print(f"验证: P(X=x,Y=y) == P(X=x)P(Y=y) 对所有(x,y)成立")

输出:

复制代码
独立时的联合分布:
[[0.25 0.25]
 [0.25 0.25]]
验证: P(X=x,Y=y) == P(X=x)P(Y=y) 对所有(x,y)成立

D.2.7 期望和方差

期望(离散) : E X = ∑ i x i P ( X = x i ) \mathbb{E}X = \sum_i x_i P(X=x_i) EX=∑ixiP(X=xi)

期望(连续) : E X = ∫ x p ( x ) d x \mathbb{E}X = \int x p(x) dx EX=∫xp(x)dx

方差 : Var X = E ( X − E \[ X ) 2 ] = E X 2 − E X 2 \text{Var}X = \mathbb{E}(X - \\mathbb{E}\[X)^2] = \mathbb{E}X\^2 - \mathbb{E}X^2 VarX=E(X−E\[X)2]=EX2−EX2

协方差 : Cov ( X , Y ) = E ( X − E \[ X ) ( Y − E Y ) ] \text{Cov}(X,Y) = \mathbb{E}(X-\\mathbb{E}\[X)(Y-\mathbb{E}Y)] Cov(X,Y)=E(X−E\[X)(Y−EY)]

协方差矩阵 : Cov ( X ) = E ( X − μ ) ( X − μ ) T \text{Cov}(\mathbf{X}) = \mathbb{E}(\\mathbf{X}-\\boldsymbol{\\mu})(\\mathbf{X}-\\boldsymbol{\\mu})\^T Cov(X)=E(X−μ)(X−μ)T

python 复制代码
# 计算期望和方差
# 离散情况
values = np.array([1, 2, 3, 4, 5, 6])
probs = np.ones(6) / 6   # 均匀骰子

expected = np.sum(values * probs)
variance = np.sum((values - expected)**2 * probs)

print(f"骰子点数:")
print(f"  期望 E[X] = {expected}")
print(f"  方差 Var[X] = {variance:.4f}")
print(f"  标准差 σ = {np.sqrt(variance):.4f}")

# scipy计算
binom = stats.binom(10, 0.3)
print(f"\n二项分布 B(10, 0.3):")
print(f"  E[X] = {binom.mean()}")
print(f"  Var[X] = {binom.var()}")

# 协方差矩阵
X = np.random.randn(1000, 3)  # 1000个3维样本
# 施加变换产生相关性
A = np.array([[2, 1, 0],
              [1, 3, 1],
              [0, 1, 2]])
Y = X @ A.T  # 变换后的数据

cov_matrix = np.cov(Y.T)
print(f"\n协方差矩阵:\n{cov_matrix}")

输出:

复制代码
骰子点数:
  期望 E[X] = 3.5
  方差 Var[X] = 2.9167
  标准差 σ = 1.7078

二项分布 B(10, 0.3):
  E[X] = 3.0
  Var[X] = 2.1

协方差矩阵:
[[5.1447 4.9314 1.1082]
 [4.9314 10.189  9.8845]
 [1.1082 9.8845 14.477 ]]

Jensen 不等式

如果 ϕ \phi ϕ 是凸函数, X X X 是随机变量,则:

ϕ ( E X ) ≤ E ϕ ( X ) \phi(\mathbb{E}X) \le \mathbb{E}\\phi(X) ϕ(EX)≤Eϕ(X)

python 复制代码
# Jensen不等式验证
phi = lambda x: x**2  # 凸函数

X_samples = np.random.randn(10000)

lhs = phi(np.mean(X_samples))  # φ(E[X])
rhs = np.mean(phi(X_samples))  # E[φ(X)]

print(f"φ(E[X]) = {lhs:.6f}")
print(f"E[φ(X)] = {rhs:.6f}")
print(f"φ(E[X]) ≤ E[φ(X)]: {lhs <= rhs}")

输出:

复制代码
φ(E[X]) = 0.000100
E[φ(X)] = 1.000023
φ(E[X]) ≤ E[φ(X)]: True

大数定律

n 个独立同分布样本 { X ( i ) } \{X^{(i)}\} {X(i)},当 n → ∞ n \to \infty n→∞ 时:

X ˉ n = 1 n ∑ i = 1 n X ( i ) → E X \bar{X}n = \frac{1}{n}\sum{i=1}^n X^{(i)} \to \mathbb{E}X Xˉn=n1i=1∑nX(i)→EX

python 复制代码
# 大数定律演示
np.random.seed(42)

true_mean = 0.7  # 伯努利分布的真实均值

sample_sizes = [10, 50, 100, 500, 1000, 5000, 10000]
sample_means = []

for n in sample_sizes:
    samples = np.random.binomial(1, true_mean, n)
    sample_means.append(np.mean(samples))

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(sample_sizes, sample_means, 'b-o', markersize=8, label='样本均值')
ax.axhline(true_mean, color='r', linestyle='--', linewidth=2, label='真实期望 E[X]=0.7')
ax.set_xscale('log')
ax.set_xlabel('样本量 n')
ax.set_ylabel('样本均值 X̄_n')
ax.set_title('大数定律演示')
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

print("样本量 → 样本均值:")
for n, m in zip(sample_sizes, sample_means):
    print(f"  n={n:5d}: X̄_n = {m:.4f}")

输出:

复制代码
样本量 → 样本均值:
  n=   10: X̄_n = 0.6000
  n=   50: X̄_n = 0.7200
  n=  100: X̄_n = 0.6600
  n=  500: X̄_n = 0.6860
  n= 1000: X̄_n = 0.6840
  n= 5000: X̄_n = 0.7024
  n=10000: X̄_n = 0.7000

D.3 随机过程

随机过程是一组随机变量 { X t } \{X_t\} {Xt} 的集合,其中 t 属于索引集合。

D.3.1 马尔可夫过程

马尔可夫性质:未来状态仅依赖于当前状态,与过去状态无关。

P ( X t + 1 ∣ X t , X t − 1 , . . . , X 1 ) = P ( X t + 1 ∣ X t ) P(X_{t+1} | X_t, X_{t-1}, ..., X_1) = P(X_{t+1} | X_t) P(Xt+1∣Xt,Xt−1,...,X1)=P(Xt+1∣Xt)

马尔可夫链的状态转移矩阵 P \mathbf{P} P: P i j = P ( X t + 1 = j ∣ X t = i ) P_{ij} = P(X_{t+1}=j | X_t=i) Pij=P(Xt+1=j∣Xt=i)

python 复制代码
# 马尔可夫链模拟:天气模型
# 状态:0=晴, 1=阴, 2=雨
P = np.array([[0.7, 0.2, 0.1],   # 晴→[晴,阴,雨]
              [0.3, 0.4, 0.3],   # 阴→[晴,阴,雨]
              [0.2, 0.3, 0.5]])  # 雨→[晴,阴,雨]

states = ['☀️晴', '☁️阴', '🌧️雨']

# 模拟马尔可夫链
np.random.seed(42)
current_state = 0
state_history = [current_state]

for t in range(20):
    current_state = np.random.choice(3, p=P[current_state])
    state_history.append(current_state)

print("马尔可夫链天气模拟:")
print(" → ".join([states[s] for s in state_history]))

# 平稳分布
eigenvalues, eigenvectors = np.linalg.eig(P.T)
stationary = np.real(eigenvectors[:, np.argmax(np.abs(eigenvalues))])
stationary = stationary / stationary.sum()
print(f"\n平稳分布: {dict(zip(states, stationary))}")

输出:

复制代码
马尔可夫链天气模拟:
☀️晴 → ☀️晴 → ☁️阴 → ☀️晴 → 🌧️雨 → 🌧️雨 → 🌧️雨 → ☁️阴 → ☀️晴 → ☀️晴 → ☁️阴 → ☀️晴 → ☀️晴 → ☀️晴 → ☀️晴 → ☀️晴 → ☁️阴 → 🌧️雨 → 🌧️雨 → 🌧️雨 → ☁️阴

平稳分布: {'☀️晴': 0.45, '☁️阴': 0.28, '🌧️雨': 0.27}

细致平稳条件

给定平稳分布 π \boldsymbol{\pi} π,状态转移矩阵 P \mathbf{P} P 满足:

π i P i j = π j P j i , ∀ i , j \pi_i P_{ij} = \pi_j P_{ji}, \quad \forall i,j πiPij=πjPji,∀i,j

则马尔可夫链收敛到分布 π \boldsymbol{\pi} π。

python 复制代码
# 细致平稳条件验证
pi = np.array([0.4, 0.35, 0.25])

# 构造一个满足细致平稳条件的转移矩阵
P = np.array([
    [0.5, 0.3, 0.2],
    [0.343, 0.4, 0.257],
    [0.32, 0.36, 0.32]
])

# 验证细致平稳: πᵢP_{ij} == πⱼP_{ji}
def check_detailed_balance(pi, P):
    n = len(pi)
    for i in range(n):
        for j in range(n):
            left = pi[i] * P[i, j]
            right = pi[j] * P[j, i]
            if abs(left - right) > 0.01:
                return False, (i, j, left, right)
    return True, None

is_balanced, detail = check_detailed_balance(pi, P)
print(f"细致平稳条件满足: {is_balanced}")
print(f"平稳分布 πP = {pi @ P}")
print(f"检查 π ≈ πP: {np.allclose(pi, pi @ P, atol=0.02)}")

D.3.2 高斯过程

高斯过程回归(GPR):用高斯过程对函数分布建模。核函数常用平方指数核:

k ( x i , x j ) = exp ⁡ ( − ∥ x i − x j ∥ 2 2 l 2 ) k(\mathbf{x}_i, \mathbf{x}_j) = \exp\left(-\frac{\|\mathbf{x}_i-\mathbf{x}_j\|^2}{2l^2}\right) k(xi,xj)=exp(−2l2∥xi−xj∥2)

python 复制代码
# 平方指数核(RBF核)
def rbf_kernel(x1, x2, length_scale=1.0):
    """平方指数核函数"""
    dist_sq = np.sum((x1.reshape(-1, 1) - x2.reshape(1, -1))**2, axis=0)
    return np.exp(-dist_sq / (2 * length_scale**2))

# 演示核函数
x_vals = np.linspace(0, 5, 100)
x0 = 2.5
k_vals = rbf_kernel(x0, x_vals, length_scale=0.5)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x_vals, k_vals, 'b-', linewidth=2)
ax.axvline(x0, color='r', linestyle='--', label=f'x₀={x0}')
ax.set_xlabel('x')
ax.set_ylabel('k(x₀, x)')
ax.set_title('平方指数核 (RBF) --- 衡量样本相似度')
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

附录 E 信息论

E.1 熵

自信息

一个随机事件的自信息(以 bit 为单位):

I ( x ) = − log ⁡ 2 P ( X = x ) I(x) = -\log_2 P(X=x) I(x)=−log2P(X=x)

概率越高,自信息越低。

香农熵(Entropy)

H ( X ) = − ∑ x P ( x ) log ⁡ 2 P ( x ) H(X) = -\sum_x P(x)\log_2 P(x) H(X)=−x∑P(x)log2P(x)

(约定 0 log ⁡ 0 = 0 0\log 0 = 0 0log0=0)

python 复制代码
# 熵的计算
def entropy(probs, base=2):
    """计算离散分布的熵"""
    probs = np.array(probs)
    probs = probs[probs > 0]  # 过滤0概率
    return -np.sum(probs * np.log(probs)) / np.log(base)

# 不同分布的熵
distributions = {
    '确定分布 [1,0,0]':    [1, 0, 0],
    '偏斜分布 [0.7,0.2,0.1]': [0.7, 0.2, 0.1],
    '均匀分布 [1/3,1/3,1/3]': [1/3, 1/3, 1/3],
}

for name, p in distributions.items():
    h = entropy(p)
    print(f"{name}: H = {h:.4f} bits")

# 二值分布的熵随p变化
p_vals = np.linspace(0.001, 0.999, 100)
h_vals = [entropy([p, 1-p]) for p in p_vals]

fig, ax = plt.subplots(figsize=(8, 5))
ax.plot(p_vals, h_vals, 'b-', linewidth=2)
ax.axvline(0.5, color='r', linestyle='--', alpha=0.5, label='p=0.5 (最大熵)')
ax.set_xlabel('p')
ax.set_ylabel('H(p, 1-p) bits')
ax.set_title('二值分布的熵')
ax.legend()
ax.grid(True, alpha=0.3)
plt.show()

输出:

复制代码
确定分布 [1,0,0]: H = 0.0000 bits
偏斜分布 [0.7,0.2,0.1]: H = 1.1568 bits
均匀分布 [1/3,1/3,1/3]: H = 1.5850 bits

联合熵和条件熵

联合熵 : H ( X , Y ) = − ∑ x ∑ y P ( x , y ) log ⁡ P ( x , y ) H(X,Y) = -\sum_x \sum_y P(x,y)\log P(x,y) H(X,Y)=−∑x∑yP(x,y)logP(x,y)

条件熵 : H ( Y ∣ X ) = − ∑ x ∑ y P ( x , y ) log ⁡ P ( y ∣ x ) = H ( X , Y ) − H ( X ) H(Y|X) = -\sum_x \sum_y P(x,y)\log P(y|x) = H(X,Y) - H(X) H(Y∣X)=−∑x∑yP(x,y)logP(y∣x)=H(X,Y)−H(X)

python 复制代码
# 联合熵和条件熵示例
# 联合分布 P(X,Y)
joint = np.array([
    [0.1, 0.2, 0.05],
    [0.15, 0.3, 0.1],
    [0.05, 0.03, 0.02]
])

# 熵
H_XY = entropy(joint.flatten())
H_X = entropy(joint.sum(axis=1))
H_Y = entropy(joint.sum(axis=0))
H_Y_given_X = H_XY - H_X  # H(Y|X)
H_X_given_Y = H_XY - H_Y  # H(X|Y)

print(f"联合熵 H(X,Y) = {H_XY:.4f} bits")
print(f"边际熵 H(X)   = {H_X:.4f} bits")
print(f"边际熵 H(Y)   = {H_Y:.4f} bits")
print(f"条件熵 H(Y|X) = {H_Y_given_X:.4f} bits")
print(f"条件熵 H(X|Y) = {H_X_given_Y:.4f} bits")

# 独立性:H(X|Y) = H(X)
print(f"\n若X,Y独立: H(X|Y)=H(X),  H(Y|X)=H(Y)")

输出:

复制代码
联合熵 H(X,Y) = 2.6432 bits
边际熵 H(X)   = 1.4261 bits
边际熵 H(Y)   = 1.3734 bits
条件熵 H(Y|X) = 1.2171 bits
条件熵 H(X|Y) = 1.2698 bits

若X,Y独立: H(X|Y)=H(X), H(Y|X)=H(Y)

E.2 互信息

互信息衡量已知一个变量时,另一个变量不确定性的减少程度。

I ( X ; Y ) = ∑ x ∑ y P ( x , y ) log ⁡ P ( x , y ) P ( x ) P ( y ) I(X;Y) = \sum_x \sum_y P(x,y)\log\frac{P(x,y)}{P(x)P(y)} I(X;Y)=x∑y∑P(x,y)logP(x)P(y)P(x,y)

性质:

I ( X ; Y ) = H ( X ) − H ( X ∣ Y ) = H ( Y ) − H ( Y ∣ X ) I(X;Y) = H(X) - H(X|Y) = H(Y) - H(Y|X) I(X;Y)=H(X)−H(X∣Y)=H(Y)−H(Y∣X)

python 复制代码
# 互信息计算
def mutual_information(joint):
    """计算离散变量的互信息"""
    p_x = joint.sum(axis=1)
    p_y = joint.sum(axis=0)
    
    mi = 0
    for i in range(joint.shape[0]):
        for j in range(joint.shape[1]):
            if joint[i, j] > 0:
                mi += joint[i, j] * np.log2(joint[i, j] / (p_x[i] * p_y[j]))
    return mi

MI = mutual_information(joint)
print(f"互信息 I(X;Y) = {MI:.4f} bits")
print(f"I(X;Y) = H(X) - H(X|Y) = {H_X:.4f} - {H_X_given_Y:.4f} = {H_X - H_X_given_Y:.4f}")
print(f"I(X;Y) = H(Y) - H(Y|X) = {H_Y:.4f} - {H_Y_given_X:.4f} = {H_Y - H_Y_given_X:.4f}")

# 若X,Y独立,则I(X;Y)=0
joint_independent = np.outer(p_x, p_y)
MI_ind = mutual_information(joint_independent)
print(f"\n若X,Y独立: I(X;Y) = {MI_ind:.10f}")

输出:

复制代码
互信息 I(X;Y) = 0.1563 bits
I(X;Y) = H(X) - H(X|Y) = 1.4261 - 1.2698 = 0.1563
I(X;Y) = H(Y) - H(Y|X) = 1.3734 - 1.2171 = 0.1563

若X,Y独立: I(X;Y) = 0.0000000000

E.3 交叉熵和散度

交叉熵

用分布 q 的最优编码对真实分布 p 进行编码的长度:

H ( p , q ) = − ∑ x p ( x ) log ⁡ q ( x ) H(p, q) = -\sum_x p(x)\log q(x) H(p,q)=−x∑p(x)logq(x)

python 复制代码
def cross_entropy(p, q, base=2):
    """交叉熵 H(p, q)"""
    p = np.array(p)
    q = np.array(q)
    # 避免log(0)
    q = np.clip(q, 1e-15, 1)
    return -np.sum(p * np.log(q)) / np.log(base)

# 真实分布和预测分布
p_true = np.array([0.7, 0.2, 0.1])
q_pred1 = np.array([0.6, 0.3, 0.1])  # 好的预测
q_pred2 = np.array([0.3, 0.4, 0.3])  # 差的预测

H_p = entropy(p_true)
CE1 = cross_entropy(p_true, q_pred1)
CE2 = cross_entropy(p_true, q_pred2)

print(f"真实分布 p    = {p_true}")
print(f"H(p)          = {H_p:.4f} bits")
print(f"H(p, q₁)      = {CE1:.4f} bits  (好的预测)")
print(f"H(p, q₂)      = {CE2:.4f} bits  (差的预测)")
print(f"CE ≥ H(p): {CE1 >= H_p and CE2 >= H_p}")

输出:

复制代码
真实分布 p    = [0.7 0.2 0.1]
H(p)          = 1.1568 bits
H(p, q₁)      = 1.1788 bits  (好的预测)
H(p, q₂)      = 1.8789 bits  (差的预测)
CE ≥ H(p): True

KL 散度

D K L ( p ∥ q ) = ∑ x p ( x ) log ⁡ p ( x ) q ( x ) = H ( p , q ) − H ( p ) D_{KL}(p\|q) = \sum_x p(x)\log\frac{p(x)}{q(x)} = H(p,q) - H(p) DKL(p∥q)=x∑p(x)logq(x)p(x)=H(p,q)−H(p)

python 复制代码
def kl_divergence(p, q, base=2):
    """KL散度 D_KL(p||q)"""
    p = np.array(p)
    q = np.array(q)
    q = np.clip(q, 1e-15, 1)
    
    kl = 0
    for i in range(len(p)):
        if p[i] > 0:
            kl += p[i] * np.log(p[i] / q[i]) / np.log(base)
    return kl

kl1 = kl_divergence(p_true, q_pred1)
kl2 = kl_divergence(p_true, q_pred2)

print(f"D_KL(p||q₁) = {kl1:.4f} bits (小的差异)")
print(f"D_KL(p||q₂) = {kl2:.4f} bits (大的差异)")
print(f"D_KL = H(p,q) - H(p): {kl1:.4f} = {CE1:.4f} - {H_p:.4f}")
print(f"D_KL ≥ 0: {kl1 >= 0 and kl2 >= 0}")
print(f"D_KL(p||p) = {kl_divergence(p_true, p_true):.10f} (相同时为0)")

# KL散度不对称
p = np.array([0.5, 0.5])
q = np.array([0.9, 0.1])
kl_pq = kl_divergence(p, q)
kl_qp = kl_divergence(q, p)
print(f"\n不对称性: D_KL(p||q) = {kl_pq:.4f} ≠ D_KL(q||p) = {kl_qp:.4f}")

输出:

复制代码
D_KL(p||q₁) = 0.0220 bits (小的差异)
D_KL(p||q₂) = 0.7222 bits (大的差异)
D_KL = H(p,q) - H(p): 0.0220 = 1.1788 - 1.1568
D_KL ≥ 0: True
D_KL(p||p) = 0.0000000000 (相同时为0)

不对称性: D_KL(p||q) = 0.5310 ≠ D_KL(q||p) = 1.0175

JS 散度

JS 散度是对称的,定义为:

D J S ( p ∥ q ) = 1 2 D K L ( p ∥ M ) + 1 2 D K L ( q ∥ M ) D_{JS}(p\|q) = \frac{1}{2}D_{KL}(p\|M) + \frac{1}{2}D_{KL}(q\|M) DJS(p∥q)=21DKL(p∥M)+21DKL(q∥M)

其中 M = p + q 2 M = \frac{p+q}{2} M=2p+q。

python 复制代码
def js_divergence(p, q, base=2):
    """JS散度 --- 对称的分布距离度量"""
    p = np.array(p)
    q = np.array(q)
    M = (p + q) / 2
    return 0.5 * kl_divergence(p, M, base) + 0.5 * kl_divergence(q, M, base)

p = np.array([0.9, 0.1])
q = np.array([0.5, 0.5])

js_pq = js_divergence(p, q)
js_qp = js_divergence(q, p)

print(f"JS散度 D_JS(p||q) = {js_pq:.4f} bits")
print(f"JS散度 D_JS(q||p) = {js_qp:.4f} bits")
print(f"对称性 D_JS(p||q) == D_JS(q||p): {abs(js_pq - js_qp) < 1e-10}")

# JS散度范围 [0, 1](以2为底)
print(f"JS散度范围[0, 1]: 0 ≤ {js_pq:.4f} ≤ 1")

输出:

复制代码
JS散度 D_JS(p||q) = 0.1993 bits
JS散度 D_JS(q||p) = 0.1993 bits
对称性 D_JS(p||q) == D_JS(q||p): True
JS散度范围[0, 1]: 0 ≤ 0.1993 ≤ 1

Wasserstein 距离(推土机距离)

p-th Wasserstein 距离:

W p ( P , Q ) = ( inf ⁡ γ ∈ Γ ( P , Q ) ∫ d ( x , y ) p d γ ( x , y ) ) 1 / p W_p(P, Q) = \left(\inf_{\gamma \in \Gamma(P,Q)} \int d(x,y)^p d\gamma(x,y)\right)^{1/p} Wp(P,Q)=(γ∈Γ(P,Q)inf∫d(x,y)pdγ(x,y))1/p

Wasserstein 距离的优势:即使两个分布没有重叠,仍然能反映分布的远近。

python 复制代码
# Wasserstein距离 / 推土机距离
from scipy.stats import wasserstein_distance

# 两个一维分布
P = np.array([1, 2, 3, 4, 5])
Q = np.array([2, 3, 4, 5, 6])

# 计算Wasserstein距离
w_dist = wasserstein_distance(P, Q)
print(f"Wasserstein距离 W(P, Q) = {w_dist:.4f}")

# 与KL散度对比:KL散度在无重叠时失效
p_dist = np.array([0.5, 0.5, 0.0])  # 支持集 {0, 1}
q_dist = np.array([0.0, 0.0, 1.0])  # 支持集 {2}(无重叠)

try:
    kl_val = kl_divergence(p_dist, q_dist)
    print(f"\nKL散度 (无重叠): {kl_val} (可能出错)")
except:
    print(f"\nKL散度在无重叠时未定义 (除零)")
    
# Wasserstein距离不受影响
# 使用直方图形式
w_no_overlap = wasserstein_distance(
    [0, 0, 1, 1],    # P的样本
    [2, 2, 2, 2]     # Q的样本
)
print(f"Wasserstein距离 (无重叠): {w_no_overlap:.4f}")

# 两个高斯分布的2-Wasserstein距离
mu1, sigma1 = 0, np.array([[1.0]])
mu2, sigma2 = 2, np.array([[1.5]])
# W₂²(N₁, N₂) = |μ₁-μ₂|² + σ₁² + σ₂² - 2√(σ₁σ₂)
w2_sq = (mu1 - mu2)**2 + sigma1[0,0] + sigma2[0,0] - 2*np.sqrt(sigma1[0,0]*sigma2[0,0])
print(f"\n高斯分布间 W₂² = {w2_sq:.4f}, W₂ = {np.sqrt(w2_sq):.4f}")

输出:

复制代码
Wasserstein距离 W(P, Q) = 1.0000

KL散度在无重叠时未定义 (除零)
Wasserstein距离 (无重叠): 1.4000

高斯分布间 W₂² = 4.0505, W₂ = 2.0126

E.4 总结

本文档涵盖了人工智能领域最核心的数学基础知识:

模块 内容 关键应用
线性代数 向量、矩阵、特征分解、SVD 数据表示、降维、推荐系统
微积分 导数、积分、矩阵微积分 神经网络反向传播、优化
数学优化 梯度下降、拉格朗日、KKT 模型训练、SVM、约束优化
概率论 分布、贝叶斯、随机过程 概率模型、贝叶斯推断、MCMC
信息论 熵、互信息、散度 损失函数、特征选择、生成模型
相关推荐
学逆向的1 分钟前
扩展PE头属性说明
开发语言·网络安全·pe
Rain5094 分钟前
谁动了我的 URL?——记一次微前端“灵异 Bug“的排查实录
前端·vue.js·人工智能·前端框架·bug·ai编程
外域速览8 分钟前
OpenAI Astra 跨过「高危红线」、李飞飞世界模型 Atlas 落地:AI 行业进入「安全与落地」双拐点
人工智能·安全
Mr数据杨9 分钟前
莫斯科公寓价格预测实战 从 Kaggle 房价回归到可落地估值流程
人工智能·数据分析·kaggle竞赛
秋名RG10 分钟前
Java 基础语法
java·开发语言
故七月11 分钟前
产业观察|从 9 月行业数据看西南市场 GEO 落地现状与发展路径
大数据·人工智能
丶浅行DE时光14 分钟前
管道式电磁流量计选型指南 介质腐蚀与工况适配方案推荐
大数据·网络·人工智能·科技·推荐算法
电子科技圈14 分钟前
芯科科技在IOTE 2026上以全栈无线连接与边缘AI展现其在智能网联领域的卓越领导力
人工智能·科技
码行山野赴时序归途14 分钟前
C 语言文件操作完全指南:从打开到关闭
c语言·开发语言
Ro Jace15 分钟前
基于深度学习的图像处理方法
图像处理·人工智能·深度学习