xgboost 文档有误吗? (早期停止轮次以及最佳和最后一次迭代)

Is the xgboost documentation wrong ? (early stopping rounds and best and last iteration)

下面是关于 xgboost 提前停止回合参数的问题,以及它如何提供或不提供最佳迭代,这是拟合结束的原因。

在 xgboost 文档中,可以在 scikit learn api 部分 (link) 中看到,当拟合因提前停止回合参数而停止时:

Activates early stopping. Validation error needs to decrease at least every "early_stopping_rounds" round(s) to continue training. Requires at least one item in evals. If there’s more than one, will use the last. Returns the model from the last iteration (not the best one).

读这个的时候,似乎模型 returned,在这种情况下,不是最好的,而是最后一个。它说,要在预测时访问最好的一个,可以使用 ntree_limit 参数调用预测,并在拟合结束时给出 bst.best_ntree_limit。

从这个意义上说,它应该与 xgboost 的火车一样工作,因为 scikitlearn api 的拟合似乎只是火车和其他火车的嵌入。

这里讨论得很激烈 or here 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

如果拟合有 return 最后一次迭代而不是最好的迭代,它应该给出 1.93803 左右的 rmse,但它给出的 rmse 为 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 的拟合,当被早期停止轮参数停止时,确实给出了最好的 iter,而不是最后一个。

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

感谢关注

你那里有一个代码错误。

请注意

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 个助推器。

我觉得,没有错,但是不一致

predict 方法的文档是正确的(例如,参见 here). To bee 100% sure it is better to look into the code: xgb github,因此 predict 的行为与文档中所述一致,但 fit 文档已过时. 拜托,post 它是 XGB github 上的一个问题,他们要么修复文档,要么你将成为 XGB 的贡献者:)

更准确地说,根据@Mykhailo Lisovyi,scikit-learn api 部分中的文档非常不一致,因为合适的段落告诉我们,当发生早期停止回合时,返回最后一次迭代不是最好的,但是预测段落告诉我们,当在没有指定 ntree_limit 的情况下调用预测时,ntree_limit 等于 best_ntree_limit.

因此,在读取fit部分时,可能会认为在调用predict时需要指定best iter是什么,但是在读取predict部分时,则默认给出了best iter,即如果需要,您必须指定的最后一个 iter。

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

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