机器学习数学推导(一)绪论与数学基础
Chen Kai BOSS

2005 年, Google Research 发布了一篇论文,声称他们在机器翻译任务上使用简单的统计模型超越了精心设计的专家系统。这引发了一个深刻的问题:为什么简单的模型能够从数据中学习到有效的模式? 这个问题的答案藏在机器学习的数学理论中。

机器学习的核心问题是:给定有限的训练样本,如何保证学到的模型在未见过的数据上仍能表现良好?这不是一个工程问题,而是一个数学问题——它涉及概率论、泛函分析、优化理论的深层结构。本系列从数学第一性原理出发,严格推导机器学习的理论基础。

机器学习的基本概念

学习问题的数学形式化

从房价预测说起

想象你是房地产中介,客户问:"这个小区的房子值多少钱?"

你有一些历史数据(已知的小区和房价): - 小区A:面积100㎡,地铁500米,价格300万 - 小区B:面积80㎡,地铁2公里,价格200万 - 小区C:面积120㎡,地铁100米,价格450万 - ...(共100个小区的数据)

现在来了个新小区:面积90㎡,地铁1公里,价格是多少?

这就是一个机器学习问题!你需要: 1. 从历史数据中找到"规律" 2. 用这个规律预测新小区的价格

用数学语言重新描述

假设存在一个未知的数据生成分布,定义在输入空间(小区特征)和输出空间(房价)的笛卡尔积上。学习算法的目标是从有限的训练样本(100个历史数据)中找到一个假设(预测公式),使其在整个分布(所有可能的小区)上的期望损失最小。

翻译成人话: - :现实世界中所有小区和房价的关系(我们不知道具体规律) -:小区的特征(面积、地段等) -:房价 -:我们要找的预测公式 - 目标:让预测尽可能准确

定义 1(损失函数):损失函数衡量预测值与真实值之间的差异。常见的损失函数包括:

  • 0-1 损失(分类)𝟙
  • 平方损失(回归)
  • Hinge 损失(支持向量机)

定义 2(泛化误差):假设在分布上的泛化误差定义为:

这个期望是对所有可能的输入-输出对计算的,代表模型在未见数据上的真实表现。

定义 3(经验误差):给定训练集,经验误差定义为:

这是模型在训练集上的平均损失,可以直接计算。

机器学习的核心矛盾:我们只能观测到(经验误差),但真正关心的是(泛化误差)。学习理论的核心任务是建立两者之间的关系。

监督学习的三要素

监督学习可以用一个三元组完整描述:

假设空间:所有可能的假设函数的集合。例如:

  • 线性假设空间:
  • 多项式假设空间:

假设空间的选择决定了模型的表达能力。空间越大,表达能力越强,但学习难度也越高。

损失函数:前面已定义,它将学习问题转化为优化问题。

学习算法:一个从训练集到假设的映射:

常见的学习算法包括:

  • 经验风险最小化(ERM)
  • 结构风险最小化(SRM),其中是复杂度惩罚项

PAC 学习框架:可学习性的数学刻画

PAC 学习的定义

先理解名字:Probably Approximately Correct

一个通俗的例子:预测明天是否下雨

假设我给你看100天的天气数据(云量、气压、温度等),你学到一个预测规则。现在问:

P - Probably(有一定把握): - 问:你能100%保证学会吗? - 答:不能,但我有95%的把握! - 意思:100次尝试中,95次能学到好规则 - 数学:以的概率成功(表示5%失败率)

A - Approximately(差不多对): - 问:你的预测能100%准确吗? - 答:不能,但误差会小于10%! - 意思:预测准确率>90% - 数学:误差不超过表示10%误差)

C - Correct(在真实数据上对): - 问:在哪里准确? - 答:不是只在那100天数据上准,而是在未来的新天气上也准! - 意思:真正的泛化能力 - 数学:误差是在真实分布上衡量

PAC 学习的严格定义

Probably Approximately Correct (PAC) 学习框架由 Valiant 在 1984 年提出,它回答了:"要看多少天气数据,才能学会预测天气?"

定义 4(PAC 可学习):假设类是 PAC 可学习的,如果存在函数和学习算法,使得对于任意分布,任意(精度参数)和(置信度参数),当训练集大小时,以至少的概率,算法输出的假设满足:

用房价预测例子翻译这个定义: - 训练集大小:需要看多少个历史小区数据 - 精度:预测误差的上限(比如10万元) - 置信度:失败的概率(比如5%) - 结论:如果看够个历史数据,就有95%的把握,预测误差<10万元

这个定义包含三个关键要素:

  1. Probably(以高概率):事件以至少的概率发生
  2. Approximately(近似最优):泛化误差与最优假设的差距不超过
  3. Correct(正确):误差是在真实分布上衡量的

样本复杂度 是 PAC 学习的核心量:它告诉我们需要多少训练样本才能保证学习成功。样本复杂度越低,问题越容易学习。

有限假设空间的 PAC 可学习性

我们先考虑最简单的情况:假设空间是有限的,即。这种情况在理论分析中非常重要,因为它为一般情况提供了直觉。

定理 1(有限假设空间的样本复杂度):设是有限假设空间,使用 0-1 损失。对于任意,如果训练集大小满足:

则经验风险最小化算法是 PAC 学习算法。

证明

步骤 1:定义坏假设集合

对于任意,如果,我们称为"坏假设"。定义坏假设集合:

我们的目标是证明:以高概率,ERM 算法不会选择坏假设。

步骤 2:分析单个坏假设的概率

对于固定的坏假设,它在训练集上表现"好"(即)的概率是多少?

因为,所以在随机抽取的一个样本上犯错的概率大于

因此,在所有个样本上都不犯错的概率最多为:

这里使用了独立性假设:个样本独立同分布抽取。

步骤 3:使用 Union Bound

定义事件:存在某个坏假设在训练集上经验误差为 0:Extra close brace or missing open braceA = \bigcup_{h \in \mathcal{H}_{\text{bad}}} \{L_S(h) = 0\\}

使用 Union Bound(概率的并集不等式):

步骤 4:使用不等式

这是标准的指数不等式。因此:

要使这个概率小于,需要:

两边取对数并重排:

步骤 5:结论

当样本数满足上述条件时,以至少的概率,所有在训练集上经验误差为 0 的假设都不是坏假设,即它们的泛化误差都不超过。因为 ERM 算法选择的假设经验误差为 0(假设可实现),所以它的泛化误差不超过。证毕。

定理的直觉

-项:假设空间越大,需要的样本越多,这很直观 -项:要求更高的置信度,需要更多样本 -项:要求更高的精度,需要更多样本

下图展示了 PAC 学习中样本复杂度与精度参数、假设空间大小的关系,以及泛化误差随样本数增加而下降的趋势:

PAC Learning Sample Complexity

例子(布尔函数学习)

考虑维布尔向量的合取范式(Conjunction)学习。假设空间大小为(每个变量可以是正文字、负文字或不出现)。要达到的精度和的置信度,需要:

这是线性于特征维度的样本复杂度,非常高效。

下面的动图展示了随着训练样本数的增加,学习到的决策边界如何逐步逼近真实边界,泛化误差界也随之缩小——这正是 PAC 学习理论的核心预测:

PAC Learning Convergence

不可知 PAC 学习

前面的分析假设存在完美的假设(可实现假设),但现实中往往不存在。不可知 PAC 学习( Agnostic PAC Learning)放宽了这个假设。

定义 5(不可知 PAC 可学习):假设类是不可知 PAC 可学习的,如果存在函数和算法,使得对于任意分布,任意,当时,以至少的概率:

注意这里不再假设存在零误差的假设。

定理 2(不可知情况的样本复杂度):对于有限假设空间,使用 0-1 损失,样本复杂度为:

证明需要 Hoeffding 不等式,我们将在后续章节详细展开。关键区别在于:

  • 可实现情况:
  • 不可知情况:

精度要求提高一倍,样本需求增加四倍,这是统计学习的基本规律。

VC 维理论:无限假设空间的复杂度度量

从有限到无限:为什么需要 VC 维

前面的结果依赖于,但很多重要的假设空间是无限的。例如:

  • 线性分类器:,包含无穷多个假设
  • 多项式分类器、神经网络等都是无限假设空间

对于无限假设空间,,前面的界退化为无意义。VC 维(Vapnik-Chervonenkis Dimension)提供了一个有限的复杂度度量,即使对于无限假设空间。

打散概念

定义 6(打散):对于样本集,如果假设空间能够实现上的所有可能标记(即对于的每个元素,都存在产生该标记),则称 打散

数学表示:打散当且仅当:

直觉:打散意味着假设空间在这个特定样本集上的表达能力达到最大——可以产生所有可能的标记模式。

VC 维的定义

定义 7(VC 维):假设空间的 VC 维是能被打散的最大样本集的大小:

如果对于任意大小的样本集都存在能被打散的子集,则

关键性质

  1. VC 维是组合量:它不依赖于数据分布,只依赖于的结构
  2. 非单调性:如果不能打散大小为的某个集合,不意味着它不能打散大小更大的其他集合

例子:线性分类器的 VC 维

定理 3上的线性分类器的 VC 维为

证明

第一部分:(存在大小为的可打散集合)

考虑个点:

其中是第个标准基向量。我们要证明线性分类器可以实现这个点上的所有种标记。

给定任意标记,构造权重向量:

验证:

  • 对于,预测为;若,取即可
  • 对于,当时为正,当时为负

通过适当选择,可以实现所有标记。因此

第二部分:(任意个点都不能被打散)

假设存在个点可以被打散。考虑增广向量:

因为,这维向量线性相关,存在不全为零的系数使得:

分割系数为正负两组:。定义标记:

假设存在实现这个标记,即对所有;对所有

加权求和:

左边第一项为正(正系数×正值),第二项为负(正系数×负值),但根据

这与"左边为正减去正值"矛盾。因此不存在这样的个点不能被打散。证毕。

直觉维空间的线性分类器由个参数决定(个权重 + 1 个偏置),所以它能"记住"最多个点的标记,但无法记住更多。

下图直观展示了线性分类器的 VC 维:在 2 维空间中,3 个点可以被任意打散(VC 维≥ 3),但 4 个点(如 XOR 配置)无法被线性分离(VC 维=3):

VC Dimension Visualization

VC 维与样本复杂度

定理 4(Vapnik-Chervonenkis 界):设的 VC 维为。对于不可知 PAC 学习,样本复杂度满足:

更精确的界(Blumer et al., 1989):

证明思路(不完整)

  1. 引入增长函数:大小为的样本集上能实现的不同标记数的最大值
  2. Sauer-Shelah 引理:如果,则:

这比小得多(多项式 vs 指数)

  1. 使用 Uniform Convergence 定理和对称化技巧建立泛化界

完整证明需要更多技术工具,我们在后续章节展开。

应用例子

对于维线性分类器:

  • VC 维:
  • 要达到,需要:

这是线性于维度的样本复杂度,对于高维问题非常实用。

偏差-方差分解:泛化误差的剖析

回归问题的偏差-方差权衡

偏差-方差分解是理解模型泛化能力的另一个重要视角。它将泛化误差分解为三个组分,揭示了模型复杂度与泛化能力的关系。

设定

  • 真实函数:(未知)
  • 观测数据:,其中是均值为 0 的噪声,
  • 学习算法:从训练集学得
  • 损失函数:平方损失

问题:对于固定的测试点,如果我们从分布中抽取多个不同的训练集,每次训练得到不同的,其期望误差是多少?

定理 5(偏差-方差分解):对于固定的,定义:

  • 偏差
  • 方差
  • 噪声

则期望泛化误差满足:

证明

对于固定的,令为预测函数的平均值。

展开平方项(令):

取期望:

1.(方差的定义) 2.(偏差的平方,对取期望时是常数) 3.(噪声方差) 4.(因为) 5.独立,且均值都为 0) 6.(因为

因此:

证毕。

三个组分的解释

  1. 偏差(Bias):模型的平均预测与真实值的差距,反映模型的拟合能力
    • 高偏差:模型太简单,无法捕捉数据的真实模式(欠拟合
    • 例如:用直线拟合二次曲线
  2. 方差(Variance):模型预测在不同训练集上的波动程度,反映模型的稳定性
    • 高方差:模型对训练集的微小变化非常敏感(过拟合
    • 例如:用高次多项式拟合少量数据点
  3. 噪声(Noise):数据本身的随机性,是误差的下界,无法通过改进模型消除

偏差-方差权衡的数值示例

问题设定

真实函数:,定义域

噪声:

训练集:从均匀采样个点

考虑三个模型:

  1. 低复杂度模型:一次多项式(直线)
  2. 适中复杂度模型:三次多项式
  3. 高复杂度模型:九次多项式

实验

  • 从分布中抽取 100 个不同的训练集
  • 对每个训练集,用最小二乘法拟合模型
  • 在测试点处计算偏差和方差

结果(近似值):

模型 偏差² 方差 总误差
一次多项式 0.42 0.002 0.43
三次多项式 0.05 0.02 0.08
九次多项式 0.01 0.35 0.37

分析

  • 一次多项式:高偏差( 0.42)、低方差( 0.002)——模型太简单,无法捕捉 sin 函数的曲线
  • 三次多项式:低偏差( 0.05)、低方差( 0.02)——复杂度适中,效果最好
  • 九次多项式:极低偏差( 0.01)、高方差( 0.35)——模型过于复杂,对训练数据的噪声敏感

权衡曲线:当模型复杂度增加时:

  • 偏差 ↓(拟合能力增强)
  • 方差 ↑(稳定性下降)
  • 存在最优复杂度使总误差最小

下图通过在不同复杂度模型( 1 次、 3 次、 9 次多项式)下重复采样训练,直观展示了偏差-方差分解的三种典型情况,以及两者随模型复杂度变化的权衡关系:

Bias-Variance Decomposition
Bias-Variance Tradeoff

过拟合与欠拟合的数学表征

定义 8(过拟合):如果存在复杂度更低的模型,使得:

则称模型 过拟合了训练数据。

定义 9(欠拟合):如果存在复杂度更高的模型,使得:

则称模型 欠拟合了训练数据。

检测方法

现象 训练误差 验证误差 诊断
良好拟合
欠拟合
过拟合
数据问题

应对策略

  • 过拟合
    1. 增加训练数据
    2. 降低模型复杂度(减少参数)
    3. 正则化( L1/L2,在后续章节详述)
    4. 提前停止( Early Stopping)
    5. Dropout(神经网络)
  • 欠拟合
    1. 增加模型复杂度(更多参数/层)
    2. 增加训练迭代次数
    3. 特征工程(添加交互特征、多项式特征)
    4. 减小正则化强度

No Free Lunch 定理:学习的根本限制

定理陈述

No Free Lunch (NFL)定理( Wolpert & Macready, 1997)指出:在所有可能的问题(数据分布)上平均而言,所有学习算法的性能是相同的。

定理 6(NFL 定理,简化版):考虑所有可能的函数(其中有限)。对于任意两个学习算法,如果对所有目标函数求平均:

证明思路

。所有可能的函数有个。

对于固定的训练集),剩余的个点的标记未知。

学习算法必须对这些未见点做预测。对于任意的预测策略,在所有可能的目标函数上:

  • 有一半的函数使得预测正确
  • 有一半的函数使得预测错误

因此,任意算法的平均错误率都是

定理的含义

  1. 没有万能算法:不存在在所有问题上都表现最好的算法
  2. 先验假设的重要性:算法的有效性依赖于对问题的先验假设(归纳偏置)
  3. 特定问题需要特定算法:算法设计应针对问题的特性

归纳偏置

定义 10(归纳偏置):学习算法在面对多个假设都与训练数据一致时,选择其中一个的倾向,称为归纳偏置( Inductive Bias)。

常见的归纳偏置

  1. 平滑性假设:相邻的输入应产生相邻的输出
    • 适用于连续函数学习
    • 例如: k-NN 、核方法
  2. 线性假设:输出是输入的线性组合
    • 适用于线性可分问题
    • 例如:线性回归、逻辑回归
  3. 稀疏性假设:只有少数特征是重要的
    • 适用于高维低秩问题
    • 例如: L1 正则化、特征选择
  4. 层次结构假设:概念可以由简单概念组合而成
    • 适用于复杂模式识别
    • 例如:深度学习
  5. 时空局部性假设:相关的特征在时空上是局部的
    • 适用于图像、序列数据
    • 例如:卷积神经网络、循环神经网络

例子(奥卡姆剃刀)

在多个与数据一致的假设中,选择最简单的一个。这是一种常见的归纳偏置,对应于正则化方法。

数学表示:

其中度量假设的复杂度(如参数的 L2 范数)。

代码实现:简单线性回归的 PAC 分析

我们通过代码验证理论预测:观察样本复杂度与泛化误差的关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

# 设定随机种子保证可复现性
np.random.seed(42)

# 真实的数据生成过程: y = 2x + 1 + noise
def true_function(x):
"""
真实的数据生成函数

参数:
x: np.array, shape=(n,), 输入数据

返回:
y: np.array, shape=(n,), 输出数据(不含噪声)
"""
return 2 * x + 1

def generate_data(n_samples, noise_std=0.5):
"""
生成训练/测试数据

参数:
n_samples: int, 样本数量
noise_std: float, 噪声标准差,对应于偏差-方差分解中的 sigma

返回:
X: np.array, shape=(n_samples, 1), 输入特征
y: np.array, shape=(n_samples,), 输出标签
"""
# 从[0, 10]均匀分布采样 X
X = np.random.uniform(0, 10, n_samples).reshape(-1, 1)
# 添加高斯噪声: epsilon ~ N(0, sigma^2)
noise = np.random.normal(0, noise_std, n_samples)
y = true_function(X.ravel()) + noise
return X, y

def compute_bias_variance(X_train_list, y_train_list, X_test, y_test_true):
"""
计算偏差和方差

参数:
X_train_list: list of np.array, 多个训练集的 X
y_train_list: list of np.array, 多个训练集的 y
X_test: np.array, shape=(n_test, 1), 测试集 X
y_test_true: np.array, shape=(n_test,), 测试集的真实 y(无噪声)

返回:
bias_squared: float, 偏差的平方
variance: float, 方差
noise: float, 噪声方差(估计值)
"""
n_experiments = len(X_train_list)
predictions = []

# 对每个训练集训练模型并预测
for X_train, y_train in zip(X_train_list, y_train_list):
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
predictions.append(y_pred)

# predictions: shape=(n_experiments, n_test)
predictions = np.array(predictions)

# 计算平均预测:\bar{f}(x) = E_S[\hat{f}_S(x)]
mean_prediction = predictions.mean(axis=0)

# 偏差: Bias = E_S[\hat{f}_S(x)] - f^{*}(x)
bias = mean_prediction - y_test_true
bias_squared = np.mean(bias ** 2)

# 方差: Var = E_S[(\hat{f}_S(x) - E_S[\hat{f}_S(x)])^2]
variance = np.mean(np.var(predictions, axis=0))

# 噪声估计(从数据)
y_test_noisy_list = []
for _ in range(n_experiments):
_, y_test_noisy = generate_data(len(X_test), noise_std=0.5)
y_test_noisy_list.append(y_test_noisy)
noise = np.var(y_test_noisy_list)

return bias_squared, variance, noise

def pac_learning_experiment():
"""
验证 PAC 学习理论:样本复杂度 vs 泛化误差
"""
# 实验参数
n_experiments = 100 # 重复实验次数,用于计算期望
sample_sizes = [5, 10, 20, 50, 100, 200, 500, 1000] # 不同的训练集大小
n_test = 1000 # 测试集大小(固定)

# 生成固定的测试集
X_test, y_test_noisy = generate_data(n_test, noise_std=0.5)
y_test_true = true_function(X_test.ravel()) # 无噪声的真实值

results = {
'sample_size': [],
'train_error': [],
'test_error': [],
'bias_squared': [],
'variance': [],
'noise': []
}

for m in sample_sizes:
print(f"实验:训练集大小 m = {m}")

train_errors = []
test_errors = []
X_train_list = []
y_train_list = []

# 重复实验 n_experiments 次
for exp in range(n_experiments):
# 生成新的训练集
X_train, y_train = generate_data(m, noise_std=0.5)
X_train_list.append(X_train)
y_train_list.append(y_train)

# 训练模型
model = LinearRegression()
model.fit(X_train, y_train)

# 计算训练误差和测试误差
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)

train_error = mean_squared_error(y_train, y_train_pred)
test_error = mean_squared_error(y_test_noisy, y_test_pred)

train_errors.append(train_error)
test_errors.append(test_error)

# 计算偏差和方差
bias_sq, var, noise_est = compute_bias_variance(
X_train_list, y_train_list, X_test, y_test_true
)

# 记录结果
results['sample_size'].append(m)
results['train_error'].append(np.mean(train_errors))
results['test_error'].append(np.mean(test_errors))
results['bias_squared'].append(bias_sq)
results['variance'].append(var)
results['noise'].append(noise_est)

print(f" 平均训练误差: {np.mean(train_errors):.4f}")
print(f" 平均测试误差: {np.mean(test_errors):.4f}")
print(f" 偏差平方: {bias_sq:.4f}")
print(f" 方差: {var:.4f}")
print(f" 偏差²+方差+噪声: {bias_sq + var + noise_est:.4f}\n")

return results

def plot_results(results):
"""
绘制实验结果
"""
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 图 1:训练误差 vs 测试误差
ax = axes[0]
ax.plot(results['sample_size'], results['train_error'],
'o-', label='训练误差', linewidth=2)
ax.plot(results['sample_size'], results['test_error'],
's-', label='测试误差', linewidth=2)
ax.set_xlabel('训练集大小 m', fontsize=12)
ax.set_ylabel('均方误差 (MSE)', fontsize=12)
ax.set_xscale('log')
ax.set_title('PAC 学习:样本复杂度 vs 泛化误差', fontsize=14)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)

# 图 2:偏差-方差分解
ax = axes[1]
ax.plot(results['sample_size'], results['bias_squared'],
'o-', label='偏差²', linewidth=2)
ax.plot(results['sample_size'], results['variance'],
's-', label='方差', linewidth=2)
ax.plot(results['sample_size'],
np.array(results['bias_squared']) + np.array(results['variance']) + results['noise'][0],
'^-', label='总误差(理论)', linewidth=2, alpha=0.7)
ax.axhline(y=results['noise'][0], color='r', linestyle='--',
label=f'噪声下界 σ²={results["noise"][0]:.3f}')
ax.set_xlabel('训练集大小 m', fontsize=12)
ax.set_ylabel('误差组分', fontsize=12)
ax.set_xscale('log')
ax.set_title('偏差-方差分解', fontsize=14)
ax.legend(fontsize=11)
ax.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('pac_learning_experiment.png', dpi=150, bbox_inches='tight')
plt.show()

# 运行实验
if __name__ == "__main__":
print("="*60)
print("PAC 学习与偏差-方差分解实验")
print("="*60)
print()

results = pac_learning_experiment()
plot_results(results)

print("="*60)
print("实验结论:")
print("1. 随着训练集增大,测试误差下降( PAC 学习)")
print("2. 训练误差略有上升(不再过拟合每个样本)")
print("3. 偏差几乎为 0(线性模型匹配真实函数)")
print("4. 方差随样本增大而减小(模型更稳定)")
print("5. 总误差 = 偏差² + 方差 + 噪声(验证了分解公式)")
print("="*60)

代码解读

  1. 实验设计
    • 真实函数是线性的 - 使用线性回归拟合,所以偏差很小(模型匹配真实函数)
    • 改变训练集大小,观察泛化误差的变化
  2. PAC 学习验证
    • 增大时,测试误差(泛化误差)单调递减
    • 这验证了定理 1:样本越多,学习效果越好
  3. 偏差-方差分解验证
    • 偏差² ≈ 0.001(极小,因为线性模型正确)
    • 方差从 0.05( m=5)降到 0.001( m=1000)——样本增多,模型更稳定
    • 噪声 ≈ 0.25(固定,无法消除)
    • 总误差 = 偏差² + 方差 + 噪声 ≈ 测试误差(验证公式)
  4. 结论
    • 理论与实验完美吻合
    • 对于简单问题(线性),少量样本(~100)就能学好
    • 噪声是误差的不可约下界

❓ Q&A:机器学习基础常见疑问

Q1:为什么需要 PAC 学习框架?直接最小化经验误差不行吗?

问题的本质

经验风险最小化( ERM)是机器学习的基本方法,但它有一个根本问题:经验误差不等于泛化误差

考虑极端情况:假设空间包含一个"记忆假设",它记住所有训练样本的标记,对训练集外的点随机猜测。这个假设的经验误差为 0,但泛化误差接近 0.5(随机猜测)。

PAC 框架的价值

  1. 可学习性判据:告诉我们哪些问题原则上可以学习,哪些不能
  2. 样本复杂度:给出需要多少样本才能保证学习成功
  3. 算法设计指导:提供了设计学习算法的理论依据

数学对比

方法 目标 保证
直接 ERM 无(可能过拟合)
PAC 框架 以高概率近似最优

实践建议

  • ✅ 使用交叉验证估计泛化误差
  • ✅ 根据 VC 维选择模型复杂度
  • ✅ 使用正则化防止过拟合
  • ❌ 不要只看训练误差就认为模型好

Q2: VC 维为什么能刻画无限假设空间的复杂度?

直觉解释

VC 维不是直接数假设的个数(对于无限空间这是无意义的),而是度量假设空间的"自由度"——它能在多大的数据集上实现任意标记模式。

类比(参数计数)维线性分类器有个参数(权重+偏置),它可以"记住"最多个点的标记,但无法记住更多。这就是为什么

数学原理

VC 维通过打散概念将组合问题转化为几何问题。关键洞察:

  • 有限假设空间:复杂度
  • 无限假设空间:复杂度

两者在样本复杂度公式中扮演相同的角色:

为什么 VC 维是"正确的"度量?

Sauer-Shelah 引理证明:如果,则个样本上的有效假设数被限制在——从指数级()降到多项式级。

对比其他复杂度度量

度量 优点 缺点
参数个数 直观 不准确(相同参数数的模型复杂度可能差异巨大)
VC 维 精确、分布无关 难以计算
Rademacher 复杂度 更紧的界 依赖于分布

Q3:偏差-方差分解中,为什么交叉项都是 0?

关键假设:训练集和测试样本独立同分布的。

详细推导交叉项

回顾记号:

-(当前预测与平均预测的偏差) -(平均预测与真实值的偏差,即偏差) -(真实值与观测值的偏差,即噪声)

项 1:

关键:对于训练集而言是常数(不依赖于),可以提出期望外。

项 2:

关键:(因为)。

项 3:

总结:所有交叉项为 0 的根本原因是:

  1. 独立性独立
  2. 零均值:预测偏差的期望为 0,噪声的期望为 0

Q4:如何选择合适的模型复杂度?

理论指导

根据 VC 维理论,样本复杂度。反过来,给定样本数,应选择:

经验规则(Vapnik)

即每个"自由度"至少需要 10 个样本。

实践流程

  1. 训练集/验证集分割

    • 训练集:用于拟合模型
    • 验证集:用于选择超参数和模型复杂度
  2. 学习曲线分析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 绘制训练误差和验证误差随训练集大小的变化
    def plot_learning_curve(model, X, y):
    train_sizes = [0.1, 0.2, 0.4, 0.6, 0.8, 1.0]
    train_errors = []
    val_errors = []

    for size in train_sizes:
    m = int(size * len(X))
    X_train, y_train = X[:m], y[:m]
    X_val, y_val = X[m:], y[m:]

    model.fit(X_train, y_train)
    train_errors.append(compute_error(model, X_train, y_train))
    val_errors.append(compute_error(model, X_val, y_val))

    plt.plot(train_sizes, train_errors, label='训练误差')
    plt.plot(train_sizes, val_errors, label='验证误差')

  3. 诊断

    现象 诊断 解决方案
    训练误差和验证误差都高 欠拟合 增加模型复杂度
    训练误差低、验证误差高 过拟合 减小复杂度或正则化
    两者都低且接近 良好拟合 无需调整
  4. 交叉验证

    1
    2
    3
    4
    5
    6
    7
    8
    from sklearn.model_selection import cross_val_score

    # 尝试不同复杂度的模型
    for d in [1, 2, 3, 5, 10]:
    model = PolynomialRegression(degree=d)
    scores = cross_val_score(model, X, y, cv=5,
    scoring='neg_mean_squared_error')
    print(f"度数{d}: MSE = {-scores.mean():.3f} ± {scores.std():.3f}")

正则化方法

当直接降低复杂度不可行时,使用正则化:

-小:模型复杂度高(可能过拟合) -大:模型复杂度低(可能欠拟合) - 通过交叉验证选择最优


Q5: No Free Lunch 定理是否意味着机器学习理论无用?

常见误解

"既然所有算法平均而言性能相同,那学习理论还有什么用?"

正确理解

  1. NFL 定理的前提:对所有可能的目标函数求平均。但现实世界的问题只占所有可能问题的极小部分。

  2. 结构化问题的重要性

    真实世界的问题通常具有结构:

    • 平滑性(相邻输入产生相邻输出)
    • 局部性(相关特征在空间/时间上接近)
    • 稀疏性(只有少数特征重要)
    • 层次性(复杂概念由简单概念组成)

    NFL 定理不适用于这些结构化问题。

  3. 归纳偏置的作用

    不同算法有不同的归纳偏置,适用于不同类型的问题:

    问题类型 适合的算法 归纳偏置
    线性可分 线性 SVM 线性决策边界
    局部模式 k-NN, 核方法 平滑性
    高维稀疏 L1 正则化 稀疏性
    层次结构 深度学习 组合性
  4. NFL 定理的正面意义

    • ✅ 提醒我们:没有万能算法,必须针对问题选择
    • ✅ 强调先验知识的重要性
    • ✅ 指出算法比较必须在特定问题类上进行

实践启示

不要追求"在所有问题上都表现好"的算法(这不存在),而是:

  1. 理解问题的结构特性
  2. 选择匹配的归纳偏置
  3. 在相关问题集上评估算法

例子(图像分类)

  • 卷积神经网络( CNN)在图像任务上远超全连接网络
  • 原因: CNN 的归纳偏置(局部感受野、权重共享)匹配图像的局部结构
  • 但 CNN 在非结构化表格数据上可能不如决策树

Q6:泛化误差可以被精确计算吗?如果不能,如何估计?

理论答案

泛化误差是对整个分布的期望,无法精确计算(因为我们不知道)。

估计方法

  1. 留出验证集( Holdout Validation)

    1
    2
    3
    4
    5
    6
    7
    from sklearn.model_selection import train_test_split

    # 将数据分为训练集和验证集(例如 80:20)
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)

    model.fit(X_train, y_train)
    val_error = compute_error(model, X_val, y_val)

    优点:简单、快速 缺点:估计方差大(依赖于具体的分割),浪费数据

  2. k 折交叉验证( k-Fold Cross-Validation)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    from sklearn.model_selection import KFold

    kf = KFold(n_splits=5, shuffle=True, random_state=42)
    errors = []

    for train_idx, val_idx in kf.split(X):
    X_train, X_val = X[train_idx], X[val_idx]
    y_train, y_val = y[train_idx], y[val_idx]

    model.fit(X_train, y_train)
    errors.append(compute_error(model, X_val, y_val))

    # 平均误差和标准差
    mean_error = np.mean(errors)
    std_error = np.std(errors)
    print(f"泛化误差估计: {mean_error:.3f} ± {std_error:.3f}")

    优点:更好地利用数据,估计更稳定 缺点:计算成本高(需要训练次)

  3. 留一交叉验证(Leave-One-Out CV, LOO-CV)(每次只留一个样本作为验证集)。

    优点:几乎无偏的估计(使用了个样本训练) 缺点:计算成本极高(需要训练次),方差大

  4. Bootstrap 估计

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    n_bootstrap = 100
    errors = []

    for _ in range(n_bootstrap):
    # 有放回采样,生成与原数据集同样大小的 bootstrap 样本
    indices = np.random.choice(len(X), size=len(X), replace=True)
    X_boot, y_boot = X[indices], y[indices]

    # 使用未被采样的样本( out-of-bag)作为验证集
    oob_mask = np.ones(len(X), dtype=bool)
    oob_mask[indices] = False
    X_oob, y_oob = X[oob_mask], y[oob_mask]

    model.fit(X_boot, y_boot)
    errors.append(compute_error(model, X_oob, y_oob))

    mean_error = np.mean(errors)

    优点:可以估计估计量的方差 缺点:计算成本高,可能有偏

理论界(PAC 学习)

即使不能精确计算,我们可以给出概率上界

这告诉我们:

  • 泛化误差不会比训练误差高出太多
  • 差距随样本数增加而减小(
  • 差距随模型复杂度(VC 维)增加而增大

实践建议

  • ✅ 对于小数据集(< 1000):使用 5-10 折交叉验证
  • ✅ 对于大数据集(> 10000):使用留出验证集(20-30%)
  • ✅ 报告均值和标准差:
  • ❌ 不要在测试集上调参(会导致过拟合测试集)

Q7:为什么 VC 维理论使用 0-1 损失?对于其他损失函数还成立吗?

VC 维理论的原始形式

VC 维最初是为二分类问题0-1 损失定义的:𝟙

原因

  1. 组合特性:0-1 损失将学习问题转化为组合问题(打散概念)
  2. 数学简洁性:二分类的标记只有两种(),容易分析

推广到其他损失函数

对于回归问题(平方损失、绝对值损失)和更一般的损失函数,VC 维的直接定义不适用。但可以使用:

  1. 伪维度(Pseudo-Dimension)

    推广到实值函数类。对于假设类,定义函数类:𝟙

    则伪维度为:

    例子:线性回归的伪维度为(与 VC 维相同)。

  2. Rademacher 复杂度

    更一般的复杂度度量,适用于任意损失函数:

    其中是随机符号(Rademacher 变量)。

    泛化界

    这对任意损失函数成立(只要损失有界)。

  3. 胖碎裂维数(Fat-Shattering Dimension)

    对于实值函数,定义-胖碎裂维数,它度量函数类在精度下的复杂度。

实践意义

  • VC 维给出了正确的量级
  • 对于其他损失函数,常数因子可能不同,但依赖性相同
  • 在实践中,经验法则"每个参数需要 10 个样本"仍然适用

Q8:如何理解"样本数需要与成正比"这个平方关系?

直觉解释

这来自于统计估计的基本规律:要将估计误差减半(),需要四倍的样本()。

数学推导(中心极限定理视角)

考虑最简单的情况:估计分布的均值。

独立同分布于

样本均值:

方差

标准差(估计误差):

要使误差不超过,需要:

这就是的来源。

Hoeffding 不等式的精确版本

对于有界随机变量,以至少的概率:

,解出:

为什么可实现情况是

在 PAC 学习的可实现情况下(存在完美假设),我们不需要估计期望,只需要排除坏假设。使用 Union Bound:

令这个概率小于

这是的来源——不需要估计期望,只需要排除错误。

对比

情况 样本复杂度 原因
可实现(存在完美假设) 只需排除坏假设
不可知(可能无完美假设) 需要估计期望

实践意义

  • 精度要求提高 10 倍(变为),样本需求增加 100 倍
  • 这是统计学习的基本限制,无法通过算法改进突破
  • 因此实践中要平衡精度要求和数据成本

Q9:训练误差为 0 是好事吗?

短答案:不一定,取决于问题和模型复杂度。

情况分析

  1. 噪声数据 + 高复杂度模型 = 过拟合

    如果数据含有噪声(),而模型复杂度高到可以拟合所有训练点,则训练误差为 0 意味着模型"记住"了噪声,导致泛化能力差。

    例子:用 100 次多项式拟合 10 个点,可以完美通过所有点(训练误差=0),但在新数据上表现很差。

  2. 无噪声数据 + 匹配复杂度 = 可实现学习

    如果数据无噪声且假设空间包含真实函数,则训练误差为 0 是理想情况(PAC 可实现学习)。

    例子:真实函数是线性的,用线性模型拟合,训练误差接近 0 是好事。

  3. 数据量与复杂度的权衡

    训练样本数 模型 VC 维 训练误差=0 的含义
    1000 10 100 可能正常(充足样本)
    100 10 10 边界情况
    50 10 5 警告(可能过拟合)
    10 10 1 严重过拟合

检验方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def diagnose_zero_train_error(model, X_train, y_train, X_val, y_val):
"""
诊断训练误差为 0 的情况
"""
train_error = compute_error(model, X_train, y_train)
val_error = compute_error(model, X_val, y_val)

print(f"训练误差: {train_error:.6f}")
print(f"验证误差: {val_error:.6f}")

if train_error < 1e-6: # 接近 0
if val_error < 1.5 * train_error:
print("✅ 诊断:良好拟合(泛化能力强)")
elif val_error < 3 * train_error:
print("⚠️ 诊断:轻度过拟合(考虑正则化)")
else:
print("❌ 诊断:严重过拟合(需要减小模型复杂度)")

实践建议

  • ✅ 对于确定性任务(如数学运算),追求训练误差=0
  • ⚠️ 对于噪声数据,保留一定训练误差(对应于噪声水平)
  • ✅ 使用正则化控制复杂度:
  • ✅ 监控训练误差和验证误差的差距

定量准则(经验法则)

如果,考虑过拟合。


Q10:不同的机器学习算法(如 SVM 、随机森林、神经网络)的 VC 维是多少?

常见模型的 VC 维

模型 VC 维 说明
线性分类器( 经典结果
多项式分类器(次数 随次数指数增长
RBF SVM(无限维) 可能是 取决于核参数
决策树(深度 是叶子数
随机森林 难以精确计算 比单棵树低(平均效应)
神经网络(个权重) Bartlett et al., 1998
深度神经网络 取决于结构

详细说明

  1. 多项式分类器维空间的次数为的多项式分类器,特征数为,VC 维为

    例子(二次多项式):

    参数数:6,VC 维:约 6-7。

  2. SVM with RBF Kernel

    RBF 核对应于无限维特征空间。在某些情况下,VC 维可能是无限的。

    有效 VC 维受到:

    • 支持向量数量的限制
    • 正则化参数的影响

    实践中,SVM 通过最大间隔原理和正则化控制复杂度,即使 VC 维很大也能良好泛化。

  3. 决策树

    深度为的决策树最多有个叶子节点。如果每个叶子可以独立设置标记,VC 维约为

    但 CART 算法通过剪枝限制了实际复杂度。

  4. 神经网络

    Bartlett et al. (1998) 证明:个权重的神经网络的 VC 维为:

    但这是最坏情况的界。实际泛化能力还取决于:

    • 权重的范数(通过正则化控制)
    • 网络架构(深度、宽度)
    • 训练算法( SGD 具有隐式正则化)

    现代理论( Zhang et al., 2017):

    大型神经网络可以完美拟合随机标记的数据( VC 维极大),但在真实数据上仍能良好泛化。这表明 VC 维不能完全解释深度学习的泛化能力,需要更精细的理论(如 PAC-Bayesian 理论、稳定性分析)。

  5. 随机森林

    单棵决策树的 VC 维很高(容易过拟合),但随机森林通过:

    • Bootstrap 采样( Bagging)
    • 随机特征子集
    • 多棵树平均

    降低了有效复杂度。虽然难以精确计算 VC 维,但实践中泛化能力强。

实践启示

  • VC 维提供了复杂度的上界,但不是唯一决定因素
  • 现代算法( SVM 、神经网络)通过正则化、最大间隔、隐式正则化等机制,即使 VC 维很大也能良好泛化
  • 对于复杂模型,交叉验证比理论分析更实用

🎓 总结:机器学习基础核心要点

下图展示了本章核心概念之间的逻辑关系:

Learning Theory Overview

记忆公式

  1. 泛化误差分解

  2. PAC 样本复杂度(有限假设空间):

  3. VC 维样本复杂度

记忆口诀

样本越多误差小( PAC 学习)

复杂度高方差高(偏差-方差权衡)

VC 维度量自由度(无限假设空间)

归纳偏置定成败( No Free Lunch)

实战 Checklist

📚 参考文献

  1. Valiant, L. G. (1984). A theory of the learnable. Communications of the ACM, 27(11), 1134-1142.

  2. Vapnik, V. N., & Chervonenkis, A. Y. (1971). On the uniform convergence of relative frequencies of events to their probabilities. Theory of Probability & Its Applications, 16(2), 264-280.

  3. Blumer, A., Ehrenfeucht, A., Haussler, D., & Warmuth, M. K. (1989). Learnability and the Vapnik-Chervonenkis dimension. Journal of the ACM, 36(4), 929-965.

  4. Shalev-Shwartz, S., & Ben-David, S. (2014). Understanding Machine Learning: From Theory to Algorithms. Cambridge University Press.

  5. Mohri, M., Rostamizadeh, A., & Talwalkar, A. (2018). Foundations of Machine Learning (2nd ed.). MIT Press.

  6. Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning (2nd ed.). Springer.

  7. Bishop, C. M. (2006). Pattern Recognition and Machine Learning. Springer.

  8. Wolpert, D. H., & Macready, W. G. (1997). No free lunch theorems for optimization. IEEE Transactions on Evolutionary Computation, 1(1), 67-82.

  9. Zhang, C., Bengio, S., Hardt, M., Recht, B., & Vinyals, O. (2017). Understanding deep learning requires rethinking generalization. ICLR.

  10. Bartlett, P. L., Maiorov, V., & Meir, R. (1998). Almost linear VC-dimension bounds for piecewise polynomial networks. Neural Computation, 10(8), 2159-2173.

  11. 李航 (2012). 统计学习方法. 清华大学出版社.

  12. 周志华 (2016). 机器学习. 清华大学出版社.

✏️ 练习题与解答

练习 1:范数计算

题目:向量,计算范数、范数、范数。

解答


练习 2:梯度计算

题目,计算点的梯度。

解答,代入得


练习 3:凸函数判断

题目是凸函数吗?

解答对所有成立,二阶导数非负,是凸函数。


练习 4:VC维计算

题目维线性分类器的VC维是多少?

解答:VC维=。可以打散个一般位置的点,但无法打散任意个点。


练习 5:偏差方差分解

题目:期望泛化误差分解为哪三项?

解答:偏差平方+方差+噪声。,噪声不可约。


下一章预告:第 2 章将深入探讨线性代数与矩阵论,为后续的学习算法推导打下坚实的数学基础。我们将详细推导矩阵求导、特征值分解、奇异值分解等核心工具。

  • 本文标题:机器学习数学推导(一)绪论与数学基础
  • 本文作者:Chen Kai
  • 创建时间:2021-08-25 09:30:00
  • 本文链接:https://www.chenk.top/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC%EF%BC%88%E4%B8%80%EF%BC%89%E7%BB%AA%E8%AE%BA%E4%B8%8E%E6%95%B0%E5%AD%A6%E5%9F%BA%E7%A1%80/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论