xgboost文档错误吗? (尽早停止回合以及最佳和最后一次迭代)

时间:2018-11-26 14:49:29

标签: python machine-learning scikit-learn xgboost

以下是有关xgboost早期停止回合参数的问题,当它是拟合结束的原因时,它如何执行或不执行最佳迭代。

在xgboost文档中,您可以在scikit学习api部分(link)中看到由于提前停止回合参数而使拟合停止时:

  

激活提前停止。验证错误至少需要减少每个“ early_stopping_rounds”回合才能继续训练。评估中至少需要一项。如果有多个,则使用最后一个。返回上一次迭代的模型(不是最佳迭代)。

在进行此操作时,返回的模型似乎不是最好的模型,而是最后一个模型。它表示,要在预测时获得最佳预测,可以使用ntree_limit参数并在拟合结束时给出bst.best_ntree_limit来调用预测。

从这个意义上讲,它应该与xgboost火车的工作方式相同,因为scikitlearn api的合适性似乎只是火车和其他火车的嵌入。

这里stack overflow discussion或这里another discussion

进行了讨论。

但是,当我尝试解决此问题并检查它如何与我的数据一起使用时,我没有找到我认为应该具有的行为。实际上,我所遇到的行为根本不是那些讨论和文档中描述的行为。

我这样称呼健身:

reg = xgb.XGBRegressor(n_jobs = 6,n_estimators = 100,max_depth = 5)

reg.fit(
   X_train, 
   y_train, 
   eval_metric='rmse',    
   eval_set=[(X_train, y_train), (X_valid, y_valid)],
   verbose=True,
   early_stopping_rounds = 6)

这是我最后得到的:

[71]    validation_0-rmse:1.70071   validation_1-rmse:1.9382
[72]    validation_0-rmse:1.69806   validation_1-rmse:1.93825
[73]    validation_0-rmse:1.69732   validation_1-rmse:1.93803
Stopping. Best iteration:
[67]    validation_0-rmse:1.70768   validation_1-rmse:1.93734

当我检查所使用的验证值时:

y_pred_valid = reg.predict(X_valid)
y_pred_valid_df = pd.DataFrame(y_pred_valid)
sqrt(mse(y_valid, y_pred_valid_df[0]))

我明白了

  

1.9373418403889535

如果拟合返回的是最后一次迭代而不是最佳迭代,则应该给出均方根值1.93803,但均方根值为1.93734,恰好是最佳分数。

我通过两种方式再次检查: [编辑]我已经根据@Eran Moshe的答案编辑了以下代码

y_pred_valid = reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)
y_pred_valid_df = pd.DataFrame(y_pred_valid)
sqrt(mse(y_valid, y_pred_valid_df[0]))
  

1.9373418403889535

即使我只用68个估算器来进行拟合(知道最好的迭代器是第67个),也可以确保最后一个是最好的:

reg = xgb.XGBRegressor(n_jobs=6, n_estimators = 68, max_depth= 5)

reg.fit(
   X_train, 
   y_train, 
   eval_metric='rmse',    
   eval_set=[(X_train, y_train), (X_valid, y_valid)],
   verbose=True,
   early_stopping_rounds = 6)

结果相同:

  

1.9373418403889535

因此,这似乎导致了这样一个想法,即与文档以及有关它的大量讨论不同,xgboost的拟合在被早期停止回合参数停止时确实给出了最佳迭代,而不是最后一个

我错了吗?如果错了,那么在哪里以及如何解释我遇到的行为?

感谢您的关注

3 个答案:

答案 0 :(得分:1)

我认为,这没错,但是不一致

predict方法的文档是正确的(例如,参见here)。要百分百确定,最好查看以下代码:xgb github,因此predict的行为与文档中所述相同,但是fit文档已过时。请把它作为问题发布到XGB github上,或者他们将修复文档,或者您将成为XGB贡献者:)

答案 1 :(得分:0)

您那里有一个代码错误。

注意如何

reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)

应该是

y_pred_valid = reg.predict(X_valid, ntree_limit=reg.best_ntree_limit)

实际上,您在进行计算时会进行相同的比较

sqrt(mse(y_valid, y_pred_valid_df[0]))

Xgboost的运行方式与您阅读的相同。 early_stopping_round = x将继续训练,直到连续x为止没有改善。

使用ntree_limit=y进行预测时,只会使用前y个增强器。

答案 2 :(得分:0)

更准确地说,与@Mykhailo Lisovyi相对应,该文档在scikit-learn api部分中非常不一致,因为fit段落告诉您,当发生早期停止回合时,返回的不是最佳迭代,而是返回最佳迭代。预测段告诉您,在未指定ntree_limit的情况下调用预测时,ntree_limit等于best_ntree_limit。

因此,当阅读拟合部分时,可能会认为需要在调用预测时指定最佳迭代,但是在阅读预测部分时,默认情况下会给出最佳迭代,它是最后一个您必须指定是否需要这样做。

我在xgboost的github上发布了一个问题。...等等,看

[UPDATE]:拉取请求已被接受:link