我正在使用评估集来实现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
因此,在这种情况下,在培训期间,我获得的MAPE为8.5%,在将模型应用于同一测试集时,我的MAPE接近9%。
正如我在具有更大且更复杂数据集的其他示例中所说的那样,差异可能更大,例如41%对58%。
这里有两个不同的问题。一个小:您对XGB培训和外部评估功能的定义略有不同(XGB评估中的分母中有+1
)。一个更重要的问题是:默认情况下,xgboost
(与lightgbm
相比)使用 All 训练的树来计算预测,而不是最佳的树。为了获得最佳的树木数量,请使用y_pred = xgb_model_mpg.predict(mpg_test_X, ntree_limit=xgb_model_mpg.best_ntree_limit)