【Kaggle】Intermediate Machine Learning(XGBoost + Data Leakage)

2020-07-13 14:28:22 浏览数 (1)

6. XGBoost

参考:《统计学习方法》提升方法(Boosting)

extreme gradient boosting “梯度提升”是指对损失函数使用梯度下降来确定此新模型中的参数

代码语言:javascript复制
from xgboost import XGBRegressor

my_model = XGBRegressor(n_estimators=500)
my_model.fit(X_train, y_train)

from sklearn.metrics import mean_absolute_error

predictions = my_model.predict(X_valid)
print("Mean Absolute Error: "   str(mean_absolute_error(predictions, y_valid)))

参数调整

XGBoost 具有一些可以极大地影响准确性和训练速度的参数

  • n_estimators :等于我们包含在集合中的模型数量

值太低会导致拟合不足,导致训练数据和测试数据的预测不正确。

值太高会导致拟合过度,导致对训练数据的准确预测,但对测试数据的预测不准确

典型值范围是100-1000,尽管这在很大程度上取决于下面讨论的 learning_rate 参数

  • early_stopping_rounds :提供了一种自动为n_estimators查找理想值的方法。为n_estimators设置一个较高的值,然后使用early_stopping_rounds查找停止迭代的最佳时间是很明智的

设置early_stopping_rounds = 5是一个合理的选择。在这种情况下,连续5轮验证评分下降后停止

当使用early_stopping_rounds时,还需要预留一些数据来计算验证分数,这是通过设置eval_set参数来完成的

代码语言:javascript复制
my_model = XGBRegressor(n_estimators=500)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)],
             verbose=False)
  • learning_rate 与其简单地将每个组件模型的预测相加即可得到预测,还可以在将每个模型的预测相加之前将其乘以一小数(称为学习率)

这意味着添加到集合中的每棵树对我们的帮助都会有所减少

因此,可以为n_estimators设置更高的值而不会过度拟合

如果我们使用 early stopping,则会自动确定适当的 tree 的数量

通常,学习率较高 且 estimators 多,会生成更精确的模型,但迭代次数较多,花费较长时间,默认情况下,XGBoost 设置 learning_rate = 0.1

代码语言:javascript复制
my_model = XGBRegressor(n_estimators=1000, learning_rate=0.05)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)], 
             verbose=False)
  • n_jobs:运行较大数据集,并行更快地构建模型

通常将参数 n_jobs 设置为等于计算机上的内核数

在较小的数据集上,这无济于事

但是,在大型数据集中很有用,否则将花费很长时间在fit命令中等待

代码语言:javascript复制
my_model = XGBRegressor(n_estimators=1000, learning_rate=0.05, n_jobs=4)
my_model.fit(X_train, y_train, 
             early_stopping_rounds=5, 
             eval_set=[(X_valid, y_valid)], 
             verbose=False)

7. Data Leakage 数据泄露

Data Leakage 相关博文

泄漏会导致模型看起来很准确,当开始对模型进行决策为止,然后模型变得非常不准确

泄漏有两种主要类型:目标泄漏 target leakage训练-测试污染train-test contamination

  • 目标泄漏 target leakage

例子:人们得了肺炎后要服用抗生素药物才能康复

原始数据显示这些列之间存在很强的关系,但是在确定got_pneumonia的值后,took_antibiotic_medicine经常更改。这是目标泄漏,因为我们要预测的是 是否会患肺炎,是否吃药是在得了肺炎之后的选择,会不确定,因果关系反了

该模型将发现,对于took_antibiotic_medicine值为False的任何人都没有肺炎。由于验证数据与训练数据来自同一来源,模型将具有很高的验证(或交叉验证)分数

但是,此模型随后在现实世界中部署时将非常不准确,因为有些患有肺炎的患者也不会接受抗生素治疗

为防止此类数据泄漏,应当将该特征数据排除

  • 训练-测试污染 Train-Test Contamination

验证旨在衡量模型如何处理之前未考虑过的数据

例如,在调用train_test_split()之前进行了预处理(例如 fitting an Imputer)。模型可能会获得良好的验证评分,但是在部署模型进行决策时却表现不佳

将验证数据或测试数据中的数据合并到了如何进行预测中,因此即使无法将其推广到新数据,该方法也可能会对特定数据表现良好。当执行更复杂的特征工程时,此问题变得更加微妙(更加危险)

例子:信用卡

没有信用卡的人 —> 100%没有消费支出

有信用卡的人 —> 2%的人,没有消费记录

根据此特征来预测是否会发放信用卡申请,正确率98%

但是有部分持有信用卡的人可能平时没有消费,并且统计出来的费用是这张申请的信用卡的消费,还是申请这张信用卡之前的消费呢?这些都不是很清楚,这就可能造成很大偏差

所以这种可能造成很大偏差的特征要弃用,或者非常谨慎

代码语言:javascript复制
# Drop leaky predictors from dataset
potential_leaks = ['expenditure', 'share', 'active', 'majorcards']
X2 = X.drop(potential_leaks, axis=1)

# Evaluate the model with leaky predictors removed
cv_scores = cross_val_score(my_pipeline, X2, y, 
                            cv=5,
                            scoring='accuracy')

print("Cross-val accuracy: %f" % cv_scores.mean())

总结:

  • 仔细分离训练和验证数据可以防止Train-Test Contamination,并且Pipeline可以帮助实现这种分离
  • 谨慎,常识和数据探索相结合可以帮助识别target leakage
  • 思考数据泄露问题,本质上需要考虑特征产生的时间顺序: 如果该特征在你做出类型判断之前可以确定,那么就可以作为类型判断的依据; 如果该特征必须在你做出类型判断之后才可以确定,那么就不可以作为类型判断的依据,否则就是因果倒置

0 人点赞