文章目录
- 人工智能数学基础
-
- [需要的 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 矩阵微积分)
-
- 标量关于向量的偏导数
- 向量关于向量的偏导数(雅可比矩阵)
- [Hessian 矩阵](#Hessian 矩阵)
- [B.3.1 导数法则](#B.3.1 导数法则)
- 链式法则
- [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 数学优化)
- [附录 D 概率论](#附录 D 概率论)
-
- [D.1 样本空间](#D.1 样本空间)
- [D.2 事件和概率](#D.2 事件和概率)
-
- [D.2.1 随机变量](#D.2.1 随机变量)
- 累积分布函数(CDF)
- [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 期望和方差)
-
- [Jensen 不等式](#Jensen 不等式)
- 大数定律
- [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,...,xn]T
其中 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),是指由向量组成的集合,并满足以下两个条件:
- 向量加法 + + +:向量空间 V V V 中的两个向量 x \mathbf{x} x 和 y \mathbf{y} y,它们的和 x + y \mathbf{x}+\mathbf{y} x+y 也属于空间 V V V;
- 标量乘法 ⋅ \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+yn]T
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,...,cxn]T
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,...,xn]T
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,...,Amn]T
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∂f]T
- 分子布局(行向量形式):
∂ 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
乘法法则:
- 若 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
- 若 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)。
局部最小解的判定条件:
- 一阶必要条件 : ∇ f ( x ∗ ) = 0 \nabla f(\mathbf{x}^*) = 0 ∇f(x∗)=0
- 二阶必要条件 : ∇ 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 条件(最优性的必要条件):
- ∇ 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(平稳性)
- g i ( x ∗ ) = 0 g_i(\mathbf{x}^*) = 0 gi(x∗)=0(等式约束满足)
- h j ( x ∗ ) ≤ 0 h_j(\mathbf{x}^*) \le 0 hj(x∗)≤0(不等式约束满足)
- μ j ≥ 0 \mu_j \ge 0 μj≥0(对偶可行性)
- μ 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) E[X]=∑ixiP(X=xi)
期望(连续) : E [ X ] = ∫ x p ( x ) d x \mathbb{E}[X] = \int x p(x) dx E[X]=∫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 Var[X]=E[(X−E[X])2]=E[X2]−E[X]2
协方差 : 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−E[Y])]
协方差矩阵 : 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)] ϕ(E[X])≤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)→E[X]
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 |
| 信息论 | 熵、互信息、散度 | 损失函数、特征选择、生成模型 |