老王是“老王私房菜”的主厨,正研发一道招牌菜——青花椒焗黄鱼。想判断这道菜行不行,他只请一位熟客打分:“很棒!”可老王心里发虚:万一是熟客那天心情好?万一是自己手抖多放了半勺盐?一个人的一次评价,太看运气了。于是老王定下规矩:新菜立项,请一批老客分多轮盲品,轮流当评委;评委口味要比照顾客构成;试菜必须按季节来,不能拿夏天的心得评价秋天的菜单;同批进货的鱼不能既当考题又当练习;更关键的是,谁提过调味建议,谁就不能进终审团——否则分数必有水分。 这套“品鉴流程”就是机器学习里的交叉验证(Cross-Validation):一种诚实、反复、公平的模型评估方法。读完这篇你会明白:什么时候用 K 折、什么时候留一验证、时序数据怎么防“穿越”、不平衡数据怎么保比例、怎样避开最隐蔽的“数据泄露”,以及如何用交叉验证的结果做模型选择。学完你也会像老王一样,心里装着一张“品鉴方案选择表”,再也不会盲目套默认配置。
交叉验证是 AI 面试、算法比赛与建模交付中最常用的评估武器。选错策略会让模型离线分数虚高、上线当场翻车。掌握它,你才真正从“会调库”进阶到“会判断”。
可视化演示
决策框架、K折/时序/嵌套交叉验证全流程可视化。
本节配有交互动效(进入视口后自动加载,约 3KB)。
策略选择决策框架 首先判断数据是否具有时间依赖结构 不平衡数据使用分层交叉验证保持比例 Decision = f(Time, Balance, Group, Size) 根据数据特征选择最合适的验证策略
交叉验证思想
老王刚推出“青花椒焗黄鱼”,想知道它是否配得上招牌。他请了一位熟客打分——客人夸“很棒!”可老王心里发虚:万一是熟客那天心情好?万一是自己手抖多放了半勺盐?一个人的一次评价,太看运气了。传统留出法(把数据一次性切成训练集和测试集)就像这次单点评审:划分方式稍有不同、测试集的人选稍有变化,分数就会大幅波动。
机器学习的评估需要“多轮盲品”:把数据切成多份,每份轮流当“考官”,其余部分当“练习材料”,每轮得到一个分数,最后把所有分数平均。这就是交叉验证的核心思想——不靠一次运气,靠反复实验取均值来估计模型的真实水平。
老王从此立下后厨铁律:新菜立项,至少请十位老客分别试吃,取平均分。谁再说“我试过,很好吃”,他都会反问一句:“你试了几轮?”
- K 次实验k 代表第 k 次验证实验,k 从 1 数到 K,总共做 K 次验证。
- 单次得分S_k 是第 k 次实验里模型在当次验证集上的指标,比如准确率或 AUC。
- 求和把所有 K 次实验的分数累加起来。
- 取平均除以 K 得到交叉验证平均分,用它衡量模型的泛化能力。
K折交叉验证
老王把二十四位常客编好号,分成五组。第一轮请第一组当“严格考官”,其余四组当“陪练食客”讨论改良;第二轮换第二组当考官……直到五组都当过一圈考官。每位客人都既出过主意,也被严格要求过——这就是 K 折交叉验证的生活版:每一份数据都轮流做验证集,其余做训练集。
技术做法是把数据集随机等分成 K 份(fold)。第 k 轮保留第 k 份作验证集,用剩下的 K-1 份训练模型并在验证集上打分;K 轮后取平均。每折训练集大小约为 (K−1)/K × N,验证集为 N/K。
K 的取值是门学问。K 越大,每折训练数据越多,模型越接近“用全量数据训练”的效果,偏差越小;但折与折之间训练集重叠变大,多次得分高度相关,评估方差反而增大,计算成本也线性上升。所以常用 K=5 或 K=10 作为偏差、方差与算力之间的平衡点。
老王的经验法则:一般季节,五轮品鉴足够稳;追求更精细就上十轮,但要多付出一倍的时间和人力成本——就像 K 从 5 升到 10,训练开销也翻倍。
- 去掉第 k 折D_{-k} 表示从完整数据集 D 中拿走第 k 份后剩下的 K-1 份数据,作为本轮训练数据。
- 训练模型在第 k 轮训练数据上学出一个模型,用下标标明它来自哪份训练集。
- 用第 k 折验证拿从没参与训练的第 k 折 D_k 当验证集,计算损失 L,损失越小模型越好。
- K 轮取平均把 K 轮损失相加再除以 K,得到最终的交叉验证误差。
留一与留P法
新店刚开张,老王的熟客只有五位。把五个人分成五组、每组一人,其实就是“一轮只有一位考官”——每次只留一位老客试菜,其余四人陪老王调配方。五位顾客轮流当考官,谁也不偏心。这就是留一法(Leave-One-Out,LOOCV):当 K 折的 K 等于样本数 N 时,每轮验证集只有一个样本。
留一法每轮用 N-1 个样本训练,只留 1 个样本做验证,重复 N 轮。在数据量极小时,它是“榨干”每一条信息的做法——平均每轮只浪费一个样本。但代价很大:要训练 N 次模型,而且各轮训练集几乎完全相同,N 个结果高度相关,评估方差反而偏大。因此它只适合小样本,N 上千之后基本不实用。
折中方案是留P法(Leave-P-Out):每轮留 P 个样本验证、N-P 个训练,适合部分带时间依赖的小场景;但工程上更常用的替代是“重复 K 折”——用不同随机种子多跑几轮 K 折再平均,成本可控且方差更低。
五位熟客帮老王撑过了最难的开业期;但客人一多,他立刻改用“分组轮流品鉴”——因为一对一评审虽然最用心,却太费厨子了。
- 遍历样本i 从 1 到 N 逐一遍历,每个样本都当一次“唯一考官”。
- 剔除单样本D_{-i} 表示从完整数据中删掉第 i 个样本后的训练集。
- 单独考核把 (x_i, y_i) 当作唯一的验证集,计算模型在这个样本上的损失。
- 平均 N 次损失将 N 轮损失相加取平均,得到留一交叉验证误差。
分层交叉验证
老王的顾客里七成爱清淡,三成无辣不欢。如果某一轮品鉴团恰好全是“清淡派”,他会误以为麻辣菜没人要;全是“重辣派”,又会高估那道剁椒鱼头。所以老王立了规矩:每一桌评委都必须按 70:30 的比例组员。这就是分层——保证每一折里各类样本的比例与全数据集一致。
分类任务遇到类别不平衡时(比如欺诈样本只占 1%),随机 K 折很可能出现某一折完全没有正样本:模型在那折根本没被正例考验过,评估分自然失真。分层K折交叉验证(Stratified K-fold)解决这个问题:先按标签把样本分组,再从每个类别里按比例抽取,组装成每一折。
分层的思路也能延伸到回归:把目标值 y 切成若干箱(bin),按箱分层,让每折里 y 的数值分布贴近全量。实现上只需用 StratifiedKFold 替代 KFold,代价几乎为零,收益却很大——尤其当你的标签分布天然不均衡时。
从那以后,老王的品鉴桌永远按顾客比例组员:七成清淡,三成麻辣。评委可以口味各异,但任何一轮都不能失真。
- 全局类别比例p_c 表示类别 c 在整个数据中的占比,由该类别样本数 n_c 除以总样本数 N 得到,它是分层的“基准菜谱”。
- 单折类别占比\hat{p}_{c,k} 是第 k 折中类别 c 的样本数 n_{c,k} 与该折总样本数 n_k 的比值。
- 分层约束要求每个类别在每一折的占比都与全局一致,即 \hat{p} 约等于 p,任何一折都不会变成“全清淡派”或“全重辣派”。
时序与分组
老王有本“时令菜谱”:春天用春笋,夏天用番茄,秋天用蟹粉。想判断秋天的蟹粉菜好不好,不能拿夏天的顾客评价来背书,更不能让“夏令菜单”去预测秋冬季——那是拿未来冒充过去。时序数据随机打乱做 K 折,等于让夏天的番茄穿越到秋天打分,分数全是幻觉。
解决“穿越”的标准做法是前向滚动验证:把数据按时间顺序切成 T 段,第一轮用第 1 段训练、预测第 2 段;第二轮用第 1+2 段训练、预测第 3 段……训练窗永远在验证窗之前且不断扩展。这就是 sklearn 的 TimeSeriesSplit(扩展窗口),另有滑动窗口变体。
另一类是分组数据:同一个病人的多次检查、同一个用户的多笔消费,组内样本高度相关。若随机划分,同一病人的片子会同时出现在训练和验证集,模型记住的是“这是谁”而不是“这是什么病”——分数虚高。GroupKFold 保证同一组样本永远只落在同一折里,绝不跨界;时序分组的组合场景可用 BlockedTimeSeriesSplit。
老王把“时令评审”和“同批食材同组试菜”写进了后厨守则:评委可以挑剔口味,但绝不允许拿明天的菜点评今天。
- 时间分块把时间序列均匀切成 T 段,先后顺序就是数据的“时令顺序”。
- 历史窗口训练D_{1:t} 表示第 1 段到第 t 段的全部历史数据,只用它训练模型。
- 预测下一段第 t+1 段是“未来”,只当验证集,绝不让它触碰训练过程。
- 滚动平均t 从 1 滚到 T,把所有轮损失平均,得到前向验证误差。
嵌套交叉验证
老王要为冬季菜单定夺“最佳火候”。他先请 A 组熟客反复试吃不同火候的版本,选出评分最高的 8 分钟方案——这叫“用验证集调超参数”。然后他把 A 组的最高分 98 分报给老板当“最终水平”,老板很高兴。但老王知道这不对:98 分是在 A 组帮助下量身定制出来的,是自我赞美,不是真实水平。于是他请来从未参与调味的 B 组评审团,用 8 分钟方案正式评测——这才是终审分数。
机器学习里,用交叉验证搜索最优超参数时,“选择”本身就消费了验证信息:验证集帮我们选出了最优模型,它的分数天然偏高,直接拿它对外报告是有偏的。嵌套交叉验证(Nested CV)把两件事分开:外层负责“评估泛化能力”,内层负责“选择超参数”。流程是:外层把数据分成 K_O 折;对每一折的训练部分,再做一个完整的内层 K_I 折 CV 选出最优超参数;然后用该参数在外层训练部分重新训练,再在外层验证折上打分。最终分数由外层各折平均得到,完全不沾内层选择过程的光。
代价是训练次数约等于 K_O × K_I 次,属于“慢但诚实”的评估。当你既要在多个超参数配置里选一个,又要向老板报告“它大概能考多少分”时,嵌套是唯一不出卖信任的方案。
老王从此给老板的报告分两张表:内层得分仅供研发内部参考,外层终审分数才对外承诺——就像 B 组评审团的分数,才配写进菜单宣传语。
- 外层循环 j外层把数据分成 K_O 折,j 表示当前正在做第 j 折的终审。
- 内层选出最优参数\hat{\lambda}_j^* 表示在第 j 折外层训练部分内部,用内层交叉验证搜索出的最优超参数。
- 重新训练再验证用选出的最优参数在外层训练部分上重新训练模型 f,然后到外层验证折 D_j 上打分。
- 外层平均K_O 个外层折的分数平均,得到无偏的泛化能力估计。
数据泄露防范
比赛的公平性怎么破坏?很简单:开赛前把正确答案贴在墙上,或让评委看到调料配方。数据泄露就是这种事——把验证集的信息提前“喂”给训练过程,分数虚高还不自知。老王绝不会让评委看见调料单,但很多机器学习项目却在不经意间犯同样的错:先在全量数据上做标准化,再划分训练集和验证集。
最常见的泄露来自全量预处理:StandardScaler 在全量数据上 fit,均值和方差里就混入了验证折的信息;全量数据上做 PCA、做缺失值填充、做特征选择后再划分,同样是泄露。信息从验证折流向训练过程,模型评估就像看答案考试。更隐蔽的还有:反复用验证集分数人工调参再回到验证集评分——超参数选择本身带有温和泄露,嵌套 CV 就是为它而生。
正确的姿势是“先划分,后预处理”,并且把预处理装进 Pipeline:每一折只在训练部分上 fit 变换器的参数,再用这些参数 transform 验证部分。这样任何均值、方差、主成分都只来自训练信息。
老王把“调料单机密”升级成后厨铁律:谁在划分前动过全量数据,这道菜直接回锅重做;评审前任何人不得进入后厨。
- 训练集统计量μ_train 与 σ_train 是当前折训练部分计算出的均值和标准差,这是泄露的“海关关口”。
- 验证样本照此转换验证折里任意样本 x_i 都套用训练集的 μ 和 σ,而不是自己的统计量。
- 禁止全量统计若 μ、σ 在全量数据上计算,验证信息就通过统计量溜进训练环节,分数虚高。
策略选择实战
现在把老王的“品鉴预案表”贴在厨房门口:常客少就一对一私房评审(留一法);时令菜分季评审(时序前向验证);口味比例按顾客构成组桌(分层);同批进货的鱼放同一桌(分组);要定终审分数先做内部盲测(嵌套)。选交叉验证方案,本质是回答四个问题:数据多不多?有没有时间顺序?样本是否天然成组?类别是否失衡?
用同一套交叉验证方案比较多个模型,选分数最高的,就是模型选择的标准动作。公平性要求:所有候选模型必须使用完全相同的折划分和随机种子,否则分数差异可能来自划分运气而非模型实力。实践建议:小数据用 repeated K 折或留一;大数据用 K=5/10;不平衡用分层 K 折;时序用 TimeSeriesSplit;有分组用 GroupKFold(可叠加分层);需要对外承诺上线水平时,用嵌套交叉验证出具最终分数。
后厨墙上的预案表,就是老王“模型选择”的全部心法:先看数据,再定方案,统一折次,取最高分,嵌套兜底——这样端上桌的菜,才敢对客人说“稳”。
- 候选模型集合M 涵盖不同算法与超参数组合,每个成员都是“参赛选手”。
- 统一方案评分每个模型都用同一交叉验证策略(同样的折划分与种子)算出平均分。
- 取最高分者\arg\max 表示返回令分数最大的那个模型。
AI 应用场景
信贷反欺诈模型的离线评估与选型
阶段:模型评估与模型选择(离线阶段)
解决的问题:欺诈交易占比不到 1%,直接用随机 K 折会出现某些折完全没有欺诈样本,评估分数忽高忽低;团队早期习惯先在全量数据上归一化再跑 K 折,导致离线 AUC 虚高、上线后回撤严重。这就像老王的品鉴团里混进了全“清淡派”,还要看一遍调料单再打分。
具体案例:某消费金融公司用 StratifiedKFold(5) 配合 Pipeline 内嵌 StandardScaler,逐折 fit 归一化;再用嵌套交叉验证比较逻辑回归与 XGBoost 的外层分数,最终 XGBoost 外层 AUC 0.89 写入模型卡。上线三个月后,线上实时 AUC 与离线差距从 0.12 缩小到 0.02。
电商销量时序预测的滚动验证
阶段:时序预测建模与特征验证
解决的问题:随机 K 折会把过去和未来的销量数据打乱,模型“偷看未来”;单次留出法只把最后一个月当测试集,验证一次,遇到大促波动就误判,相当于只请一位熟客评一道时令菜。
具体案例:某电商团队用 TimeSeriesSplit 按周切出 5 个验证窗,滚动评估销量预测模型;将“是否加入节假日特征”两组配置放在完全相同的 5 个窗上对比平均 MAE,最终确定保留该特征,并额外用 BlockedTimeSeriesSplit 验证跨年度泛化能力后才上线。
医疗影像按患者分组的合规评估
阶段:评估协议设计(临床前验证)
解决的问题:同一病人的几十张影像若随机划分,训练集和验证集都会出现该病人的片子,模型学会“认人”而非“认病灶”,准确率虚高。就像同一批进货的鱼既当考题又当练习,分数自然漂亮。
具体案例:某医院 AI 辅助诊断项目中,团队用 GroupKFold(5) 按病人 ID 分组评估肺结节检测模型,保证同一病人的所有影像只出现在一个折;再叠加嵌套交叉验证给出最终模型卡,审评专家认可了这份“同组不跨界”的评估报告。
Python 演示
import numpy as npfrom sklearn.datasets import make_classificationfrom sklearn.linear_model import LogisticRegressionfrom sklearn.model_selection import (KFold, StratifiedKFold, LeaveOneOut, TimeSeriesSplit, GroupKFold, cross_val_score)from sklearn.preprocessing import StandardScalerfrom sklearn.pipeline import make_pipeline np.random.seed(42) # 1. imbalanced data: compare KFold vs StratifiedKFoldX, y = make_classification(n_samples=1000, n_features=8, weights=[0.95], random_state=7)model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))plain = cross_val_score(model, X, y, cv=KFold(5), scoring='roc_auc')straf = cross_val_score(model, X, y, cv=StratifiedKFold(5), scoring='roc_auc')print('KFold AUC: %.4f (+/- %.4f)' % (plain.mean(), plain.std()))print('StrKFold AUC: %.4f (+/- %.4f)' % (straf.mean(), straf.std())) # 2. time series: expanding forward validation onlyX_t, y_t = make_classification(n_samples=120, n_features=4, random_state=3)tscv = TimeSeriesSplit(n_splits=4)tscores = cross_val_score(model, X_t, y_t, cv=tscv, scoring='accuracy')print('TimeSeries acc per fold:', np.round(tscores, 3)) # 3. group data: same patient never crosses foldsX_g, y_g = make_classification(n_samples=200, n_features=6, random_state=9)groups = np.repeat(np.arange(40), 5) # 40 patients x 5 images eachgscv = GroupKFold(n_splits=5)gscores = cross_val_score(model, X_g, y_g, cv=gscv, groups=groups, scoring='accuracy')print('GroupKFold acc: %.4f' % gscores.mean()) # 4. LOOCV on a very small datasetX_s, y_s = make_classification(n_samples=40, n_features=3, random_state=5)loo_scores = cross_val_score(model, X_s, y_s, cv=LeaveOneOut(), scoring='accuracy')print('LOOCV acc: %.4f' % loo_scores.mean())
make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))把标准化放进管线,每折只对训练部分拟合,根治数据泄露。cross_val_score(model, X, y, cv=KFold(5), scoring='roc_auc')普通五折,随机划分未考虑类别占比。cv=StratifiedKFold(5)分层五折,保证每折维持 95:5 的类别比例。TimeSeriesSplit(n_splits=4)前向滚动切分,训练窗口永远在验证窗口之前。groups = np.repeat(np.arange(40), 5)模拟 40 个病人每人 5 张影像,构成 40 个分组。cv=GroupKFold(n_splits=5), groups=groups按组切分,同一病人的样本绝不跨折。cv=LeaveOneOut()极小数据集上每轮只留 1 个样本做验证,最大化数据利用。
常见误区
误区我项目里的交叉验证就用 sklearn 默认的 KFold,套在时序数据上也照样跑,跑出来的分数还很漂亮。
正解随机 K 折只适合独立同分布的数据。时序数据必须用 TimeSeriesSplit 保证训练永远早于验证,否则等于“拿夏天的番茄评价冬天的菜单”,再漂亮的分数也是幻觉;分组数据要用 GroupKFold 防止同组样本跨界。选方案前先回答“数据有没有顺序?有没有组结构?”。
为何常见:教程里的示意图几乎全是随机划分的 K 折,“默认即万能”的印象被牢牢种下,很少有人主动质疑数据背后的结构假设。
误区留一法每轮都用 N-1 个样本训练,最能利用数据,所以 K=N 一定最严谨,我每次都上留一。
正解留一法的 N 个结果几乎一致,折与折之间高度相关,评估方差反而偏大;同时训练 N 次模型,成本随样本量线性飙升。K 在 5~10 之间是偏差、方差与算力的经验平衡点。只有样本量很小(几十条)时,留一或重复 K 折才有真正收益。
为何常见:“训练数据越多越准”的直觉很强大,但评估关心的是“估得稳不稳”,而不是“训练得爽不爽”,这一点初学者很难转过弯。
误区标准化只是把数值缩放一下,又不碰标签,先在全量数据上 fit StandardScaler 再做 K 折,肯定不影响结果。
正解全量 fit 的均值与方差里含有验证折的信息,这就是数据泄露。验证集样本的 z 分数被“训练过的统计量”加工过,分数虚高;本质上像开考前把答案的统计规律泄露给了考生。必须把预处理装进 Pipeline,每折只 fit 训练部分,再 transform 验证部分。
为何常见:预处理不接触标签,很多人误以为“无监督操作”就不算泄露;实际上任何基于全量数据的统计量,都会把验证信息引入训练过程。
误区我用网格搜索调参,验证集上最高 AUC 是 0.92,直接写进周报说这个模型上线能考 0.92。
正解网格搜索的目标函数就是验证集分数,选出来的最高分必然被“选择过程”推高——这叫乐观偏差。要用嵌套交叉验证:内层选超参数,外层给每份配置一次从未参与选择的终审分数,那才是可对外承诺的泛化估计,相当于 A 组调配方、B 组出终审分。
为何常见:人的本能是把自己亲手选出来的最好成绩当宝贝,忘了成绩单和颁奖词不能由同一个人写。
误区我的模型离线 5 折 CV 有 0.95,老板问上线行不行,我说当然行,数据都验证过了。
正解交叉验证评估的是“相似分布数据上的泛化能力”,不等于生产环境。训练与上线之间存在数据分布漂移、特征缺失、延迟差异;更常见的坑是评估流程本身带泄露,让离线分数虚高。规范做法:统一 Pipeline、嵌套打分、上线后监控漂移,再用 A/B 测试回填真实效果。
为何常见:离线评估天然给人“实验室即世界”的错觉,把代理指标当成业务指标,是新手最容易付出昂贵学费的一课。
面试题
Q1. 下列哪种交叉验证方式最适合样本量很小(如 N=50)的分类任务?
- A.做五次交叉验证
- B.留一交叉验证← 正确答案
- C.做普通留出法
- D.做分层五折法
答案:B。数据量很小时,留一法每轮用 N-1 个样本训练,最大化数据利用;五折每折训练数据只有 80%,信息损失较大。这就像老王只有五位熟客时采用“一对一私房评审”,每个顾客都不放过。
Q2. 时序预测任务中直接使用随机 K 折交叉验证的最大风险是什么?
- A.训练集样本量减少
- B.未来信息混入训练← 正确答案
- C.模型训练速度加快
- D.评估方差必然变小
答案:B。随机打乱会打破时间顺序,让模型用“未来”数据训练再去预测“过去”,相当于拿夏天的番茄评价冬天的菜单,评估结果没有意义且分数虚高。时序场景应使用前向滚动验证。
Q3. 类别不平衡数据(正例仅占 2%)应该优先选择哪种交叉验证?
- A.随机K折交叉验证
- B.分组K折交叉验证
- C.分层K折交叉验证← 正确答案
- D.前向链式交叉验证
答案:C。随机 K 折可能让某一折完全没有正例,模型在该折“没东西可测”。分层 K 折保证每折正负例比例与全量一致,正如老王每桌评委都按 70:30 配比,任何一轮都不会变成全“清淡派”。
Q4. 关于 K 值增大对 K 折交叉验证的影响,下列说法正确的是?
- A.训练数据增多偏差增大
- B.训练数据增多方差增大← 正确答案
- C.计算时间随之线性减少
- D.每折验证集占比变大
答案:B。K 增大使每折训练占比 (K−1)/K 增大,模型更接近全量训练,偏差减小;但折间重叠变大,评估结果相关性变高,方差增大。C 错在计算量增加而非减少,D 错在验证集占比变小。
Q5. 嵌套交叉验证中外层循环的作用是什么?
- A.用全部数据训练最终模型
- B.对模型泛化能力做无偏评估← 正确答案
- C.搜索并选出最优超参数
- D.替代所有特征选择步骤
答案:B。内层循环负责为每一折选超参数,外层循环只拿“没参与选择过程”的验证折做最终评分,避免选参导致的乐观偏差。最终上线模型仍需要用全量数据重新训练一次。
Q6. 同一病人的多张医学影像出现在数据集中,评估模型时应使用哪种验证方式?
- A.随机K折且可打乱样本
- B.分层K折保持样本比例
- C.按病人分组的GroupKFold← 正确答案
- D.留一法逐样本做评估
答案:C。同一病人的影像高度相关,随机划分会让同一病人同时出现在训练与验证集,模型“记住人”导致分数虚高。GroupKFold 保证同一组样本不跨折,如同批进货的鱼不能既当考题又当练习。
Q7. 下列关于数据泄露的说法,最准确的是哪一项?
- A.训练验证无重叠即无泄露
- B.全量标准化属于正常操作
- C.全量拟合标准化再做K折即泄露← 正确答案
- D.泄露只影响速度不影响分数
答案:C。泄露的本质是验证信息混入训练流程。先在全量数据上拟合 StandardScaler 再划分 K 折,均值与方差已包含验证折信息,即使训练验证样本没有重叠,工序错了分数也会虚高,属于典型的“先看答案再考试”。
Q8. 下列哪些情况适合使用留一法交叉验证?
- A.样本量极小只有几十条← 正确答案
- B.训练一次模型需要数天
- C.希望最大化每折训练数据← 正确答案
- D.数据存在明显时间顺序
答案:AC。留一法适合样本量小的场景,且每轮用 N-1 个样本训练,最大化训练数据利用。但若单次训练成本极高,N 次训练不可行;时序数据应使用前向滚动验证,而不是留一法。
Q9. 关于嵌套交叉验证,下列说法正确的有哪些?
- A.内层循环负责模型选择← 正确答案
- B.外层分数可保证线上效果
- C.外层分数估计泛化能力无偏← 正确答案
- D.嵌套交叉验证成本高于普通← 正确答案
答案:ACD。内层在每折训练部分内再划分并搜索最优超参数,外层用未参与选择的验证折打分,因此是无偏的泛化估计。但“无偏”不等于“必然等于上线效果”,分布漂移仍会造成差异;嵌套训练次数约为内外折数乘积,成本显著更高。
Q10. 上线前比较两个模型的泛化能力,下列做法中有利于评估更可靠的有哪些?
- A.所有模型用相同的折划分← 正确答案
- B.用嵌套交叉验证外层分数← 正确答案
- C.直接比网格搜索的最优分数
- D.重复K折报告均值与标准差← 正确答案
答案:ABD。相同折划分保证分数差异来自模型而非划分运气;嵌套外层分数避免超参数选择的乐观偏差;重复 K 折降低单次划分的方差。C 犯“自我赞美”错误——搜索过程已用过验证信息,直接取最高分会系统性高估模型能力。