交叉验证与模型堆叠混合
交叉验证与模型堆叠混合
1. 交叉验证 (Cross-Validation)
交叉验证是一种用于评估模型性能和鲁棒性的技术。它通过将数据集划分为多个子集,并在不同的子集组合上进行训练和验证,从而更可靠地估计模型在未知数据上的表现。
- 目的 (重点内容):
- 更准确地评估模型泛化能力: 避免模型评估结果对特定训练/测试集划分的依赖。
- 防止过拟合评估集: 在模型开发和调参过程中,如果反复使用同一验证集来评估和调整模型,模型可能会“记住”验证集的特征,导致在真正的未知数据上性能下降。交叉验证通过使用不同的验证集来减轻这个问题。
- 充分利用数据: 在数据集较小的情况下,交叉验证可以确保所有数据都用于训练和验证。
- 基本思想:
- 将整个数据集随机分成 个互斥的子集(称为“折”或“folds”)。
- 进行 轮训练和验证:
- 每一轮,选择其中一个子集作为验证集,剩下的 个子集作为训练集。
- 在训练集上训练模型。
- 在验证集上评估模型性能。
- 最终的模型性能评估是 轮验证结果的平均值。
- 常用类型 (重点内容):
- k-Fold Cross-Validation: 将数据集分成 等份。最常用。
- Stratified k-Fold Cross-Validation: 在分类问题中,确保每一折中的类别分布与整个数据集的类别分布大致相同。对于不平衡数据集尤其重要。
- Leave-One-Out Cross-Validation (LOOCV): 等于样本数量 。每一轮用 个样本训练,1个样本验证。计算量巨大,适用于极小数据集。
- Group K-Fold: 根据样本的分组进行划分,确保同一组的样本不会同时出现在训练集和验证集中(例如,患者 ID)。用于避免数据泄露。
- 在 GBDT/Tree Models 中的应用:
- 模型评估: 使用交叉验证来获取模型性能的平均分数和标准差,作为模型泛化能力的估计。
- 超参数调优: 与网格搜索、随机搜索等结合使用,在交叉验证的每一折上评估一组超参数的效果,选择平均性能最好的参数组合。
- 早期停止 (Early Stopping): 在 GBDT 的训练过程中,通常会在训练时提供一个单独的验证集(或在交叉验证中使用某一折作为验证集),监控模型在该验证集上的性能,如果连续多轮性能没有提升,则提前停止训练。这是防止过拟合的重要手段。XGBoost 的
cv函数,以及 XGBoost, LightGBM, CatBoost 的fit方法中,都可以指定eval_set和early_stopping_rounds/callbacks来实现。
2. 网格搜索 (Grid Search)
网格搜索是一种超参数优化技术。它通过在预先指定的超参数值网格中进行穷举搜索,找到在指定评估标准下性能最好的参数组合。
- 目的 (重点内容): 寻找模型的最佳超参数组合,以最大化模型在未知数据上的性能。
- 基本思想:
- 定义一个字典,指定要调优的超参数名称以及每个参数要尝试的值列表。
- 网格搜索会生成所有可能的超参数组合。
- 对于每个超参数组合,使用交叉验证(通常是 k-fold CV)来评估模型性能。
- 选择在交叉验证中平均性能最好的超参数组合。
- 与交叉验证结合 (重点内容):
- 网格搜索通常与交叉验证一起使用。例如,在使用 scikit-learn 的
GridSearchCV时,它会自动对参数网格中的每个组合进行交叉验证。 - 在每一折交叉验证中,模型都在该折的训练集上训练,并在对应的验证集上评估。
- 最终选择的参数是使交叉验证平均得分最高的那个组合。
- 网格搜索通常与交叉验证一起使用。例如,在使用 scikit-learn 的
- 在 GBDT/Tree Models 中的应用: 用于调优 XGBoost, LightGBM, CatBoost 等模型的参数,例如
n_estimators,learning_rate,max_depth/num_leaves/depth,subsample,colsample_bytree,reg_alpha,reg_lambda/l2_leaf_reg等。 - 优缺点:
- 优点: 简单易懂,保证找到网格中最好的参数组合。
- 缺点: 计算量巨大,特别是当参数数量多或每个参数尝试的值范围大时;无法探索网格之外的参数空间。对于计算资源有限或数据集很大的情况可能不实用。
3. 模型堆叠 (Stacking)
模型堆叠 (Stacking) 是一种集成学习技术,它结合了多个不同模型(称为基础模型或第一层模型)的预测,然后使用另一个模型(称为元模型或第二层模型)来学习如何最佳地组合这些预测。
- 目的 (重点内容): 通过结合多个模型来提高预测性能,特别是当基础模型具有不同的优势和劣势时。
- 核心思想: 使用基础模型的预测作为新的特征,训练一个元模型来做出最终预测。
- 过程 (重点内容):
- 训练集划分: 将原始训练集划分为两部分(例如,使用交叉验证)。
- 训练基础模型 (Layer 1):
- 对原始训练集使用 -fold 交叉验证。
- 在每一折中,用 折的数据训练基础模型(例如,XGBoost, Logistic Regression, SVM 等)。
- 用训练好的模型对剩余的 1 折数据进行预测(这部分数据在训练当前模型时是未见过的)。
- 重复 次,将所有折的预测结果拼接起来,得到与原始训练集大小相同的“out-of-fold (OOF) 预测”数据集。这些 OOF 预测将作为元模型的训练数据。
- (可选)在整个原始训练集上训练基础模型,用于对测试集进行预测。
- 生成元模型训练数据: 将所有基础模型在训练集上生成的 OOF 预测结果作为新的特征集 。原始训练集的标签 作为元模型的标签。
- 训练元模型 (Layer 2): 在 和 上训练元模型(例如,简单的线性模型、树模型、神经网络等)。
- 对测试集进行预测:
- 用所有基础模型对原始测试集进行预测。
- 将所有基础模型在测试集上的预测结果作为新的特征集 。
- 使用训练好的元模型对 进行预测,得到最终的预测结果。
- 在 GBDT/Tree Models 中的应用:
- GBDT/Tree Models (XGBoost, LightGBM, CatBoost) 可以用作强大的基础模型。
- 简单的模型(如 Logistic Regression, Ridge Regression)或 Tree Models 也可以用作元模型。简单的元模型有助于防止过拟合。
- 优缺点:
- 优点: 通常能获得比任何单个基础模型更好的性能,是 Kaggle 比赛等场景中常用的技术。
- 缺点: 过程复杂,需要训练多个模型;训练时间较长;如果基础模型相似或元模型选择不当,可能提升不明显甚至过拟合。
4. 模型混合 (Blending)
模型混合 (Blending) 是一种比 Stacking 更简单的集成技术,也可以用来组合多个模型的预测。它与 Stacking 的主要区别在于,它使用一个单独的保持集 (Hold-out Set) 来生成元模型的训练数据,而不是使用交叉验证。
- 目的 (重点内容): 类似于 Stacking,通过组合多个模型的预测来提高性能,但实现更简单快捷。
- 核心思想: 将一部分数据完全分离出来作为“混合集”,用于训练元模型。
- 过程 (重点内容):
- 数据集划分: 将原始数据集划分为三个不重叠的部分:训练集 (Training Set)、混合集 (Blending Set) 和 测试集 (Test Set)。
- 训练基础模型 (Layer 1): 在训练集上训练所有基础模型。
- 生成元模型训练数据: 用在训练集上训练好的基础模型对混合集进行预测。这些预测结果作为新的特征集 。混合集的标签 作为元模型的标签。
- 训练元模型 (Layer 2): 在 和 上训练元模型。
- 对测试集进行预测:
- 用在训练集上训练好的所有基础模型对测试集进行预测。
- 将所有基础模型在测试集上的预测结果作为新的特征集 。
- 使用训练好的元模型对 进行预测,得到最终的预测结果。
- 在 GBDT/Tree Models 中的应用:
- GBDT/Tree Models (XGBoost, LightGBM, CatBoost) 可以用作强大的基础模型。
- 简单的模型(如 Logistic Regression, Ridge Regression)或 Tree Models 也可以用作元模型。
- 优缺点:
- 优点: 实现简单快捷,避免了 Stacking 中的 OOF 预测计算复杂性;对训练集和混合集有明确的分离,避免了信息泄露。
- 缺点: 基础模型只在训练集上训练,可能没有充分利用所有可用数据;混合集的大小对元模型的训练效果影响很大;容易过拟合到特定的混合集划分。
数据、公式与示例列表 (交叉验证, 网格搜索, Stacking, Blending)
数据与数值:
- k-Fold 交叉验证的折数: (通常取 5 或 10)
- LOOCV 的折数: (样本数量)
- Grid Search: 需要指定参数网格(例如
{'param_name': [value1, value2, ...], ...}) - Stacking: 需要 -fold 交叉验证 (通常 )
- Blending 数据集划分比例: 没有固定比例,常见如 60% 训练,20% 混合,20% 测试。
公式:
-
交叉验证平均分数:
( 是第 轮交叉验证在验证集上的得分)
-
Stacking 元模型输入:
-
Blending 元模型输入:
示例:
-
k-Fold Cross-Validation (Scikit-learn):
1
2
3
4
5
6
7from sklearn.model_selection import cross_val_score, KFold
# model = ... # 你的模型 (e.g., lgb.LGBMClassifier)
# X, y = ... # 数据
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(model, X, y, cv=kf, scoring='accuracy')
print(f"CV Scores: {scores}")
print(f"Mean Accuracy: {scores.mean():.4f}") -
Grid Search with Cross-Validation (Scikit-learn):
1
2
3
4
5
6
7
8from sklearn.model_selection import GridSearchCV
# model = ... # 你的模型
# param_grid = {'param1': [v1, v2], 'param2': [v3, v4]}
# X, y = ... # 数据
grid_search = GridSearchCV(model, param_grid, cv=5, scoring='accuracy', n_jobs=-1)
grid_search.fit(X, y)
print(f"Best Parameters: {grid_search.best_params_}")
print(f"Best Cross-validated Score: {grid_search.best_score_:.4f}") -
Stacking (概念性示例 - 实际实现通常使用更高级库或手动编写):
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 假设 base_models 是一个基础模型列表
# 假设 meta_model 是一个元模型
# 使用 KFold 生成 OOF 预测
# train_meta_features = np.zeros((X_train.shape[0], len(base_models)))
# test_meta_features = np.zeros((X_test.shape[0], len(base_models)))
# for i, model in enumerate(base_models):
# oof_preds = cross_val_predict(model, X_train, y_train, cv=5, method='predict_proba') # 或 predict
# test_preds = model.fit(X_train, y_train).predict_proba(X_test) # 或 predict
# train_meta_features[:, i] = oof_preds[:, 1] # 对于二分类
# test_meta_features[:, i] = test_preds[:, 1] # 对于二分类
# meta_model.fit(train_meta_features, y_train)
# final_predictions = meta_model.predict(test_meta_features)(注意: scikit-learn 提供了
StackingClassifier和StackingRegressor,但需要 Python 3.6+ 和较新版本。) -
Blending (概念性示例 - 实际代码):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# 假设 X_train, X_blend, X_test, y_train, y_blend 是已经划分好的数据
# base_models = [...] # 基础模型列表
# meta_model = ... # 元模型
# # 训练基础模型
# trained_base_models = [model.fit(X_train, y_train) for model in base_models]
# # 生成混合集上的预测 (元模型的训练数据)
# blend_meta_features = np.column_stack([
# model.predict_proba(X_blend)[:, 1] for model in trained_base_models # 二分类
# ])
# # 训练元模型
# meta_model.fit(blend_meta_features, y_blend)
# # 生成测试集上的预测 (元模型的测试数据)
# test_meta_features = np.column_stack([
# model.predict_proba(X_test)[:, 1] for model in trained_base_models # 二分类
# ])
# # 最终预测
# final_predictions = meta_model.predict(test_meta_features)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 Stay hungry. Stay foolish.!
评论
