一、交叉验证法不需要先分出训练集和验证集
一般算法中,训练集和验证集是分开的,5 折交叉验证不同:对基模型而言,训练集和验证集不分开(合并集),然后,按5折,取第一折,作为验证集(其余折作为训练集),对基模型训练出模型1,取第二折作为验证集模型2,如此这般,由基模型得到模型1、模型2、...、模型5
| 维度 | 普通 train/valid 划分 | 5折交叉验证(5-Fold CV) |
|---|---|---|
| 数据使用 | 固定切分:比如 80% 训练,20% 验证,验证集永远不参与训练 | 全集复用:把全部训练数据分成 5 份,轮流让其中 1 份做验证,其余 4 份做训练;每份数据既当过训练集,也当过验证集 |
| 模型数量 | 只训练 1 个模型(用训练集训练,在验证集上评估/调参) | 训练 5 个模型(每折对应 1 个,比如你说的模型1~模型5) |
| 验证集作用 | 用于早停、调参、评估性能,不参与最终模型训练 | 用于生成折外预测(Out-of-Fold Prediction),为 Stacking 等集成提供「无泄露」的中间特征,同时也能评估模型稳定性 |
| 数据泄露风险 | 若多次用验证集反馈调参,有轻微泄露风险 | 折外预测天然避免泄露:验证集样本从未被当前折的模型见过 |
| 结果利用 | 最终只用在训练集上训练的 1 个模型;验证集指标只是参考 | 5个模型的预测可以拼接成完整训练集的 OOF 预测 (用于 Stacking),或对测试集预测时做平均/加权融合,提升鲁棒性 |
- 输入 :完整训练集 DDD(不再额外切分 train/valid)
- 切分 :将 DDD 均匀分成 5 份:D1,D2,D3,D4,D5D_1, D_2, D_3, D_4, D_5D1,D2,D3,D4,D5
- 循环训练 (对某个基模型,比如 XGBoost):
- 第1折:用 D2+D3+D4+D5D_2+D_3+D_4+D_5D2+D3+D4+D5 训练 → 得到 模型1 ,在 D1D_1D1 上预测 → 保存 D1D_1D1 的预测结果
- 第2折:用 D1+D3+D4+D5D_1+D_3+D_4+D_5D1+D3+D4+D5 训练 → 得到 模型2 ,在 D2D_2D2 上预测 → 保存 D2D_2D2 的预测结果
- 第3折:用 D1+D2+D4+D5D_1+D_2+D_4+D_5D1+D2+D4+D5 训练 → 得到 模型3 ,在 D3D_3D3 上预测 → 保存 D3D_3D3 的预测结果
- 第4折:用 D1+D2+D3+D5D_1+D_2+D_3+D_5D1+D2+D3+D5 训练 → 得到 模型4 ,在 D4D_4D4 上预测 → 保存 D4D_4D4 的预测结果
- 第5折:用 D1+D2+D3+D4D_1+D_2+D_3+D_4D1+D2+D3+D4 训练 → 得到 模型5 ,在 D5D_5D5 上预测 → 保存 D5D_5D5 的预测结果
- OOF 拼接 :把 D1D_1D1~D5D_5D5 的预测结果按顺序拼回去 → 得到完整训练集的折外预测(每个样本都被「没见过它的模型」预测过)
- 测试集预测:用模型1~模型5 分别预测测试集 → 对 5 个结果取平均/加权 → 得到该基模型在测试集上的最终预测
二、「折外预测(Out-of-Fold Prediction)」
这个名字非常直观,我们可以拆成两部分理解:
1. Fold(折)
- 指交叉验证里划分出来的每一份数据子集 (比如5折CV里的 D1,D2,D3,D4,D5D_1, D_2, D_3, D_4, D_5D1,D2,D3,D4,D5)。
- 每一轮训练时,我们会留出1份作为验证集,用剩下的4份去训练模型。
2. Out-of(在...之外)
- 对当前这一轮训练的模型来说,验证集是「在训练集之外」的样本:模型在训练时完全没见过这些验证样本。
- 所以,模型对验证集的预测,就是「在当前训练折之外的样本上做的预测 」,因此叫 Out-of-Fold Prediction。
三、集成学习中的Stacking(堆叠集成)
在Stacking中,我们会先训练N个不同的基模型(比如XGBoost、随机森林、MLP等),而训练这些基模型时,我们不会用普通的"训练集+验证集"固定划分,而是用上述的5折交叉验证(也可以是10折,核心逻辑一致)。
**通过 K 折交叉验证生成折外预测,将多个基模型的预测结果拼接为「影子特征」,再结合原始标签构造「影子数据集」,用于训练元模型 ------ 这就是 Stacking 集成的核心数据构造范式。**Stacking 集成的步骤总结如下:
第一步:单个基模型,生成"无泄露"的折外预测
对于任意一个基模型,我们用5折交叉验证的方式训练5个不同的子模型(每折对应一个子模型)。每一个子模型,都是用"当前折之外"的4折数据作为训练集训练而成,训练完成后,会对当前折(即该子模型的验证折)的样本进行预测------这就是我们之前聊过的折外预测(Out-of-Fold Prediction,简称OOF预测)。简单说,子模型的训练集是"当前验证折之外"的样本,预测对象则是"当前验证折"的样本,折外预测并非"当前折之外"(从字面上对"折外预测"易错误理解)。
关键在于:每个样本的折外预测,都来自一个"从未见过它"的子模型。比如样本A在第1折被当作验证折,那么训练该子模型时,会用其余4折(第2-5折)数据作为训练集(即"训练折"),样本A不在训练集中,子模型训练时从未见过它,训练完成后再对第1折(验证折)的样本A进行预测,完全避免了数据泄露,保证了预测的客观性。
这样一来,一个基模型就能为原训练集中的每一个样本,生成一个唯一的折外预测值。
第二步:N个基模型,拼接出"影子样本"
假设我们训练了N个基模型(比如3个:XGBoost、随机森林、MLP),那么:对于原训练集中的同一个样本,每个基模型都会给它一个折外预测值。我们把这N个预测值像串珠子一样拼接起来,就得到了一个N维的向量------这就是这个样本的"影子样本"。
举个例子:样本B的原特征是"年龄、收入、消费习惯、..."(不管它是多少维),我们用3个基模型对它做折外预测,得到3个预测值(通常用概率预测而不是"0/1"预测),将这3个值拼接成的向量[0.82, 0.79, 0.85],不妨称为样本B的"影子样本"。
这里要注意:影子样本不是对原样本的替代,而是原样本的"高阶抽象"------它不再是原始的特征数据,而是多个基模型对这个样本的"判断结果",相当于把多个专家的意见,浓缩成了一个新的特征向量。
第三步:拼接标签,得到"影子样例"
影子样本只有"输入",没有"输出",还不能用来训练模型。我们需要给每个影子样本,配上它对应的"标准答案"------也就是原样本的真实标签。
把"影子样本"和"原样本标签"拼接在一起,就构成了一个完整的"影子样例"。比如样本B的影子样本是[0.82, 0.79, 0.85],原标签是1,那么这个影子样例就是([0.82, 0.79, 0.85], 1)。
第四步:遍历所有样本,生成"完整影子集"
我们把原训练集中的每一个样本,都按照上面的步骤操作:生成影子样本,拼接原标签,得到影子样例。当我们遍历完所有样本后,就得到了一个和原训练集大小完全一致的新数据集------"完整影子集"。
这个原训练集对应的影子集,有两个核心特点:
-
无数据泄露:所有影子样本的预测值,都来自"未见过该样本的基模型";
-
信息密度高:影子集的特征是多个基模型的"知识结晶",比原始特征更能反映样本的核心规律,也更适合用于高阶融合。
第五步:用原训练集的"完整影子集"训练元模型
到这里,Stacking的第一层(基模型层)工作就完成了,而"完整影子集",就是我们给第二层模型(元模型,比如逻辑回归、线性回归)准备的专属训练数据。
元模型的任务很简单:学习如何融合这N个基模型的预测结果(也就是影子样本的N维特征),最终输出比任何一个单个基模型都更精准的预测。
总结Stacking的精髓:让基模型"负责学习原始数据",让元模型"负责学习如何融合基模型的知识",层层递进,实现"1+1>2"的集成效果。
- 无泄露:折外预测保证影子特征不会让元模型看到"训练过的样本",避免过拟合。
- 信息高阶:影子特征是基模型学到的"知识蒸馏"结果,包含了原始特征无法捕捉的模式。
- 分层学习:第一层基模型学习原始数据,第二层元模型学习"如何融合知识",实现更强大的泛化能力。