翻到Week 7的笔记,这大概是整门《机器学习技法》公开课里最让人耳目一新的一章。前面六周我们一直在跟“单一模型”较劲:线性模型、支持向量机、核方法、决策树,每一个都研究得很深,但谁都避免不了一个尴尬——换个数据分布,模型表现就可能波动很大。Week 7的“Blending and Bagging”直接换了一个思路:不再纠结于选哪个模型,而是把多个模型组合起来,让群体的判断代替单个模型的判断。这篇笔记会把这周的核心概念、课程里最关键的数学推导、以及我在课下做的验证实验完整记录下来,适合正学到这一周的同学,也适合想系统理解集成学习入门逻辑的读者。
1. 从单一模型走向群体决策:课程为什么在这个节点讲聚合
1.1 前半程课程留下的“稳定性”难题
课堂进入第七周之前,我们已经看了很多威力强大的算法:SVM可以把非线性边界分离得干干净净,决策树能通过不断分裂拟合复杂模式。但这些模型的“强”往往是建立在特定参数设置和特定训练样本之上。换一组样本,决策边界就可能抖动得厉害;参数差一点,模型的泛化误差可能大幅上升。
这是单一模型在有限数据下很难绕开的“方差困境”。课程正是从这里切入:如果我们手里不只有一个候选模型,而是有一组模型,能不能用某种方式把它们的判断整合起来,得到一个比其中任何一个都更稳健的最终模型?
我的理解是,这周的定位非常巧妙。前面几周教的是“单点突破”,把线性模型、SVM、决策树每个都打磨到足够强;这周开始教“协同作战”,不再假设一个模型能搞定所有问题,而是假设很多普通模型凑在一起,能够互相纠正彼此的偏差。这种思路上的转折,正是“技法”两个字想表达的深层含义。
1.2 聚合的两个关键问题:多样性与组合规则
把多个模型组合起来,听起来简单,实际上要回答两个问题。第一,怎么得到一组有差异的模型?如果训练了十个完全一样的模型,再怎么组合也还是同一个模型。第二,组合规则怎么定?是简单投票,还是学习一个权重?Week 7的核心就是把这两个问题拆开讲:Blending系列方法解决“组合规则”的问题,Bagging解决“制造多样性”的问题。
课程里强调,聚合要想超过单一模型,需要同时满足“多样性”和“准确性”。一堆胡言乱语的模型投票,不会得到正确结论;只有每个模型都有一定正确率、同时彼此犯错模式还不一样,群体决策才可能变强。
这就像开会讨论。如果所有人都是同一个思路,多开几场会也讨论不出新东西;如果大家角度各异但都基于事实,讨论结果往往比一个人拍脑袋可靠。但在实际训练中,“角度各异”不是天然存在的,需要专门设计数据采样或模型扰动来制造。课程后面所有集成方法,本质上都在做这两件事:制造差异、聚合判断。
1.3 多数表决的思想实验:弱而不同的模型才有价值
我自己觉得,这周最精彩的地方是一个概率思想实验:假设我们有若干正确率略高于随机猜测的小模型,每个模型的正确率是 (p=0.6),错误率是 (0.4),如果只用其中一个模型,正确率就是0.6。但如果用11个这样的模型做多数表决,并且假设它们犯错彼此独立,表决正确的概率会变成:
[ \sum_{k=6}^{11} \binom{11}{k} (0.6)^k (0.4)^{11-k} ]
算下来大约是0.75,比单个模型的0.6高出一截。如果把模型数量增加到21个,这个概率还会继续上升。这个思想实验直观地说明:模型可以弱,但只要不是瞎猜,并且彼此独立地犯错,多数表决就能把正确率“拔”上去。
反过来,如果这11个模型完全一样,或者它们总是在同样的样本上犯错,那表决结果不会有任何改善。这正是课程反复强调的“弱但不同”的模型组合才有价值。理解这一点,后面看Bagging的设计思路就会很顺畅——Bagging的核心目标不是把模型变得更准,而是让一组模型变得更不同。
2. 三种Blending方式:由浅入深的“组合模型”操作路径
2.1 Uniform Blending:投票、平均和那个平方误差不等式
最简单的一种组合方式,就是给每个 (g_t) 相同的地位。分类问题中做多数表决,回归问题中做算术平均。课程给出了一个很有用的推导:对于回归,如果用平方误差来衡量,令 (G(x)) 为一组 (g_t(x)) 的平均值,那么对任意一个样本 (x),有:
[ (G(x) - y)^2 \leq \frac{1}{T} \sum_{t=1}^{T} (g_t(x) - y)^2 ]
也就是说,平均模型在每个点的误差,不会比所有基模型在该点误差的平均值更大。这个结论可以从代数上直接写出来。看下面的展开式:
e_t = (g_t - y)^2 = (g_t - G + G - y)^2 = (g_t - G)^2 + (G - y)^2 + 2(g_t - G)(G - y)对所有 (t) 取平均,第三项的求和部分是 (2(G - y) \cdot \frac{1}{T}\sum_t (g_t - G))。因为 (G) 本身就是 (g_t) 的平均值,所以 (\sum_t(g_t - G)=0),这一整项就消失了。剩下来的两项中,((g_t - G)^2 \ge 0),于是自然得到上面的不等式。
理解这个不等式的含义很重要:Uniform Blending并不保证新模型一定好于“最好的那个基模型”,它保证的是新模型不会比所有基模型“平均水平”更差。换句话说,如果你手里有几个说得过去的模型,把它们平均一下,至少不会吃大亏。这是一种非常稳健的兜底策略。
2.2 Linear Blending:让数据帮我们决定权重
均匀投票虽然稳,但把“老专家”和“新手”平等对待,显然不太合理。Linear Blending的做法是:把每个模型 (g_t) 的输出当作新的特征,然后在验证集上学习一组权重 (\alpha_t),使得组合后的打分 (\sum_t \alpha_t g_t(x)) 在验证集上误差最小。
课程特别提醒,学习权重时用的是验证集而不是训练集。这个细节非常关键:基模型本来就在训练集上表现好,再基于训练集学权重,会放大过拟合模型的贡献。只有在验证集上,才能公平地看到每个模型对新数据的预测能力,权重才可信。
这一层可以类比成“评委打分”:每个基模型是选手,线性权重是评委对选手的信任度。如果评委只看选手训练时的成绩,很容易被“刷题家”骗了;只有看新题成绩,才能选出真正靠谱的选手。Linear Blending还把负权重也纳入考虑范围,这相当于允许评委说“这个选手的答案有系统偏差,要从总分里扣掉一部分”,是一种比硬投票灵活得多的机制。
2.3 Stacking:把组合层变成可学习的模型
如果把Linear Blending中的线性回归换成更复杂的模型,就得到Stacking。课程中把这种结构描述为“将基模型的输出作为新的特征,再用一个学习算法来融合它们”。从操作上看,它是在验证集上构造一个新数据集,新数据集的每一列来自一个基模型的预测值,然后在这个数据集上训练一个上层模型。
Stacking的好处是融合层可以捕捉到基模型输出之间的非线性关系。比如,基模型A在样本A类区域更准,基模型B在样本B类区域更准,上层模型可以学到“在不同区域分别信任不同模型”的复杂规则,而不只是给它们一个固定权重。
坏处也明显:融合层的自由度变大,更容易过拟合。业界在竞赛里经常用两层结构,但实际工程里要格外小心。所有基模型必须在训练集和验证集上分别产出输出,融合层只在验证集的输出上训练,最后再用完整训练数据重新训练基模型,或者直接使用交叉验证来稳定融合结果。课程虽然点到为止,但这个思想几乎贯穿后续所有集成学习实践。
3. Bagging:用数据的“重复采样”制造差异性
3.1 为什么必须用有放回抽样
Blending假设我们已经有一组训练好的模型,但现实中我们往往只有一个数据集。怎么造出一组足够不同的模型?这周的Bagging给了一个经典思路:对原始数据集做有放回抽样,得到T份大小相同但内容略有差异的新数据集,再分别训练T个模型。
之所以必须“有放回”,是为了让每次抽样都更像一次独立的“重新采样”。如果无放回地把样本分成T份,每份样本量只有原来的1/T,且样本之间不重叠,模型的数据基础会弱很多;而有放回抽样允许同一批样本重复出现,每次产生的数据集都带着近似原始分布但又有细微变化的信息。
这相当于模拟了“从真实分布里重新采一份新数据”的过程。我们虽然没有能力真的拿到多份独立样本,但通过有放回抽样,可以在原始数据范围内制造出很多份“看起来像是重新采样”的数据集。每份数据集训练出的模型,就会在决策边界上产生差异。差异正是Bagging的燃料。
3.2 Bagging的完整流程与袋外样本
Bagging的算法流程可以写成下面这样的伪代码:
输入:训练集 D,基学习算法 A,模型数量 T for t = 1 to T: 从 D 中有放回地抽取 n 个样本,得到 D_t 用算法 A 在 D_t 上训练得到模型 g_t 输出:G(x) = 多数表决(分类)或算术平均(回归)这里的核心参数是 (T)。课程没给一个“最优轮数”,因为它取决于具体问题和基模型。通常几十轮到几百轮都能看到明显效果,再增加轮数收益会逐渐饱和。
有一个小细节值得专门提一下:在每一轮有放回抽样中,一个样本在 (n) 次抽样里都没被抽到的概率约为 ((1 - 1/n)^n \approx e^{-1} \approx 0.368)。也就是说,每次训练大约有36.8%的样本没有参与该轮训练,这些样本被称为“袋外样本”。
袋外样本是个免费的好东西。它们没有被某个基模型见过,天然适合用来估计这个模型的泛化误差,不需要额外划分验证集。课程没有展开细讲,但这是我后来做实验时觉得特别实用的部分,尤其在数据量不大时能省下很多样本。
3.3 从方差角度看Bagging为什么有效
假设T个 (g_t) 相互独立,且每个 (g_t) 的方差都是 (\sigma^2),那么对 (G) 求平均后,方差变成 (\sigma^2 / T)。模型数量的增加,会让组合结果的波动迅速下降。当然,实际训练出的 (g_t) 来自同一个原始数据集,彼此之间高度相关,方差削减效果没有这么理想,但方向上确实把“单模型方差太大”的问题缓解了。
这里要特别提一个课程里的重要结论:Bagging适合搭配那些“对数据敏感、容易过拟合”的基模型,比如决策树。如果基模型本身是线性回归这类低方差模型,Bagging带来的收益很有限,平均几个长得差不多的线性模型,结果还是线性模型。
这也是为什么后续课程讲随机森林时,会在“决策树 + Bagging”的基础上再加一个“特征随机选择”。特征随机选择的目的,就是进一步增大树与树之间的差异性,让树们不那么“相似”,从而把相关性的影响压下去。理解了这一层,再看随机森林的设计就不是记结构,而是顺着需求推出来了。
4. 与前后课程的知识衔接:这周的真正位置
4.1 从SVM到Bagging:两条稳定的路线
前几周的SVM通过间隔最大化来提升稳定性,软间隔又允许少量误分点,本质上是在“一个模型内部”加上正则约束。而Bagging走的是另一条路:不修改基模型内部结构,通过重复训练和组合来降低不确定性。两种思路并不冲突,甚至经常会在同一个系统里同时出现。
| 路线 | 核心手段 | 适用范围 | 典型代表 |
|---|---|---|---|
| 单模型 + 正则 | 限制模型复杂度,提高泛化性 | 数据量适中、模型容易过拟合时 | 软间隔SVM、带L2惩罚的逻辑回归 |
| 多模型 + 组合 | 制造差异,降低预测方差 | 基模型本身不稳定、数据扰动大时 | Bagging、随机森林 |
这张对比表是我自己整理笔记时画的。考试和面试里经常会把这两种思路放在一起问,本质上就是考察你是否理解“正则化是在模型内部做文章,集成是在模型外部做文章”。
4.2 Kernel Ridge Regression 与 Linear Blending 的共通思想
课程早期讲Kernel Ridge Regression时,我们已经知道“高维空间里的线性模型往往比原始空间里的线性模型强得多”。Linear Blending做的事情其实异曲同工:把多个低维模型的输出映射成一个新的特征向量,然后在这个新特征空间里做线性加权。
区别在于,Kernel方法是把原始特征映射到隐式高维空间,Linear Blending则是把“模型预测结果”映射成度量特征。但二者都遵循同一个原则:先变换,再线性学习。
这种相似性带来的好处是,以前学的正则化、交叉验证经验可以直接迁移到集成模型上。组合层权重过大时,可以加L2惩罚;基模型数量太多时,可以用交叉验证选择哪些模型最终参与组合。课程还提到,在组合时加入常数项做截距,等价于允许一个固定的偏置模型,这在实践里有时会带来稳定提升。
4.3 为什么下一周马上要讲AdaBoost
Bagging通过并行地重采样制造多样性,但每个模型之间没有信息交流,遇到特别难分的样本,依然可能集体犯错。下一周引入的AdaBoost换了一种策略:串行地调整样本权重,让后一个模型更关注前一个模型犯错的样本。
这样,模型之间就有了明确的协作关系,而不是单纯的并行。Week 7把blending和bagging讲透,其实是为后面的“串行式”集成做一个脚手架。如果这周“权重学习”和“重采样制造多样性”两个概念没有吃透,下周看AdaBoost会非常吃力。
我自己在复习时会把这周当成一个分水岭:前面全是“单模型时代”,从这周开始进入“集成学习时代”。后面出现的随机森林、AdaBoost、Gradient Boosting,全都是从这周的两个基本问题出发,在“怎么制造差异”和“怎么组合模型”上做文章的变体。
5. 一个可以马上上手的验证实验:Bagging稳定性测试
5.1 实验设置与基模型选择
学完理论我忍不住做了个小实验。实验设定是两个类别的二维模拟数据,样本量600个,带0.35的高噪声,保证单模型很容易过拟合。基模型选择不剪枝的决策树,因为它方差大、对样本扰动敏感,最适合展示Bagging的效果。
实验中直接比较三种配置:单棵决策树、Bagging 10棵树、Bagging 50棵树,都用测试集错误率来评估。为了公平,所有配置使用同一个随机种子划分训练集和测试集。
5.2 核心代码实现
实现本身不复杂,用一个常见的机器学习库就够了。下面是参考代码:
import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import BaggingClassifier from sklearn.model_selection import train_test_split from sklearn.datasets import make_moons X, y = make_moons(n_samples=600, noise=0.35, random_state=7) X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42 ) base = DecisionTreeClassifier(random_state=0) base.fit(X_train, y_train) print("single tree error:", round(1 - base.score(X_test, y_test), 4)) for n in [10, 50]: bag = BaggingClassifier( base_estimator=base, n_estimators=n, random_state=0 ) bag.fit(X_train, y_train) error = 1 - bag.score(X_test, y_test) print(f"bagging ({n}) error:", round(error, 4))代码里最关键的一点是,base_estimator传进去的是同一个决策树配置,但BaggingClassifier会把它自动克隆成多份,每份用不同的自助采样数据集去训练。默认情况下这就是有放回抽样。
5.3 结果解读与扩展观察
在我的模拟运行中,单棵决策树错误率在0.25附近波动,Bagging 10棵树降到0.20左右,Bagging 50棵树进一步降到0.18附近。这个例子直观地展示了方差下降:单棵决策树会因为某些噪声样本画出完全不同的边界,而Bagging通过平均多个边界,把边界“磨平”了。
我也试过用线性模型作为基模型做同样的Bagging,结果错误率几乎不变,正好印证了课程里“低方差模型对Bagging不敏感”的结论。另外还有一个观察:随着基模型数量增加,Bagging的错误率会先快速下降,然后进入平台期,这时候再加更多树意义不大。实际工程里,我会先用几十棵树看看趋势,再决定要不要加到几百棵。
这个实验还提醒了我一个细节:基模型的多样性不只由抽样次数决定,还受数据噪声水平和模型复杂度的共同影响。如果数据本身太干净、模型过于稳定,重复抽样带来的多样性就很小,Bagging的效果自然也有限。
6. 学习时最容易踩的坑与几点答疑
6.1 Blending和Bagging到底怎么区分
这是Week 7最容易被问住的问题。简单记:Blending关心“怎么组合已经训练好的模型”,Bagging关心“怎么从一份数据中生成多个有差异的模型”。二者可以配合使用:先用Bagging生成一组模型,再用Blending(比如Linear Blending)决定它们的权重。
把它们混为一谈,后面看随机森林的源码就会觉得别扭。随机森林是Bagging的典型应用,但它内部使用的组合规则通常是简单的投票或平均,并没有单独的“融合层学习”。所以随机森林本质上是Bagging,而不是Blending。
6.2 均匀平均的误差不等式说明了什么
很多人把那个平方误差不等式理解成“平均后一定比最好的模型好”,这是不对的。不等式证明的只是“平均模型不比各基模型的平均差”。在具体数据集上,最好的单一模型仍然可能赢过平均模型。
这个细节在多个讨论里都是个坑。比如有人说“Bagging保证能提升模型”,这句话就不够严谨。Bagging真正稳定改善的是稳定性,是降低预测对训练样本波动的敏感度,而不是保证每一次都超过最优单模型。课程后面用大量实验说明,聚合的实际价值通常在小波动、多模型场景下最明显。
6.3 负权重与组合层的正则化
Linear Blending学出来的权重可能是负的。有些人觉得投票权重不该为负,但线性组合里负权重是有意义的:它相当于在组合中减去某个模型的“错误直觉”,可以作为对其他模型偏差的修正。
当然,权重没有约束时也可能变得很大或很小。课程建议在组合层使用正则化,比如对权重加L2惩罚,这在样本量不足时尤其重要。否则组合层很容易为了在验证集上压误差而记住噪声。
6.4 袋外样本的隐藏用途
Bagging的“余数”其实很有用。一个样本在T轮训练中平均有约36.8%的轮次没有参与训练,这些未使用的数据天然可以作为验证集来估计每个 (g_t) 的表现。
工程上,随机森林等算法甚至可以直接根据袋外误差调整参数,省去单独划分验证集的麻烦。比如在调参时,先看袋外错误率随树数量的变化曲线,就能大致判断多少棵树足够。这是我后来做项目时最常用到的一个隐藏技巧。
6.5 一点个人学习的体会
如果时间有限,优先把Week 7的两个核心图搞懂:一个是“模型输出做特征”的流程图,对应Blending;一个是“有放回抽样训练多个模型”的示意图,对应Bagging。我在学习时最大的体会是,这周的内容少而精,不需要背结论,最好亲自跑一遍Bagging实验,观察单模型稳定性和组合模型稳定性之间的差异。
把实验做一遍以后,再看后面的Boosting、随机森林、Stacking等扩展内容,会轻松非常多。尤其是当我亲手看到一棵不剪枝决策树的边界在土里土气的数据上飘来飘去,而50棵树的平均边界稳稳地把分界控制在合理位置时,才真正理解“群体决策”这四个字的分量。