我正在使用一个评估集来实现Python中xgboost的早期停止。让我感到困惑的是,在培训期间报告的最佳评估指标比我在用于评估目的的集合上使用相同模型进行预测时获得的评估指标要好得多。
为了清楚起见,我使用了一个带有玩具数据集的可重现的例子。在这种情况下,差异不是很大,尽管仍然很重要。然而,在我实际使用的数据集的情况下,差距更大。
代码如下:
import xgboost as xgb
import seaborn as sns
def xgb_mape(preds, dtrain):
labels = dtrain.get_label()
return('mape', np.mean(np.abs((labels - preds) / (labels+1))))
mpg = sns.load_dataset('mpg')
mpg = mpg.sample(frac = 1)
n = int(mpg.shape[0] * 0.7)
mpg_train = mpg.iloc[:n, :7]
mpg_test = mpg.iloc[n:, :7]
mpg_train_y = mpg_train.iloc[:, 0].values
mpg_test_y = mpg_test.iloc[:, 0].values
mpg_train_X = mpg_train.iloc[:, 1:].values
mpg_test_X = mpg_test.iloc[:, 1:].values
xgb_model_mpg = xgb.XGBRegressor(max_depth= 10, learning_rate=0.1, n_estimators=1000, silent=True, \
objective='reg:linear',\
booster='gbtree', subsample= 0.6, colsample_bytree= 0.9, colsample_bylevel= 1, reg_lambda= 20 ,\
random_state=1 , seed= 1, importance_type='gain')
xgb_model_mpg.fit(mpg_train_X ,mpg_train_y , eval_set= [(mpg_test_X , mpg_test_y )], eval_metric= xgb_mape,\
early_stopping_rounds= 20)
[...]
82] validation_0-rmse:3.41167 validation_0-mape:0.085761
[83] validation_0-rmse:3.40828 validation_0-mape:0.085618
[84] validation_0-rmse:3.40087 validation_0-mape:0.085519
[85] validation_0-rmse:3.403 validation_0-mape:0.085631
[86] validation_0-rmse:3.39977 validation_0-mape:0.085711
[87] validation_0-rmse:3.39626 validation_0-mape:0.085739
[88] validation_0-rmse:3.40048 validation_0-mape:0.085727
[89] validation_0-rmse:3.40356 validation_0-mape:0.085883
[90] validation_0-rmse:3.40341 validation_0-mape:0.085664
Stopping. Best iteration:
[70] validation_0-rmse:3.42186 validation_0-mape:0.085076
XGBRegressor(base_score=0.5, booster='gbtree', colsample_bylevel=1,
colsample_bytree=0.9, gamma=0, importance_type='gain',
learning_rate=0.1, max_delta_step=0, max_depth=10,
min_child_weight=1, missing=None, n_estimators=1000, n_jobs=1,
nthread=None, objective='reg:linear', random_state=1, reg_alpha=0,
reg_lambda=20, scale_pos_weight=1, seed=1, silent=True,
subsample=0.6)
y_pred = xgb_model_mpg.predict(mpg_test_X)
results = pd.DataFrame({'actual':mpg_test_y, 'predictions' : y_pred})
results['Absolute_Percent_Error'] = 100 * np.abs(results['actual'] - results['predictions'])/results['actual']
MAPE = results['Absolute_Percent_Error'].mean()
MAPE
8.982732737486339
所以在这种情况下,在训练期间我获得了8.5%的MAP,并且当将模型应用于相同的测试集时,我得到接近9%的MAP。
正如我在其他更大和更复杂的数据集的例子中所说,差异可能会大得多,例如41%对58%。
这里有两个不同的问题。一个小:你对xgb训练和外面的评估函数的定义略有不同(在xgb评估的分母中有+1
)。一个更重要的问题:xgboost
(与lightgbm
相反)默认情况下使用所有受过训练的树而不是最佳树数来计算预测。要在预测中获得最佳树数,请使用y_pred = xgb_model_mpg.predict(mpg_test_X, ntree_limit=xgb_model_mpg.best_ntree_limit)