Skip to content

交叉验证与模型选择

交叉验证(Cross-Validation, CV)是机器学习里”如何诚实评估模型”的核心方法,也是超参调优、模型选择的标准工具。本页系统讲解 K 折、分层 K 折、留一法、时序 CV、分组 CV 等变体,嵌套 CV 的数学原理,以及网格/随机/贝叶斯搜索的正确用法与对比。前置阅读:模型评估与指标、监督学习。

把交叉验证想象成多次模拟考试取平均分:只用一次期末考试(单一训练/测试划分)来评判学生水平,可能碰巧考了他复习过的题型。多次考试、每次换题、最后取平均——这样估出来的水平才可靠。

  • 训练/验证/测试三件套:训练集 = 平时作业(学习用);验证集 = 模拟考试(调超参、选模型用);测试集 = 期末考试(只在最后用一次,评估泛化)。
  • K 折 CV = 把模拟考卷切成 K 份轮流当考题:数据分 K 份,每次拿 1 份当验证、其余 K-1 份训练,循环 K 次取平均——每条样本都被验证过一次,评估最稳。
  • 分层 K 折 = 每份都保持类别比例:不平衡数据用普通 K 折可能某份里一个正样本都没有,分层保证每份比例一致。
  • 时序 CV = 永远用过去预测未来:时间序列不能随机打乱,必须严格用前面的数据训练、后面的数据验证,否则就是”用未来信息预测过去”(数据泄漏)。

把数据随机切成一份训练集、一份测试集,评估结果取决于这次随机切分——数据少时方差很大。一个极端例子:只有 20 条样本,换一种切法,准确率可能从 70% 跳到 90%。交叉验证的本质是降低评估方差:让每条数据都参与验证,取多次结果的平均。

从概率角度理解:设模型在数据集 D 上的真实泛化误差为 EtrueE_{\text{true}},单次 holdout 得到的估计为 E^holdout\hat{E}_{\text{holdout}}。由于 holdout 只用了一个子集做测试,E^holdout\hat{E}_{\text{holdout}} 是一个随机变量——其方差取决于测试集大小 ntestn_{\text{test}}:

Var(E^holdout)≈Etrue(1−Etrue)ntest\text{Var}(\hat{E}_{\text{holdout}}) \approx \frac{E_{\text{true}}(1 - E_{\text{true}})}{n_{\text{test}}}

测试集越小,方差越大。K 折 CV 通过重复 K 次评估取平均,等效于把”有效测试集大小”从 N/KN/K 扩大到 NN(每条样本恰好被测试一次),从而显著降低估计方差。

设数据集 DD 含 NN 个样本。K 折步骤:

  1. 把 DD 尽量均等地划分成 KK 个互不相交的子集 D1,D2,…,DKD_1, D_2, \ldots, D_K,每个子集约 N/KN/K 个样本。
  2. 对 ii 从 1 到 KK:用 DiD_i 作为验证集,其余 K−1K-1 份合并 Dtrain(i)=D∖DiD^{(i)}_{\text{train}} = D \setminus D_i 作为训练集,训练模型 fif_i 并在 DiD_i 上评估,得到分数 sis_i。
  3. 最终分数为 K 个分数的平均,并附标准差衡量稳定性:

sˉ=1K∑i=1Ksi,SD(s)=1K−1∑i=1K(si−sˉ)2\bar{s} = \frac{1}{K}\sum_{i=1}^{K} s_i, \quad \text{SD}(s) = \sqrt{\frac{1}{K-1}\sum_{i=1}^{K}(s_i - \bar{s})^2}

典型取 K=5K = 5 或 1010。KK 越大训练成本越高(每次训练用更多数据),但评估方差越小;K=NK = N 时即”留一法”(Leave-One-Out)。

K 折 CV 的估计误差也受偏差-方差权衡影响:

  • 训练集大小效应(影响偏差):KK 越大,每折训练集 N(K−1)/KN(K-1)/K 越接近全集 NN,训练出的模型越接近最终模型,偏差越小。K=2K=2 时训练集只有一半数据,偏差最大。
  • 折间相关性效应(影响方差):KK 越大,各折训练集重叠越多(K−2K-2 份数据是共享的),模型 fif_i 之间高度相关,取平均降低方差的效果递减。

Kohavi (1996) 的经典实验表明:K=10K=10 在多数场景下偏差和方差的平衡最好;K=5K=5 是精度与效率的实用折中。

当 K=NK = N(留一法),每折训练集大小为 N−1N-1,偏差几乎为零。但 LOOCV 有一个微妙问题:各折训练集之间有 N−2N-2 个样本重叠,模型之间高度相关。对于稳定模型(如线性回归),LOOCV 的方差甚至比 K=10K=10 更大。

对于线性回归有一个优雅的封闭解(“留一残差”公式),无需真正训练 NN 次:

LOOCV 误差=1N∑i=1N(yi−y^i1−hii)2\text{LOOCV 误差} = \frac{1}{N}\sum_{i=1}^{N}\left(\frac{y_i - \hat{y}_i}{1 - h_{ii}}\right)^2

其中 hiih_{ii} 是帽子矩阵(hat matrix)H=X(XTX)−1XTH = X(X^TX)^{-1}X^T 的第 ii 个对角元素,也叫杠杆值(leverage)。杠杆值高的样本对模型影响大,留一误差也大——这与直觉一致。

  • 分层 K 折(Stratified K-Fold):每个折里类别比例与全集保持一致。例如全集有 10% 正样本,则每折也保持约 10% 正样本。分类任务(尤其类别不平衡)必用,否则某折可能完全没有正样本。
  • 留一法(LOOCV):K=NK = N 的特例,每次只留 1 条验证。评估方差最小但计算量最大,且每次训练集几乎相同导致方差估计有偏,一般不推荐。
  • 重复 K 折(RepeatedKFold):把 K 折 CV 重复 RR 次(每次重新随机分折),共 K×RK \times R 次评估。在不增加单次训练成本的前提下进一步降低方差——对于小数据集特别有效。
  • 分组 K 折(GroupKFold):同一”组”(如同一患者、同一会话)必须同时在训练集或验证集,防止信息泄漏,医疗/用户数据必备。
  • 时序 CV(TimeSeriesSplit):第 1 折用前 nn 份训练、第 n+1n+1 份验证;第 2 折用前 n+1n+1 份训练、第 n+2n+2 份验证……严格递增,绝不回头,适用于一切有时间顺序的数据。
  • 留 P 组(LeavePGroupsOut):留出若干整组做验证,组内相关性强时使用。

选定评估指标后,遍历超参组合,每组用交叉验证取平均分,选最优组合。三种搜索策略对比:

穷举所有超参组合。例如 3 个超参各 5 个值就是 53=1255^3 = 125 组,乘以 5 折 CV 即 625 次训练。网格搜索的缺点是组合爆炸,且浪费资源在不重要的超参维度上——如果只有 1 个关键超参,网格搜索会搜索 4 个无关维度的所有组合。

从参数空间随机采 NN 组。Bergstra & Bengio (2012) 的经典论文证明:在相同试验次数下,随机搜索往往不逊于甚至优于网格搜索。关键洞察是**“有效维度”通常远低于参数空间的维度**——只有少数超参真正重要,随机采样更容易在这些关键轴上探索不同值。

设超参空间维度为 dd,网格搜索在每维取 gg 个值,每个维度只采样 g1/dg^{1/d} 个不同值(因为预算被分摊到所有维度组合)。随机搜索每个维度都能取到 NN 个不同值(NN 是试验次数),关键维度的覆盖率高得多。

贝叶斯优化的核心思想:用上一个试验的结果指导下一个采样,越搜越聪明。它维护一个代理模型(surrogate model)来近似超参到性能的映射,然后用采集函数(acquisition function)决定下一个采样点。

贝叶斯优化的数学框架:

  1. 代理模型:用高斯过程(GP)或树结构 Parzen 估计器(TPE)来建模 p(score∣x)p(\text{score} | \mathbf{x}),其中 x\mathbf{x} 是超参向量。
  2. 采集函数:平衡”探索”(exploration,去不确定区域采样)与”利用”(exploitation,在已知好区域细化)。常用的 Expected Improvement:

EI(x)=E[max⁡(f(x)−f∗,0)]\text{EI}(\mathbf{x}) = \mathbb{E}\left[\max(f(\mathbf{x}) - f^*, 0)\right]

其中 f∗f^* 是当前最优值。EI 高的点就是”既可能好、又不确定”的点。

  1. 迭代:每次选 EI 最大的点试验 → 更新代理模型 → 重新计算 EI → 选下一个点……

Optuna 使用的是 TPE(Tree-structured Parzen Estimator),它不直接建模 p(y∣x)p(y|\mathbf{x}),而是用贝叶斯定理建模 p(x∣y)p(\mathbf{x}|y):

p(x∣y)=p(y∣x)p(x)p(y)  ⟹  p(x∣y)∝p(y∣x)p(x)p(\mathbf{x}|y) = \frac{p(y|\mathbf{x})p(\mathbf{x})}{p(y)} \implies p(\mathbf{x}|y) \propto p(y|\mathbf{x})p(\mathbf{x})

TPE 把 p(x∣y)p(\mathbf{x}|y) 拆成两部分:l(x)l(\mathbf{x})(“好”的参数分布,y<y∗y < y^*)和 g(x)g(\mathbf{x})(“差”的参数分布,y≥y∗y \geq y^*)。最大化 l(x)/g(x)l(\mathbf{x})/g(\mathbf{x}) 的比值就是下一个采样点——即”在好区域密度高、在差区域密度低”的地方。

特性网格搜索随机搜索贝叶斯优化
试验效率低(穷举所有组合)中(随机覆盖关键维度)高(历史指导采样)
并行性极好(所有组合独立)极好(所有采样独立)差(需要历史结果指导下一步,串行性强)
连续/条件参数不支持(必须离散化)支持原生支持
适用场景参数少、维度低参数中等、需要快速并行参数多、训练昂贵、预算紧张
过拟合风险中(依赖网格设计)中高(试验次数多时可能过拟合 CV)

当超参搜索本身也用 CV 时,用同一份数据既选超参又评估会”偷看”验证集,导致选择偏差(selection bias)——评估偏乐观。原因:超参搜索本质上是在验证集上”优化”了,验证分数自然偏高。

数学上,设超参搜索在 CV 上的最优分数为 s^∗\hat{s}^*,真实泛化性能为 strues_{\text{true}}。由于 s^∗=max⁡θs^(θ)\hat{s}^* = \max_{\theta} \hat{s}(\theta) 是多个候选中的最大值,它是一个向上偏的估计:

E[s^∗]≥strue\mathbb{E}[\hat{s}^*] \geq s_{\text{true}}

候选超参组合越多(网格越密、搜索次数越多),乐观偏差越大——这叫多重比较问题(multiple comparisons problem)。

嵌套 CV 用两层循环解决:

  • 外层(outer loop):KouterK_{\text{outer}} 折,用于泛化评估。每折的验证集是”最终未见数据”的模拟。
  • 内层(inner loop):在每折的训练集上,再用 KinnerK_{\text{inner}} 折做超参搜索,选出最优超参。
  • 外层评估:用内层选出的超参在训练集上训练,在外层验证集上评估。

总训练次数 = Kouter×Kinner×超参组合数K_{\text{outer}} \times K_{\text{inner}} \times \text{超参组合数}。例如 5×3×50=7505 \times 3 \times 50 = 750 次训练——计算量是单层 CV 的约 KouterK_{\text{outer}} 倍。

嵌套 CV 评估的是**“包含超参搜索的整个流程”的泛化性能**——而非某个固定超参的模型性能。这是一个重要区别:

  • 如果你只想知道”在给定超参下这个模型有多好”→ 用单层 CV。
  • 如果你想知道”这个模型 + 自动调参流程,在新数据上有多好”→ 用嵌套 CV。

实践中,嵌套 CV 用于研究报告和模型选型对比(诚实评估),单层 CV 用于最终模型的超参确定(选出超参后在全集重训)。

K 折 CV 的 KK 个分数 s1,…,sKs_1, \ldots, s_K 本身可以用来构造置信区间。但由于各折训练集高度重叠,sis_i 之间不独立,直接用 tt-分布构造 CI 会偏窄(低估不确定性)。

改进方法——重复 K 折(Repeated K-Fold):将 K 折 CV 重复 RR 次,得到 K×RK \times R 个分数,它们的分布更接近真实分布,CI 更可靠。Nadeau & Bengio (2003) 提出了考虑折间相关性的修正方差估计:

σ^corrected2=(1K+NtestNtrain)σ^s2\hat{\sigma}^2_{\text{corrected}} = \left(\frac{1}{K} + \frac{N_{\text{test}}}{N_{\text{train}}}\right) \hat{\sigma}^2_{s}

其中 σ^s2\hat{\sigma}^2_s 是折分数的样本方差,NtestNtrain\frac{N_{\text{test}}}{N_{\text{train}}} 修正项反映了折间重叠导致的额外相关性。

  • 先归一化/填充再划分:预处理(标准化、缺失值填充、特征选择)用到了全数据的统计量,验证集信息泄漏到训练。正确做法是把预处理放进 Pipeline,由 CV 在每折内部 fit_transform。
  • 时序数据随机划分:用未来的数据训练去预测过去,是时间序列里最常见的错误。
  • 同组样本跨划分:同一患者的多次记录分到训练和验证两边,模型”记住”了这个人,评估虚高。
  • 重复样本跨划分:同一图像做不同增强后的副本分散到训练和验证集,等效于”看过答案”。
from sklearn.datasets import make_classification
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
X, y = make_classification(n_samples=1000, weights=[0.1], random_state=42)
# 关键:把标准化放进 Pipeline,CV 每折内部各自 fit,杜绝泄漏
pipe = make_pipeline(StandardScaler(), RandomForestClassifier(random_state=42))
cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(pipe, X, y, cv=cv, scoring="f1")
print(f"5 折 F1: {scores.mean():.3f} ± {scores.std():.3f}")
import optuna
from sklearn.model_selection import cross_val_score
from sklearn.ensemble import GradientBoostingClassifier
def objective(trial):
params = dict(
n_estimators=trial.suggest_int("n_estimators", 50, 300),
max_depth=trial.suggest_int("max_depth", 2, 8),
learning_rate=trial.suggest_float("learning_rate", 0.01, 0.3, log=True),
)
clf = GradientBoostingClassifier(**params, random_state=42)
return cross_val_score(clf, X, y, cv=5, scoring="f1").mean()
study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=30)
print(f"最优 F1: {study.best_value:.3f}, 超参: {study.best_params}")
from sklearn.datasets import make_classification
from sklearn.model_selection import GridSearchCV, cross_val_score, StratifiedKFold
from sklearn.ensemble import RandomForestClassifier
import numpy as np
X, y = make_classification(n_samples=500, n_features=20, random_state=42)
# 内层:超参搜索(3 折网格搜索)
inner_cv = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)
param_grid = {
"max_depth": [3, 5, 7, None],
"min_samples_leaf": [1, 5, 10],
}
clf = RandomForestClassifier(n_estimators=50, random_state=42)
grid = GridSearchCV(clf, param_grid, cv=inner_cv, scoring="f1", n_jobs=-1)
# 外层:泛化评估(5 折)
outer_cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
nested_scores = cross_val_score(grid, X, y, cv=outer_cv, scoring="f1")
print(f"嵌套 CV F1: {nested_scores.mean():.3f} ± {nested_scores.std():.3f}")
# 对比:非嵌套(同一份数据做搜索和评估,分数会偏乐观)
grid.fit(X, y)
print(f"非嵌套(乐观偏差)F1: {grid.best_score_:.3f}")

运行后你会看到嵌套 CV 分数低于非嵌套分数——这个差值就是选择偏差的大小,超参组合越多差值越大。

重复 K 折构造更可靠的置信区间

Section titled “重复 K 折构造更可靠的置信区间”
from sklearn.model_selection import RepeatedStratifiedKFold
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
import numpy as np
X, y = make_classification(n_samples=300, n_features=15, random_state=42)
# 5 折重复 10 次 = 50 次评估,CI 更可靠
rskf = RepeatedStratifiedKFold(n_splits=5, n_repeats=10, random_state=42)
pipe = make_pipeline(StandardScaler(), RandomForestClassifier(random_state=42))
scores = cross_val_score(pipe, X, y, cv=rskf, scoring="f1")
# 95% 置信区间(近似正态)
mean, std = scores.mean(), scores.std()
ci_low, ci_high = mean - 1.96 * std, mean + 1.96 * std
print(f"F1 = {mean:.3f}, 95% CI = [{ci_low:.3f}, {ci_high:.3f}]")

scikit-learn 1.0+ 提供了逐步淘汰(successive halving)策略:先用少量资源评估所有候选,淘汰一半差的,再用更多资源评估剩下的,以此类推。总训练次数远少于完整 GridSearchCV。

from sklearn.experimental import enable_halving_search_cv # noqa
from sklearn.model_selection import HalvingGridSearchCV
from sklearn.ensemble import RandomForestClassifier
param_grid = {"max_depth": [3, 5, 7, 10, None], "min_samples_leaf": [1, 5, 10, 20]}
# 资源从少到多,逐步淘汰
search = HalvingGridSearchCV(
RandomForestClassifier(random_state=42), param_grid,
factor=3, cv=5, scoring="f1", random_state=42, n_jobs=-1
)
search.fit(X, y)
print(f"最优参数: {search.best_params_}, F1: {search.best_score_:.3f}")
  • 分类默认用 StratifiedKFold,回归用 KFold;不平衡数据绝不裸用 KFold。
  • 时序数据一律用 TimeSeriesSplit,绝不能随机打乱,否则评估完全失真。
  • 有组结构的用 GroupKFold:同一患者/同一用户/同一会话必须整体留在同一侧。
  • 预处理永远放进 Pipeline,由 CV 在每折内 fit,避免数据泄漏。
  • K 取 5 或 10 最常用。数据少时可加大 K 或用 RepeatedKFold,但 LOOCV 一般不划算;评估要报均值加标准差。
  • 模型最终选定的超参,要在全集上重训一次,再用独立测试集评估——验证集只是用来选超参,测试集只碰一次。
  • 嵌套 CV 用于”诚实地评估模型本身”,单层 CV 用于最终选参——别混用。
  • 超参搜索预算有限时,贝叶斯优化(Optuna)优于随机搜索优于网格搜索,但搜索空间要先调研好范围。
  • 贝叶斯优化试验次数过多时注意过拟合 CV:搜索 1000+ 组超参后,CV 分数本身就开始过拟合——可设置较少试验次数或用嵌套 CV 评估。
  • 报告模型性能时附上置信区间:仅报平均分不够,用 RepeatedKFold 构造 CI 才能判断差异是否显著。
  • Kaggle 竞赛标准流程:所有竞赛选手都用 5 折/10 折 OOF(out-of-fold)预测做模型融合与评估,单一 holdout 划分在竞赛中被认为不可靠。
  • 超参自动调优平台:Optuna、Ray Tune、Weights & Biases Sweeps 内部都基于交叉验证 + 贝叶斯优化,是 AutoML 的核心组件。
  • 医疗模型稳健性评估:临床试验中用 GroupKFold 按患者分组,确保”模型对患者泛化”而非”对单次检查记忆”,是医疗 AI 通过审查的前提。
  • 金融时序模型回测:用 TimeSeriesSplit(滚动窗口或扩展窗口)做回测,避免未来函数,是量化策略评估的硬性规范。
  • AutoML 产品:Google AutoML、H2O DriverlessAI、Azure AutoML 内部大量使用嵌套 CV 做模型选择,详见 自动化机器学习与可解释性。
  • LLM 超参搜索:大语言模型微调的超参搜索(learning rate、batch size、LoRA rank 等)同样适用 CV 思路,但因单次训练成本极高,通常用 Optuna + 早停(median pruner)来节约算力。
  • Optuna v4.x(2024-2025):引入了多目标优化(multi-objective optimization)支持——可同时优化准确率和推理延迟,用 Pareto 前沿替代单一最优解;改进的 QMOMF(Quasi-Monte Carlo 采样)在冷启动阶段比纯随机采样更快找到好区域。
  • scikit-learn 1.5-1.7(2024-2025):HalvingRandomSearchCV 稳定化;新增 FixedThresholdClassifier / TunedThresholdClassifier 可与 CV 结合做阈值调优——解决了分类阈值(默认 0.5)不一定是 F1/Recall 最优的问题。
  • ENABLE 超参搜索框架:Meta(Facebook)开源的分布式超参搜索框架,内置 ASHA(Asynchronous Successive Halving)算法,专为大规模分布式训练设计,比 Optuna 更适合 GPU 集群上的深度学习调参。
  • 微分贝叶斯优化(Differentiable Bayesian Optimization, DBO):2024-2025 年的研究热点——利用自动微分让贝叶斯优化的采集函数可微,在深度学习的超参(如网络结构参数)搜索中效率显著提升。
  • CV 与 conformal prediction 的结合:2025 年越来越多的工作将交叉验证与保形预测(conformal prediction)结合,为 CV 评估提供有限样本保证的预测集(prediction set),而非仅一个点估计——在医疗和安全关键领域尤为重要。
  • 时序 CV 的 PurgedKFold:金融机器学习(Marcos López de Prado 体系)推广了”清洗 + embargo”的时序 CV 方法,在训练/验证折之间留出隔离带,彻底消除标签重叠带来的泄漏——已成为量化金融的标准实践。
类库语言说明
scikit-learnPythonKFold、StratifiedKFold、GroupKFold、TimeSeriesSplit、RepeatedKFold、cross_val_score、GridSearchCV、RandomizedSearchCV、HalvingGridSearchCV
OptunaPython高效的贝叶斯超参优化框架(TPE + 多目标),支持剪枝、可视化、分布式搜索
HyperoptPython基于 TPE 的贝叶斯优化库,早期主流方案
Ray TunePython分布式超参搜索,支持 ASHA、Population-Based Training 等高级调度策略
Weights & Biases SweepsPython团队协作的实验跟踪 + 超参搜索一体化平台
ENABLE / AxPythonMeta 开源的贝叶斯优化平台,支持高维参数空间与多目标优化
术语英文解释
交叉验证Cross-Validation将数据分成多份轮流做训练/验证,取多次评估平均以降低方差的方法
K 折交叉验证K-Fold CV将数据等分 K 份,每次用 1 份验证其余训练,循环 K 次
分层 K 折Stratified K-Fold每个折保持与全集一致的类别比例,分类任务标配
留一法Leave-One-Out (LOOCV)K 等于样本数的特例,每次只留 1 条做验证
时序交叉验证TimeSeriesSplit严格按时间顺序,用过去训练验证未来,用于时序数据
分组交叉验证GroupKFold保证同一组样本不跨划分,防止组内信息泄漏
嵌套交叉验证Nested CV外层评估泛化、内层选超参的两层 CV,无偏评估的黄金标准
选择偏差Selection Bias在验证集上选超参导致评估偏乐观的现象
数据泄漏Data Leakage验证/测试集信息间接进入训练,导致评估过于乐观
网格搜索Grid Search穷举所有超参组合,全面但组合爆炸
贝叶斯优化Bayesian Optimization用历史试验结果指导下一组采样,越搜越聪明的超参优化方法
代理模型Surrogate Model贝叶斯优化中用于近似超参到性能映射的轻量模型(GP 或 TPE)
采集函数Acquisition Function贝叶斯优化中决定下一个采样点的函数(如 Expected Improvement)
逐步淘汰Successive Halving先用少资源评估全部候选、逐步淘汰差的,用多资源精评少数候选的搜索策略
保形预测Conformal Prediction提供有限样本保证的预测区间方法,可与 CV 结合
  • Kohavi, “A Study of Cross-Validation and Bootstrap for Accuracy Estimation and Model Selection” (IJCAI, 1996):经典实验研究,建议 10 折 CV 优于留一法,是 K=5/10 经验值的来源。
  • Bergstra & Bengio, “Random Search for Hyper-Parameter Optimization” (JMLR, 2012):证明随机搜索在相同预算下常优于网格搜索,且更易并行,超参搜索的范式转变。
  • Cawley & Talbot, “On Over-fitting in Model Selection and Subsequent Selection Bias in Performance Evaluation” (JMLR, 2010):论证嵌套 CV 才是无偏评估,揭示单层 CV 的乐观偏差。
  • Akiba et al., “Optuna: A Next-generation Hyperparameter Optimization Framework” (KDD, 2019):Optuna 官方论文,提出 TPE 与剪枝的高效实现,工业界超参优化首选。
  • Snoek et al., “Practical Bayesian Optimization of Machine Learning Hyperparameters” (NeurIPS, 2012):贝叶斯优化用于深度学习超参的经典工作,是 Spearmint/Skopt 的基础。
  • Nadeau & Bengio, “Inference for the Generalization Error” (Machine Learning, 2003):提出考虑折间相关性的 CV 置信区间修正方法,是 CV 统计推断的理论基础。
  • López de Prado, “Advances in Financial Machine Learning” (2018):第 7 章系统讲解 PurgedKFold 与 embargo 技巧,金融时序 CV 的权威参考。
  • Jamieson & Talwalkar, “Non-stochastic Best Arm Identification and Hyperparameter Optimization” (AISTATS, 2016): successive halving 的理论基础,是 HalvingGridSearchCV 的算法来源。