XGBoost训练过程中的ROC AUC值与最终结果不符。

6

我正在使用XGBoost训练BDT模型,对22个特征进行二元分类。我有1800万个样本(60%用于训练,40%用于测试)。

在训练过程中,我得到的ROC AUC值与最终结果不符,我不明白为什么会出现这种情况。此外,ROC AUC指标表现出比其他任何指标更多的过度拟合,并且在测试数据上似乎有一个最大值。

是否有人之前遇到过类似的问题,或者有任何想法可以找出我的模型存在的问题,或者如何找出问题所在?

我的代码核心内容:

params = {
 "model_params": {
    "n_estimators": 2000,
    "max_depth": 4,
    "learning_rate": 0.1,
    "scale_pos_weight": 11.986832275943744,
    "objective": "binary:logistic",
    "tree_method": "hist"
  },
  "train_params": {
    "eval_metric": [
      "logloss",
      "error",
      "auc",
      "aucpr",
      "map"
    ]
  }
}

model = xgb.XGBClassifier(**params["model_params"], use_label_encoder=False)
model.fit(X_train, y_train, 
          eval_set=[(X_train, y_train), (X_test, y_test)], 
          **params["train_params"])

train_history = model.evals_result()

...

plt.plot(iterations, train_history["validation_0"]["auc"], label="training data")
plt.plot(iterations, train_history["validation_1"]["auc"], label="test data")

...

y_pred_proba_train = model.predict_proba(X_train)
y_pred_proba_test = model.predict_proba(X_test)

fpr_test, tpr_test, _ = sklearn.metrics.roc_curve(y_test, y_pred_proba_test[:, 1])
fpr_train, tpr_train, _ = sklearn.metrics.roc_curve(y_train, y_pred_proba_train[:, 1])

auc_test = sklearn.metrics.auc(fpr_test, tpr_test)
auc_train = sklearn.metrics.auc(fpr_train, tpr_train)

...

plt.title(f"ROC curve, AUC=(test: {auc_test:.4f}, train: {auc_train:.4f})")
plt.plot(fpr_test, tpr_test, label="test data")
plt.plot(fpr_train, tpr_train, label="train data")

...


scikit-learn 默认采用宏平均AUC,而我不确定xgboost采用什么方法,但我猜测它采用微平均。你的数据集是否不平衡?这可能是原因,特别是如果你的测试集没有分层。 - eschibli
我刚刚测试了一下。我手动使用roc_curve + auc,得到的结果与使用roc_auc_scoremacroweightedNone得到的结果相同。然而,使用micro计算的roc_auc_score在训练和测试数据上得到了较低的分数,为0.71。我不认为这是正确的,但这是一个有趣的观察!samples计算起来需要太长时间。 - Nico G.
回答你的问题:我的数据集是不平衡的,比例为12:1(类别:0、1)。我使用了sklearn.model_selection.train_test_split进行分层抽样。 - Nico G.
你是在集群上训练吗?XGBoost会对每个节点的auc进行平均。 - eschibli
是的,我正在使用具有多个 CPU 的服务器进行训练。我不明白你的意思,你能提供一个进一步阅读的链接或者在回答中解释一下吗?这听起来像一个很有前途的解释。 - Nico G.
文档中有说明(按cntl-f查找“auc”)- AUC独立计算分配给每个节点的样本,然后取平均值。 - eschibli
2个回答

1
当提供验证集时,XGBoost可能会在使用scikit-learn API进行预测时使用具有最佳验证度量(在您的情况下为map)的迭代的模型状态,但这在文档中不是很清楚。
您没有做错任何事情;当允许训练多个迭代时,GBT过度拟合是完全正常的。
编辑:这并不能解释它;根据更新的原始帖子,验证map在每次迭代中都得到了改善。

“with the best validation metric”是什么意思?我的担心在于,最终模型仅表现出轻微过拟合,但训练历史显示出明显的过拟合。测试数据上的AUC值更高,而训练数据上的AUC值较低。 - Nico G.
您的模型将使用在显示最佳验证“map”(您提供的最后一个指标)的迭代中的模型状态。这大约是在第40次迭代时,在您的图表中可以看到验证auc的峰值,训练和验证auc与您稍后进行的测试相匹配。由于您继续进行了额外的1960次迭代,训练历史记录显示出明显的过拟合,但由于验证指标没有改善,您的模型在预测时使用了在过拟合之前的第40次迭代的状态。 - eschibli
我认为这不是真的。model.best_iteration 返回 1999,而 map 历史记录在迭代 <100 时并没有达到峰值。(我已经将其添加到帖子中)此外,训练后得到的 AUC 分数与训练期间的 AUC 分数非常不同,即使在迭代 ~40 时也是如此。或者我错过了什么?无论如何感谢!我之前不知道大部分内容。 - Nico G.
另外,我没有使用早停技术。 - Nico G.

0

在集群上进行训练时,XGBoost会将 AUC计算(使用ctrl-f查找“auc”)作为每个节点的宏平均值。特别是考虑到您的类别不平衡,我怀疑这可能是罪魁祸首。


也不是这样的。我只是在一台CPU上进行了训练,结果基本相同。而且,我现在认为我正在使用的服务器并不能算作分布式环境。 - Nico G.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接