[大模型教我成为大模型算法工程师之day1:机器学习数学基础]
本文介绍了机器学习中必备的数学基础,重点聚焦于线性代数和概率统计两大核心内容。在线性代数部分,阐述了向量、矩阵的本质及其在机器学习中的应用,包括特征值分解、SVD等矩阵分解方法及其实际应用场景。概率论部分则强调了其在处理不确定性中的重要性,涵盖了基本概率概念和统计方法。文章采用直观解释与代码示例相结合的方式,帮助读者建立数学直觉,理解这些数学工具如何支撑机器学习算法。通过掌握这些基础知识,读者可以
Day 1: 机器学习数学基础
写在前面:数学是机器学习的语言。本文不追求面面俱到,而是聚焦于ML/DL中最常用的数学工具,帮你建立直觉、理解本质。
目录
1. 线性代数核心
1.1 为什么线性代数如此重要?
机器学习的本质是数据的变换与表示:
- 数据表示为向量和矩阵
- 模型参数是矩阵
- 前向传播是矩阵乘法
- 神经网络就是一系列线性变换 + 非线性激活
理解线性代数 = 理解数据如何在高维空间中流动和变换
1.2 向量与向量空间
向量的几何直觉
向量不只是一列数字,它代表:
- 点:空间中的一个位置
- 方向:从原点出发的箭头
- 特征:数据的一种表示
import numpy as np
# 一个词向量(简化示例)
word_king = np.array([0.8, 0.2, 0.9, 0.1]) # [royalty, gender_male, power, ...]
word_queen = np.array([0.8, -0.2, 0.7, 0.1]) # 类似king,但gender不同
# 向量运算揭示语义关系
# king - man + woman ≈ queen (Word2Vec的经典例子)
向量空间的核心概念
| 概念 | 直觉解释 | ML中的应用 |
|---|---|---|
| 线性无关 | 向量之间不能相互表示 | 特征冗余检测 |
| 张成空间(Span) | 向量能"覆盖"的所有点 | 模型的表达能力 |
| 基(Basis) | 最小的"坐标系" | 降维的目标 |
| 维度(Dimension) | 需要几个基向量 | 特征数量 |
内积与相似度
向量内积是ML中最常用的操作之一:
⟨ a , b ⟩ = a T b = ∑ i = 1 n a i b i = ∥ a ∥ ∥ b ∥ cos θ \langle \mathbf{a}, \mathbf{b} \rangle = \mathbf{a}^T \mathbf{b} = \sum_{i=1}^{n} a_i b_i = \|\mathbf{a}\| \|\mathbf{b}\| \cos\theta ⟨a,b⟩=aTb=i=1∑naibi=∥a∥∥b∥cosθ
直觉:内积衡量两个向量的"相似程度"
- 值大 → 方向相近
- 值为0 → 正交(无关)
- 值为负 → 方向相反
# 余弦相似度:归一化的内积
def cosine_similarity(a, b):
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
if norm_a == 0 or norm_b == 0:
return 0.0
return np.dot(a, b) / (norm_a * norm_b)
# 在推荐系统、文本相似度、人脸识别中广泛使用
similarity = cosine_similarity(word_king, word_queen)
1.3 矩阵与线性变换
矩阵的本质是变换
矩阵不是一堆数字的表格,而是空间的变换规则:
y = A x \mathbf{y} = \mathbf{A}\mathbf{x} y=Ax
- x \mathbf{x} x:原始空间中的向量
- A \mathbf{A} A:变换规则(旋转、缩放、投影…)
- y \mathbf{y} y:变换后的向量
# 2D旋转矩阵(逆时针旋转θ角)
def rotation_matrix(theta):
return np.array([
[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]
])
# 神经网络中的线性层就是矩阵变换
# y = Wx + b (注意:深度学习框架通常使用 y = xW^T + b)
特殊矩阵
| 矩阵类型 | 性质 | ML中的应用 |
|---|---|---|
| 对称矩阵 A = A T A = A^T A=AT | 特征值都是实数 | 协方差矩阵、核矩阵 |
| 正交矩阵 A T A = I A^T A = I ATA=I | 保持向量长度和角度 | 权重初始化 |
| 正定矩阵 x T A x > 0 x^T A x > 0 xTAx>0 | 所有特征值 > 0 | 损失函数的Hessian |
| 对角矩阵 | 只有对角线非零 | 特征值分解结果 |
1.4 特征值与特征向量
核心定义
对于方阵 A \mathbf{A} A,如果存在非零向量 v \mathbf{v} v 和标量 λ \lambda λ 使得:
A v = λ v \mathbf{A}\mathbf{v} = \lambda \mathbf{v} Av=λv
则 λ \lambda λ 是特征值, v \mathbf{v} v 是对应的特征向量。
直觉理解
特征向量是矩阵变换下方向不变的向量,特征值是缩放倍数:
- λ > 1 \lambda > 1 λ>1:沿该方向拉伸
- 0 < λ < 1 0 < \lambda < 1 0<λ<1:沿该方向压缩
- λ < 0 \lambda < 0 λ<0:方向反转
A = np.array([[3, 1], [1, 3]])
# 计算特征值和特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)
print(f"特征值: {eigenvalues}") # [4, 2]
print(f"特征向量:\n{eigenvectors}") # 两个正交方向
# 验证:Av = λv
v = eigenvectors[:, 0]
lambda_ = eigenvalues[0]
print(f"Av = {A @ v}")
print(f"λv = {lambda_ * v}")
特征分解
对于对称矩阵,可以分解为:
A = Q Λ Q T \mathbf{A} = \mathbf{Q} \mathbf{\Lambda} \mathbf{Q}^T A=QΛQT
- Q \mathbf{Q} Q:特征向量组成的正交矩阵
- Λ \mathbf{\Lambda} Λ:特征值组成的对角矩阵
应用:PCA降维的核心就是对协方差矩阵做特征分解
1.5 奇异值分解 (SVD)
为什么需要SVD?
特征分解只适用于方阵,但实际数据矩阵往往不是方阵(m个样本,n个特征)。SVD适用于任意矩阵。
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 \mathbf{U} U: m × m m \times m m×m 正交矩阵(左奇异向量)
- Σ \mathbf{\Sigma} Σ: m × n m \times n m×n 对角矩阵(奇异值,从大到小排列)
- V \mathbf{V} V: n × n n \times n n×n 正交矩阵(右奇异向量)
在实际计算中(如 full_matrices=False),通常使用紧凑SVD:
- U U U: m × k m \times k m×k
- Σ \Sigma Σ: k × k k \times k k×k (对角线)
- V T V^T VT: k × n k \times n k×n
其中 k = min ( m , n ) k = \min(m, n) k=min(m,n)
# SVD分解
A = np.array([[1, 2, 3], [4, 5, 6]]) # shape (2, 3)
# full_matrices=False 返回紧凑SVD
U, S, Vt = np.linalg.svd(A, full_matrices=False)
print(f"U shape: {U.shape}") # (2, 2)
print(f"S: {S}") # 奇异值向量 (2,)
print(f"Vt shape: {Vt.shape}") # (2, 3)
# 重构原矩阵
A_reconstructed = U @ np.diag(S) @ Vt
print(f"重构误差: {np.linalg.norm(A - A_reconstructed)}")
低秩近似
SVD的杀手级应用:保留前k个奇异值,实现数据压缩
A k = ∑ i = 1 k σ i u i v i T \mathbf{A}_k = \sum_{i=1}^{k} \sigma_i \mathbf{u}_i \mathbf{v}_i^T Ak=i=1∑kσiuiviT
这是矩阵的最佳低秩近似(Frobenius范数意义下)。
应用场景:
- 图像压缩
- 推荐系统(矩阵分解)
- 降噪
- 潜在语义分析(LSA)
def svd_compress(matrix, k):
"""使用SVD压缩矩阵,保留前k个奇异值"""
U, S, Vt = np.linalg.svd(matrix, full_matrices=False)
# 只有当k小于min(m,n)时才有压缩效果
k = min(k, len(S))
return U[:, :k] @ np.diag(S[:k]) @ Vt[:k, :]
# 图像压缩示例
# original_image: (512, 512) 灰度图
# compressed = svd_compress(original_image, k=50) # 只保留50个奇异值
# 压缩比: 512*512 / (512*50 + 50 + 50*512) ≈ 5倍
1.6 矩阵分解总结
| 分解方法 | 适用范围 | 形式 | 典型应用 |
|---|---|---|---|
| 特征分解 | 方阵(最好对称) | A = Q Λ Q T A = Q\Lambda Q^T A=QΛQT | PCA、谱聚类 |
| SVD | 任意矩阵 | A = U Σ V T A = U\Sigma V^T A=UΣVT | 降维、推荐、压缩 |
| LU分解 | 方阵 | A = L U A = LU A=LU | 解线性方程组 |
| QR分解 | 任意矩阵 | A = Q R A = QR A=QR | 最小二乘、特征值计算 |
| Cholesky | 正定矩阵 | A = L L T A = LL^T A=LLT | 高斯过程、采样 |
2. 概率论与统计
2.1 为什么需要概率?
机器学习面对的是不确定性:
- 数据本身有噪声
- 模型只是对真实世界的近似
- 我们需要量化预测的置信度
概率论是量化不确定性的语言
2.2 概率基础回顾
基本概念
| 概念 | 符号 | 含义 |
|---|---|---|
| 概率 | P ( A ) P(A) P(A) | 事件A发生的可能性 |
| 条件概率 | $P(A | B)$ |
| 联合概率 | P ( A , B ) P(A, B) P(A,B) | A和B同时发生的概率 |
| 边缘概率 | P ( A ) = ∑ B P ( A , B ) P(A) = \sum_B P(A, B) P(A)=∑BP(A,B) | 对其他变量求和/积分 |
两大学派
| 频率派 | 贝叶斯派 | |
|---|---|---|
| 概率的含义 | 长期频率的极限 | 主观置信度 |
| 参数θ | 固定但未知的常数 | 随机变量,有分布 |
| 核心方法 | 极大似然估计 | 后验推断 |
| 代表算法 | 逻辑回归、SVM | 贝叶斯网络、GPR |
2.3 常用概率分布
离散分布
import scipy.stats as stats
# 伯努利分布:抛硬币
bernoulli = stats.bernoulli(p=0.7)
# 二项分布:n次伯努利试验中成功的次数
binomial = stats.binom(n=10, p=0.7)
# 多项分布:骰子,多分类的softmax输出
# P(X1=x1, ..., Xk=xk) = n! / (x1!...xk!) * p1^x1 * ... * pk^xk
# 泊松分布:单位时间内事件发生的次数
poisson = stats.poisson(mu=3)
连续分布
# 正态分布/高斯分布:最重要的分布
normal = stats.norm(loc=0, scale=1) # 标准正态
# 多元正态分布
mean = np.array([0, 0])
cov = np.array([[1, 0.5], [0.5, 1]])
multivariate_normal = stats.multivariate_normal(mean, cov)
# 均匀分布
uniform = stats.uniform(loc=0, scale=1)
# 指数分布:事件间隔时间
exponential = stats.expon(scale=1)
# Beta分布:概率的概率,用于建模[0,1]之间的值
beta = stats.beta(a=2, b=5)
# Gamma分布:正值的连续分布
gamma = stats.gamma(a=2, scale=1)
分布之间的关系图
┌─────────────┐
│ 二项分布 │
└──────┬──────┘
│ n→∞ (CLT)
┌──────▼──────┐
│ 正态分布 │
└─────────────┘
▲
│ n→∞, np=λ
┌──────┴──────┐
│ 泊松分布 │
└─────────────┘
Beta(1,1) = Uniform(0,1)
Gamma(1,λ) = Exponential(λ) (注:λ为率参数)
χ²(k) = Gamma(k/2, 2)
2.4 极大似然估计 (MLE)
核心思想
给定观测数据 D = { x 1 , . . . , x n } \mathcal{D} = \{x_1, ..., x_n\} D={x1,...,xn},找到使数据出现概率最大的参数:
θ ^ M L E = arg max θ P ( D ∣ θ ) = arg max θ ∏ i = 1 n P ( x i ∣ θ ) \hat{\theta}_{MLE} = \arg\max_\theta P(\mathcal{D}|\theta) = \arg\max_\theta \prod_{i=1}^{n} P(x_i|\theta) θ^MLE=argθmaxP(D∣θ)=argθmaxi=1∏nP(xi∣θ)
实际中取对数(将乘法变加法,数值更稳定):
θ ^ M L E = arg max θ ∑ i = 1 n log P ( x i ∣ θ ) \hat{\theta}_{MLE} = \arg\max_\theta \sum_{i=1}^{n} \log P(x_i|\theta) θ^MLE=argθmaxi=1∑nlogP(xi∣θ)
例子:高斯分布的MLE
def gaussian_mle(data):
"""估计高斯分布的参数"""
# MLE解析解
mu_mle = np.mean(data)
# 注意:MLE估计的方差是有偏的 (除以 n)
sigma2_mle = np.var(data, ddof=0)
# 无偏估计通常用于样本方差 (除以 n-1)
sigma2_unbiased = np.var(data, ddof=1)
return mu_mle, sigma2_mle
# 生成数据
true_mu, true_sigma = 5, 2
data = np.random.normal(true_mu, true_sigma, 1000)
# MLE估计
estimated_mu, estimated_sigma2 = gaussian_mle(data)
print(f"真实参数: μ={true_mu}, σ²={true_sigma**2}")
print(f"MLE估计: μ={estimated_mu:.2f}, σ²={estimated_sigma2:.2f}")
深度学习中的MLE
- 分类任务:交叉熵损失 = 负对数似然
- 回归任务:MSE损失 = 假设高斯噪声时的负对数似然
# 交叉熵损失就是负对数似然
def cross_entropy_loss(y_true, y_pred):
"""y_pred是softmax输出的概率"""
return -np.sum(y_true * np.log(y_pred + 1e-8))
# 等价于:最大化正确类别的概率
2.5 贝叶斯推断
贝叶斯定理
P ( θ ∣ D ) = P ( D ∣ θ ) P ( θ ) P ( D ) P(\theta|\mathcal{D}) = \frac{P(\mathcal{D}|\theta) P(\theta)}{P(\mathcal{D})} P(θ∣D)=P(D)P(D∣θ)P(θ)
| 术语 | 符号 | 含义 |
|---|---|---|
| 后验 | $P(\theta | \mathcal{D})$ |
| 似然 | $P(\mathcal{D} | \theta)$ |
| 先验 | P ( θ ) P(\theta) P(θ) | 看到数据前对参数的信念 |
| 证据 | P ( D ) P(\mathcal{D}) P(D) | 数据的边缘概率(归一化常数) |
核心思想:
后验 ∝ 似然 × 先验 \text{后验} \propto \text{似然} \times \text{先验} 后验∝似然×先验
贝叶斯 vs MLE
# MLE: 点估计
theta_mle = np.mean(data) # 一个值
# 贝叶斯: 分布估计
# theta ~ N(mu_posterior, sigma_posterior) # 一个分布
# 贝叶斯的优势:
# 1. 可以量化不确定性
# 2. 可以融入先验知识
# 3. 小样本时更稳健(正则化效果)
MAP估计
最大后验估计(Maximum A Posteriori)是MLE和全贝叶斯的折中:
θ ^ M A P = arg max θ P ( θ ∣ D ) = arg max θ [ P ( D ∣ θ ) P ( θ ) ] \hat{\theta}_{MAP} = \arg\max_\theta P(\theta|\mathcal{D}) = \arg\max_\theta [P(\mathcal{D}|\theta) P(\theta)] θ^MAP=argθmaxP(θ∣D)=argθmax[P(D∣θ)P(θ)]
# MAP = MLE + 正则化
# 假设先验是高斯分布 P(θ) ∝ exp(-θ²/2σ²)
# MAP = argmax [log P(D|θ) + log P(θ)]
# = argmax [log P(D|θ) - θ²/2σ²]
# = MLE + L2正则化 (最小化 -log P)
# 假设先验是拉普拉斯分布 P(θ) ∝ exp(-|θ|/b)
# MAP = MLE + L1正则化
2.6 EM算法
问题背景
有时我们的模型包含隐变量(latent variables)——观测不到但影响数据的因素。
例如:高斯混合模型(GMM)
- 观测到:数据点 x x x
- 隐变量:每个点属于哪个高斯成分 z z z
直接优化似然函数很困难,因为需要对隐变量积分/求和。
EM算法框架
E步(Expectation):固定参数,估计隐变量的后验分布
Q ( θ , θ ( t ) ) = E z ∼ P ( z ∣ x , θ ( t ) ) [ log P ( x , z ∣ θ ) ] Q(\theta, \theta^{(t)}) = \mathbb{E}_{z \sim P(z|x, \theta^{(t)})} [\log P(x, z|\theta)] Q(θ,θ(t))=Ez∼P(z∣x,θ(t))[logP(x,z∣θ)]
M步(Maximization):固定隐变量分布,优化参数
θ ( t + 1 ) = arg max θ Q ( θ , θ ( t ) ) \theta^{(t+1)} = \arg\max_\theta Q(\theta, \theta^{(t)}) θ(t+1)=argθmaxQ(θ,θ(t))
def em_gmm(X, K, max_iter=100):
"""高斯混合模型的EM算法"""
n, d = X.shape
# 初始化参数
mu = X[np.random.choice(n, K, replace=False)] # K个中心
sigma = np.array([np.eye(d)] * K) # K个协方差矩阵
pi = np.ones(K) / K # 混合权重
for _ in range(max_iter):
# E步:计算每个点属于每个成分的后验概率
gamma = np.zeros((n, K))
for k in range(K):
gamma[:, k] = pi[k] * multivariate_normal_pdf(X, mu[k], sigma[k])
# 归一化 (防止除零,通常加eps)
gamma /= (gamma.sum(axis=1, keepdims=True) + 1e-10)
# M步:更新参数
Nk = gamma.sum(axis=0) # 每个成分的有效样本数
for k in range(K):
# 加权平均
mu[k] = (gamma[:, k:k+1] * X).sum(axis=0) / (Nk[k] + 1e-10)
diff = X - mu[k]
sigma[k] = (gamma[:, k:k+1] * diff).T @ diff / (Nk[k] + 1e-10)
pi[k] = Nk[k] / n
return mu, sigma, pi, gamma
EM的应用
- GMM聚类:软聚类
- HMM训练:Baum-Welch算法
- 话题模型:pLSA
- 缺失数据处理:填补缺失值
3. 优化理论
3.1 为什么优化是核心?
机器学习的本质就是优化问题:
min θ L ( θ ) = 1 n ∑ i = 1 n ℓ ( f θ ( x i ) , y i ) + λ R ( θ ) \min_\theta \mathcal{L}(\theta) = \frac{1}{n} \sum_{i=1}^{n} \ell(f_\theta(x_i), y_i) + \lambda R(\theta) θminL(θ)=n1i=1∑nℓ(fθ(xi),yi)+λR(θ)
- L \mathcal{L} L:总损失函数
- ℓ \ell ℓ:单样本损失
- R ( θ ) R(\theta) R(θ):正则项
- θ \theta θ:需要优化的参数
3.2 凸优化基础
凸函数
函数 f f f 是凸函数,当且仅当:
f ( α x + ( 1 − α ) y ) ≤ α f ( x ) + ( 1 − α ) f ( y ) , ∀ α ∈ [ 0 , 1 ] f(\alpha x + (1-\alpha) y) \leq \alpha f(x) + (1-\alpha) f(y), \quad \forall \alpha \in [0, 1] f(αx+(1−α)y)≤αf(x)+(1−α)f(y),∀α∈[0,1]
直觉:弦在曲线上方
重要性质:凸函数的局部最优 = 全局最优
# 常见凸函数
# f(x) = x² (强凸)
# f(x) = |x| (凸)
# f(x) = max(0, 1-x) (Hinge Loss, 凸)
# f(x) = log(1 + exp(-x)) (Logistic Loss, 凸)
# 非凸函数
# 神经网络的损失函数(几乎一定非凸)
凸优化 vs 非凸优化
| 凸优化 | 非凸优化 | |
|---|---|---|
| 局部最优 | = 全局最优 | ≠ 全局最优 |
| 典型算法 | SVM, 逻辑回归 | 神经网络 |
| 收敛保证 | 强理论保证 | 只能保证到驻点 |
| 实际表现 | 可能欠拟合 | 通常效果更好 |
3.3 梯度下降
基本形式
θ t + 1 = θ t − η ∇ θ L ( θ t ) \theta_{t+1} = \theta_t - \eta \nabla_\theta \mathcal{L}(\theta_t) θt+1=θt−η∇θL(θt)
直觉:沿着下坡最快的方向走一小步
def gradient_descent(grad_fn, init_theta, lr=0.01, max_iter=1000, tol=1e-6):
"""基础梯度下降"""
theta = init_theta.copy()
for i in range(max_iter):
grad = grad_fn(theta)
theta_new = theta - lr * grad
if np.linalg.norm(theta_new - theta) < tol:
print(f"收敛于迭代 {i}")
break
theta = theta_new
return theta
梯度下降变体
| 变体 | 公式 | 特点 |
|---|---|---|
| BGD | 全量数据计算梯度 | 稳定但慢 |
| SGD | 单样本计算梯度 | 快但噪声大 |
| Mini-batch SGD | 小批量计算梯度 | 折中,最常用 |
def sgd_minibatch(data, labels, model, loss_fn, lr, batch_size, epochs):
"""Mini-batch SGD 伪代码"""
n = len(data)
for epoch in range(epochs):
# 打乱数据
indices = np.random.permutation(n)
for i in range(0, n, batch_size):
batch_idx = indices[i:i+batch_size]
batch_x, batch_y = data[batch_idx], labels[batch_idx]
# 前向传播 + 计算损失
pred = model.forward(batch_x)
loss = loss_fn(pred, batch_y)
# 反向传播 (得到关于参数的梯度)
grad = model.backward(loss)
# 参数更新
model.params -= lr * grad
动量法 (Momentum)
问题:SGD在"峡谷"地形中震荡
解决:累积历史梯度方向
v t = γ v t − 1 + η ∇ θ L ( θ t ) v_t = \gamma v_{t-1} + \eta \nabla_\theta \mathcal{L}(\theta_t) vt=γvt−1+η∇θL(θt)
θ t + 1 = θ t − v t \theta_{t+1} = \theta_t - v_t θt+1=θt−vt
def sgd_momentum(grad_fn, init_theta, lr=0.01, momentum=0.9, max_iter=1000):
theta = init_theta.copy()
v = np.zeros_like(theta)
for i in range(max_iter):
grad = grad_fn(theta)
# v = momentum * v + lr * grad (标准实现)
# 或者是PyTorch风格: v = momentum * v + grad; theta -= lr * v
v = momentum * v + lr * grad
theta = theta - v
return theta
Adam优化器
结合动量 + 自适应学习率:
m t = β 1 m t − 1 + ( 1 − β 1 ) g t m_t = \beta_1 m_{t-1} + (1-\beta_1) g_t mt=β1mt−1+(1−β1)gt
(一阶矩估计)
v t = β 2 v t − 1 + ( 1 − β 2 ) g t 2 v_t = \beta_2 v_{t-1} + (1-\beta_2) g_t^2 vt=β2vt−1+(1−β2)gt2
(二阶矩估计)
m ^ t = m t / ( 1 − β 1 t ) \hat{m}_t = m_t / (1-\beta_1^t) m^t=mt/(1−β1t)
(偏差校正)
v ^ t = v t / ( 1 − β 2 t ) \hat{v}_t = v_t / (1-\beta_2^t) v^t=vt/(1−β2t)
θ t + 1 = θ t − η m ^ t v ^ t + ϵ \theta_{t+1} = \theta_t - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon} θt+1=θt−ηv^t+ϵm^t
class Adam:
def __init__(self, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8):
self.lr = lr
self.beta1 = beta1
self.beta2 = beta2
self.eps = eps
self.m = None
self.v = None
self.t = 0
def update(self, params, grads):
if self.m is None:
self.m = np.zeros_like(params)
self.v = np.zeros_like(params)
self.t += 1
# 更新一阶和二阶矩估计
self.m = self.beta1 * self.m + (1 - self.beta1) * grads
self.v = self.beta2 * self.v + (1 - self.beta2) * (grads ** 2)
# 偏差校正
m_hat = self.m / (1 - self.beta1 ** self.t)
v_hat = self.v / (1 - self.beta2 ** self.t)
# 更新参数
params -= self.lr * m_hat / (np.sqrt(v_hat) + self.eps)
return params
3.4 学习率策略
| 策略 | 公式 | 适用场景 |
|---|---|---|
| 固定 | η = c o n s t \eta = const η=const | 简单任务 |
| 阶梯衰减 | 每N个epoch乘以γ | 传统CV |
| 指数衰减 | η t = η 0 ⋅ γ t \eta_t = \eta_0 \cdot \gamma^t ηt=η0⋅γt | |
| 余弦退火 | η t = η m i n + 1 2 ( η m a x − η m i n ) ( 1 + cos ( t T π ) ) \eta_t = \eta_{min} + \frac{1}{2}(\eta_{max}-\eta_{min})(1+\cos(\frac{t}{T}\pi)) ηt=ηmin+21(ηmax−ηmin)(1+cos(Ttπ)) | 大模型预训练 |
| Warmup | 前几步线性增加 | Transformer |
| OneCycleLR | 先增后减 | 快速训练 |
def cosine_annealing(epoch, total_epochs, lr_max, lr_min=0):
"""余弦退火学习率"""
return lr_min + 0.5 * (lr_max - lr_min) * (1 + np.cos(np.pi * epoch / total_epochs))
def warmup_cosine(epoch, warmup_epochs, total_epochs, lr_max, lr_min=0):
"""带Warmup的余弦退火"""
if epoch < warmup_epochs:
return lr_max * epoch / warmup_epochs
else:
return cosine_annealing(epoch - warmup_epochs, total_epochs - warmup_epochs, lr_max, lr_min)
3.5 约束优化与拉格朗日乘子
问题形式
min x f ( x ) s.t. g ( x ) ≤ 0 , h ( x ) = 0 \min_x f(x) \quad \text{s.t.} \quad g(x) \leq 0, \quad h(x) = 0 xminf(x)s.t.g(x)≤0,h(x)=0
拉格朗日函数
L ( x , λ , μ ) = f ( x ) + ∑ i λ i g i ( x ) + ∑ j μ j h j ( x ) \mathcal{L}(x, \lambda, \mu) = f(x) + \sum_i \lambda_i g_i(x) + \sum_j \mu_j h_j(x) L(x,λ,μ)=f(x)+i∑λigi(x)+j∑μjhj(x)
KKT条件
最优点必须满足的条件:
- 定常性: ∇ x L = 0 \nabla_x \mathcal{L} = 0 ∇xL=0
- 原始可行性: g ( x ) ≤ 0 , h ( x ) = 0 g(x) \leq 0, h(x) = 0 g(x)≤0,h(x)=0
- 对偶可行性: λ ≥ 0 \lambda \geq 0 λ≥0
- 互补松弛: λ i g i ( x ) = 0 \lambda_i g_i(x) = 0 λigi(x)=0
应用:SVM的推导依赖于拉格朗日对偶
# SVM的原始问题:
# min 1/2 ||w||²
# s.t. y_i(w·x_i + b) >= 1
# 拉格朗日函数:
# L = 1/2 ||w||² - Σ α_i [y_i(w·x_i + b) - 1]
# 对偶问题(更容易求解):
# max Σ α_i - 1/2 Σ_ij α_i α_j y_i y_j (x_i · x_j)
# s.t. α_i >= 0, Σ α_i y_i = 0
3.6 二阶优化方法
牛顿法
利用二阶导数(Hessian矩阵)信息:
θ t + 1 = θ t − H − 1 ∇ θ L \theta_{t+1} = \theta_t - H^{-1} \nabla_\theta \mathcal{L} θt+1=θt−H−1∇θL
优点:收敛快(二次收敛)
缺点:Hessian计算和求逆代价高 O ( n 3 ) O(n^3) O(n3)
拟牛顿法
近似Hessian逆矩阵,避免直接计算:
- BFGS:经典方法
- L-BFGS:限制内存版本,大规模优化常用
from scipy.optimize import minimize
def objective(x):
return (x[0] - 1)**2 + (x[1] - 2.5)**2
result = minimize(objective, x0=[0, 0], method='L-BFGS-B')
print(f"最优解: {result.x}")
4. 信息论基础
4.1 为什么信息论很重要?
信息论提供了量化"信息"和"不确定性"的数学工具:
- 损失函数设计(交叉熵)
- 模型评估(困惑度)
- 特征选择(互信息)
- 变分推断(KL散度)
4.2 熵 (Entropy)
定义
随机变量的不确定性度量:
H ( X ) = − ∑ x P ( x ) log P ( x ) = E [ − log P ( X ) ] H(X) = -\sum_{x} P(x) \log P(x) = \mathbb{E}[-\log P(X)] H(X)=−x∑P(x)logP(x)=E[−logP(X)]
直觉:
- 熵高 → 不确定性大 → 难以预测
- 熵低 → 确定性高 → 容易预测
def entropy(probs):
"""计算离散分布的熵 (Bits)"""
probs = np.array(probs)
probs = probs[probs > 0] # 避免log(0)
return -np.sum(probs * np.log2(probs))
# 例子:公平硬币 vs 不公平硬币
fair_coin = entropy([0.5, 0.5]) # = 1 bit
biased_coin = entropy([0.9, 0.1]) # ≈ 0.47 bit
certain = entropy([1.0, 0.0]) # = 0 bit
print(f"公平硬币熵: {fair_coin:.2f} bits")
print(f"偏置硬币熵: {biased_coin:.2f} bits")
联合熵与条件熵
H ( X , Y ) = − ∑ x , y P ( x , y ) log P ( x , y ) H(X, Y) = -\sum_{x,y} P(x, y) \log P(x, y) H(X,Y)=−x,y∑P(x,y)logP(x,y)
H ( Y ∣ X ) = H ( X , Y ) − H ( X ) H(Y|X) = H(X, Y) - H(X) H(Y∣X)=H(X,Y)−H(X)
链式法则: H ( X , Y ) = H ( X ) + H ( Y ∣ X ) H(X, Y) = H(X) + H(Y|X) H(X,Y)=H(X)+H(Y∣X)
4.3 KL散度
定义
两个分布之间的"距离"(实际上不是真正的距离):
D K L ( P ∣ ∣ Q ) = ∑ x P ( x ) log P ( x ) Q ( x ) = E P [ log P ( X ) Q ( X ) ] D_{KL}(P || Q) = \sum_x P(x) \log \frac{P(x)}{Q(x)} = \mathbb{E}_P \left[ \log \frac{P(X)}{Q(X)} \right] DKL(P∣∣Q)=x∑P(x)logQ(x)P(x)=EP[logQ(X)P(X)]
直觉:用Q来近似P时,平均需要多少额外的bit
def kl_divergence(p, q):
"""计算KL散度 (Nats)"""
p, q = np.array(p), np.array(q)
# 避免除以0和log(0)
# 仅当p>0时计算,且若q=0则距离为无穷大
# 此处添加epsilon保证数值稳定性
q = q + 1e-10
mask = p > 0
return np.sum(p[mask] * np.log(p[mask] / q[mask]))
# 注意:KL散度不对称!
p = [0.4, 0.6]
q = [0.5, 0.5]
print(f"KL(P||Q) = {kl_divergence(p, q):.4f}")
print(f"KL(Q||P) = {kl_divergence(q, p):.4f}")
KL散度的性质
- 非负性: D K L ( P ∣ ∣ Q ) ≥ 0 D_{KL}(P||Q) \geq 0 DKL(P∣∣Q)≥0,当且仅当 P = Q P = Q P=Q 时等号成立
- 不对称性: D K L ( P ∣ ∣ Q ) ≠ D K L ( Q ∣ ∣ P ) D_{KL}(P||Q) \neq D_{KL}(Q||P) DKL(P∣∣Q)=DKL(Q∣∣P)
- 不满足三角不等式:不是真正的距离
前向KL vs 反向KL
| | 前向KL: D K L ( P ∣ ∣ Q ) D_{KL}(P||Q) DKL(P∣∣Q) | 反向KL: D K L ( Q ∣ ∣ P ) D_{KL}(Q||P) DKL(Q∣∣P) |
|—|------------------------|------------------------|
| 优化目标 | 最小化 − E P [ log Q ] -\mathbb{E}_P[\log Q] −EP[logQ] | 最小化 − E Q [ log Q ] + E Q [ log P ] -\mathbb{E}_Q[\log Q] + \mathbb{E}_Q[\log P] −EQ[logQ]+EQ[logP] |
| 行为 | 均值寻求 (mean-seeking) | 众数寻求 (mode-seeking) |
| 覆盖 | Q尽量覆盖P的所有模式 | Q集中在P的一个模式 |
| 应用 | 变分推断 (VAE) | 策略梯度 |
4.4 交叉熵
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)
与KL散度的关系:
H ( P , Q ) = H ( P ) + D K L ( P ∣ ∣ Q ) H(P, Q) = H(P) + D_{KL}(P||Q) H(P,Q)=H(P)+DKL(P∣∣Q)
因为 H ( P ) H(P) H(P) 是常数,最小化交叉熵 = 最小化KL散度
def cross_entropy(p, q):
"""计算交叉熵"""
p, q = np.array(p), np.array(q)
# 添加 epsilon 防止 log(0)
return -np.sum(p * np.log(q + 1e-10))
# 在深度学习中:
# p = one-hot真实标签
# q = softmax预测概率
# cross_entropy(p, q) 就是分类损失
4.5 互信息
I ( X ; Y ) = H ( X ) − H ( X ∣ Y ) = H ( Y ) − H ( Y ∣ X ) = D K L ( P X Y ∣ ∣ P X P Y ) I(X; Y) = H(X) - H(X|Y) = H(Y) - H(Y|X) = D_{KL}(P_{XY} || P_X P_Y) I(X;Y)=H(X)−H(X∣Y)=H(Y)−H(Y∣X)=DKL(PXY∣∣PXPY)
直觉:知道Y后,X的不确定性减少了多少
def mutual_information(joint_prob):
"""计算互信息
joint_prob: 联合概率分布矩阵 P(X, Y)
"""
# 边缘分布
p_x = joint_prob.sum(axis=1)
p_y = joint_prob.sum(axis=0)
mi = 0
for i in range(len(p_x)):
for j in range(len(p_y)):
# 只累加概率大于0的项
if joint_prob[i, j] > 0:
mi += joint_prob[i, j] * np.log(
joint_prob[i, j] / (p_x[i] * p_y[j] + 1e-10)
)
return mi
# 应用:特征选择
# 选择与标签Y互信息最大的特征X
4.6 信息论在ML中的应用总结
| 概念 | 应用场景 |
|---|---|
| 熵 | 决策树分裂准则、模型不确定性 |
| 交叉熵 | 分类损失函数 |
| KL散度 | VAE损失、知识蒸馏、策略优化 |
| 互信息 | 特征选择、表示学习(InfoNCE) |
| 困惑度(Perplexity) | 语言模型评估 |
5. 总结
5.1 知识图谱
机器学习数学基础
│
┌────────────────────┼────────────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
│ 线性代数 │ │ 概率统计 │ │ 优化理论 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
┌─────┼─────┐ ┌─────┼─────┐ ┌─────┼─────┐
│ │ │ │ │ │ │ │ │
向量 矩阵 分解 分布 估计 推断 凸 梯度 约束
空间 变换 SVD 概型 MLE 贝叶斯 优化 下降 优化
│
EM
┌───────┴───────┐
│ 信息论 │
└───────┬───────┘
│
┌────────────┼────────────┐
│ │ │
熵 KL散度 互信息
5.2 一句话总结
| 领域 | 核心思想 |
|---|---|
| 线性代数 | 数据是向量,模型是变换,训练是找最好的变换矩阵 |
| 概率统计 | 用概率描述不确定性,用数据更新信念 |
| 优化理论 | 学习就是找到损失函数的最小值点 |
| 信息论 | 用bit度量信息,用熵度量不确定性 |
5.3 下一步
- Day 2:传统机器学习算法(上)
- 练习:实现一个简单的MLE估计和梯度下降
📚 参考资源
书籍
- 《深度学习》(花书) - 第2-4章
- 《Pattern Recognition and Machine Learning》(PRML) - Bishop
- 《统计学习方法》- 李航
- 《Convex Optimization》- Boyd
在线课程
- Stanford CS229: Machine Learning
- MIT 18.06: Linear Algebra (Gilbert Strang)
- Stanford EE364a: Convex Optimization
工具
- NumPy、SciPy:数值计算
- SymPy:符号计算
- 3Blue1Brown:线性代数可视化
明日预告:Day 2 我们将深入传统机器学习算法,包括线性回归、逻辑回归、决策树、随机森林和SVM。这些是理解深度学习的重要基石。
如果有更多问题,欢迎关注公众号【算法最TOP】进一步讨论!
更多推荐


所有评论(0)