点击获取AI摘要

交叉验证与模型堆叠混合

1. 交叉验证 (Cross-Validation)

交叉验证是一种用于评估模型性能和鲁棒性的技术。它通过将数据集划分为多个子集,并在不同的子集组合上进行训练和验证,从而更可靠地估计模型在未知数据上的表现。

  • 目的 (重点内容):
    • 更准确地评估模型泛化能力: 避免模型评估结果对特定训练/测试集划分的依赖。
    • 防止过拟合评估集: 在模型开发和调参过程中,如果反复使用同一验证集来评估和调整模型,模型可能会“记住”验证集的特征,导致在真正的未知数据上性能下降。交叉验证通过使用不同的验证集来减轻这个问题。
    • 充分利用数据: 在数据集较小的情况下,交叉验证可以确保所有数据都用于训练和验证。
  • 基本思想:
    1. 将整个数据集随机分成 kk 个互斥的子集(称为“折”或“folds”)。
    2. 进行 kk 轮训练和验证:
      • 每一轮,选择其中一个子集作为验证集,剩下的 k1k-1 个子集作为训练集。
      • 在训练集上训练模型。
      • 在验证集上评估模型性能。
    3. 最终的模型性能评估是 kk 轮验证结果的平均值。
  • 常用类型 (重点内容):
    • k-Fold Cross-Validation: 将数据集分成 kk 等份。最常用。
    • Stratified k-Fold Cross-Validation: 在分类问题中,确保每一折中的类别分布与整个数据集的类别分布大致相同。对于不平衡数据集尤其重要。
    • Leave-One-Out Cross-Validation (LOOCV): kk 等于样本数量 nn。每一轮用 n1n-1 个样本训练,1个样本验证。计算量巨大,适用于极小数据集。
    • Group K-Fold: 根据样本的分组进行划分,确保同一组的样本不会同时出现在训练集和验证集中(例如,患者 ID)。用于避免数据泄露。
  • 在 GBDT/Tree Models 中的应用:
    • 模型评估: 使用交叉验证来获取模型性能的平均分数和标准差,作为模型泛化能力的估计。
    • 超参数调优: 与网格搜索、随机搜索等结合使用,在交叉验证的每一折上评估一组超参数的效果,选择平均性能最好的参数组合。
    • 早期停止 (Early Stopping): 在 GBDT 的训练过程中,通常会在训练时提供一个单独的验证集(或在交叉验证中使用某一折作为验证集),监控模型在该验证集上的性能,如果连续多轮性能没有提升,则提前停止训练。这是防止过拟合的重要手段。XGBoost 的 cv 函数,以及 XGBoost, LightGBM, CatBoost 的 fit 方法中,都可以指定 eval_setearly_stopping_rounds/callbacks 来实现。

网格搜索是一种超参数优化技术。它通过在预先指定的超参数值网格中进行穷举搜索,找到在指定评估标准下性能最好的参数组合。

  • 目的 (重点内容): 寻找模型的最佳超参数组合,以最大化模型在未知数据上的性能。
  • 基本思想:
    1. 定义一个字典,指定要调优的超参数名称以及每个参数要尝试的值列表。
    2. 网格搜索会生成所有可能的超参数组合。
    3. 对于每个超参数组合,使用交叉验证(通常是 k-fold CV)来评估模型性能。
    4. 选择在交叉验证中平均性能最好的超参数组合。
  • 与交叉验证结合 (重点内容):
    • 网格搜索通常与交叉验证一起使用。例如,在使用 scikit-learn 的 GridSearchCV 时,它会自动对参数网格中的每个组合进行交叉验证。
    • 在每一折交叉验证中,模型都在该折的训练集上训练,并在对应的验证集上评估。
    • 最终选择的参数是使交叉验证平均得分最高的那个组合。
  • 在 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) 是一种集成学习技术,它结合了多个不同模型(称为基础模型或第一层模型)的预测,然后使用另一个模型(称为元模型或第二层模型)来学习如何最佳地组合这些预测。

  • 目的 (重点内容): 通过结合多个模型来提高预测性能,特别是当基础模型具有不同的优势和劣势时。
  • 核心思想: 使用基础模型的预测作为新的特征,训练一个元模型来做出最终预测。
  • 过程 (重点内容):
    1. 训练集划分: 将原始训练集划分为两部分(例如,使用交叉验证)。
    2. 训练基础模型 (Layer 1):
      • 对原始训练集使用 kk-fold 交叉验证。
      • 在每一折中,用 k1k-1 折的数据训练基础模型(例如,XGBoost, Logistic Regression, SVM 等)。
      • 用训练好的模型对剩余的 1 折数据进行预测(这部分数据在训练当前模型时是未见过的)。
      • 重复 kk 次,将所有折的预测结果拼接起来,得到与原始训练集大小相同的“out-of-fold (OOF) 预测”数据集。这些 OOF 预测将作为元模型的训练数据。
      • (可选)在整个原始训练集上训练基础模型,用于对测试集进行预测。
    3. 生成元模型训练数据: 将所有基础模型在训练集上生成的 OOF 预测结果作为新的特征集 Xmeta_trainX_{\mathrm{meta\_train}}。原始训练集的标签 ytrainy_{\mathrm{train}} 作为元模型的标签。
    4. 训练元模型 (Layer 2):Xmeta_trainX_{\mathrm{meta\_train}}ytrainy_{\mathrm{train}} 上训练元模型(例如,简单的线性模型、树模型、神经网络等)。
    5. 对测试集进行预测:
      • 用所有基础模型对原始测试集进行预测。
      • 将所有基础模型在测试集上的预测结果作为新的特征集 Xmeta_testX_{\mathrm{meta\_test}}
      • 使用训练好的元模型对 Xmeta_testX_{\mathrm{meta\_test}} 进行预测,得到最终的预测结果。
  • 在 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,通过组合多个模型的预测来提高性能,但实现更简单快捷。
  • 核心思想: 将一部分数据完全分离出来作为“混合集”,用于训练元模型。
  • 过程 (重点内容):
    1. 数据集划分: 将原始数据集划分为三个不重叠的部分:训练集 (Training Set)、混合集 (Blending Set) 和 测试集 (Test Set)。
    2. 训练基础模型 (Layer 1):训练集上训练所有基础模型。
    3. 生成元模型训练数据: 用在训练集上训练好的基础模型对混合集进行预测。这些预测结果作为新的特征集 Xmeta_blendX_{\mathrm{meta\_blend}}。混合集的标签 yblendy_{\text{blend}} 作为元模型的标签。
    4. 训练元模型 (Layer 2):Xmeta_blendX_{\mathrm{meta\_blend}}yblendy_{\mathrm{blend}} 上训练元模型。
    5. 对测试集进行预测:
      • 用在训练集上训练好的所有基础模型对测试集进行预测。
      • 将所有基础模型在测试集上的预测结果作为新的特征集 Xmeta_testX_{\mathrm{meta\_test}}
      • 使用训练好的元模型对 Xmeta_testX_{\mathrm{meta\_test}} 进行预测,得到最终的预测结果。
  • 在 GBDT/Tree Models 中的应用:
    • GBDT/Tree Models (XGBoost, LightGBM, CatBoost) 可以用作强大的基础模型
    • 简单的模型(如 Logistic Regression, Ridge Regression)或 Tree Models 也可以用作元模型
  • 优缺点:
    • 优点: 实现简单快捷,避免了 Stacking 中的 OOF 预测计算复杂性;对训练集和混合集有明确的分离,避免了信息泄露。
    • 缺点: 基础模型只在训练集上训练,可能没有充分利用所有可用数据;混合集的大小对元模型的训练效果影响很大;容易过拟合到特定的混合集划分。

数据、公式与示例列表 (交叉验证, 网格搜索, Stacking, Blending)

数据与数值:

  • k-Fold 交叉验证的折数: kk (通常取 5 或 10)
  • LOOCV 的折数: nn (样本数量)
  • Grid Search: 需要指定参数网格(例如 {'param_name': [value1, value2, ...], ...}
  • Stacking: 需要 kk-fold 交叉验证 (通常 k5k \ge 5)
  • Blending 数据集划分比例: 没有固定比例,常见如 60% 训练,20% 混合,20% 测试。

公式:

  • 交叉验证平均分数:

    AvgScore=1ki=1kScorei\text{AvgScore} = \frac{1}{k} \sum_{i=1}^k \text{Score}_i

    (Scorei\text{Score}_i 是第 ii 轮交叉验证在验证集上的得分)

  • Stacking 元模型输入:

    Xmeta=[PredictionBaseModel1,PredictionBaseModel2,]X_{\text{meta}} = [\text{Prediction}_{\text{BaseModel}_1}, \text{Prediction}_{\text{BaseModel}_2}, \dots]

  • Blending 元模型输入:

    Xmeta_blend=[PredictionBaseModel1(BlendingSet),PredictionBaseModel2(BlendingSet),]X_{\mathrm{meta\_blend}} = [\mathrm{Prediction}_{\mathrm{BaseModel}_1}(\mathrm{BlendingSet}), \mathrm{Prediction}_{\mathrm{BaseModel}_2}(\mathrm{BlendingSet}), \dots]

示例:

  • k-Fold Cross-Validation (Scikit-learn):

    1
    2
    3
    4
    5
    6
    7
    from 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
    8
    from 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 提供了 StackingClassifierStackingRegressor,但需要 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)