Boosting Ensembles完整指南
在理解Boosting Ensembles之前,最好先了解集成(Ensembles)是什么,让我们从了解集成开始。
Ensembles - 简介
在机器学习中,集成是将多个模型(称为基础学习者)一起使用以形成单个预测模型的模型。
但是,当我们的机器学习算法起了惊人的作用时,那么问题来了
为什么集成比单个机器学习模型好?为什么集成能够最大限度地减少误差呢??? 为什么明显的弱基础学习者与类似的基础学习者能形成强大的集成呢?
为了回答这些“ 为什么 ”并理解集成,我试着用日常生活的例子来构建它的解释,然后使用数学,并在python中实现,以理解集成技术背后的概念。
考虑David想要尝试一个新落成的餐厅吃晚餐,但在去之前他想对那个地方有一点了解,因此决定查看一下餐馆的评论。
对餐厅的评价
为什么集成比单个模型好?
现在考虑David想要做出决定,基于单一的评价——无论是正面的还是负面的——他并没有完全信服于这个地方,但是当他通过多次评价时,他会对这个地方有一点信心。
以非常相似的方式,集成可以被认为是相对较强的,因为单个分类器的决策可能是可疑的,但通过许多类似的决策,数据科学家可以对机器的输出更有信心。
为什么集成能够最大限度地减少误差呢???
维恩图显示了团队决策如何减少错误
假设有人强烈推荐餐厅,但相信单一评论有点困难,因为没有什么是完美的,简而言之,只查看一次评论就会产生一些偏见。
现在相反David所做的是他检查了多个评论,现在他可以更好地判断这个地方,有一个具体的理由可以去或不去。
这就是集成学习试图实现的目标,即不是相信单个算法或单个机器学习模型,而是集合了多个算法的平均结果 - 听起来很简单但是集成是解决问题的一种出色方法。
为什么明显的弱基础学习者与类似的基础学习者能形成强大的集成呢?
对于几乎所有人来说,回答这个问题都很容易,但是让我试着通过上面的例子来解释,David不仅要检查的许多评论工作,他还应该确保他得到各种评论。如果所有评论者都是中国美食爱好者,或者如果人们尝试了一些饮料,但喜欢这种氛围,那么即使是一组评论者有偏见,他们也有多种可能。另一方面,如果评论者尝试各种食物,有不同的口味等,那么肯定会使评论成为决定餐厅的有力工具。
这就是每个领域都想要的东西,研究问题并从每个可能的方面将其可视化,使得合奏超级有用。在合奏而不是与类似的基础学习者或具有几乎相似的超参数的情况下,通常更好地选择各种基础学习者。
现在,它的一种或多种方式的明显集合优于其他机器学习算法。现在是时候了解提升类型的集成及其各种变体。
Boosting- 介绍
Boosting,也称为sequential ensemble,是使用几个依赖于彼此的弱基础学习者组合形成一个强学习者的形式。这是一种迭代技术,我们在训练数据上启动模型构建,然后以这样的方式构建第二个模型,即它尝试减少第一个模型的误差,然后第三个尝试减少第二个模型误差,依此类推。
如图所示,当输入被假设错误分类时,其权重会增加,以便下一个假设更有可能对其进行正确分类。通过将整个集合结合起来,将弱学习者转化为表现更好的机器学习模型。
由于基础学习者的迭代加法,提升模型容易过度,因此其低方差和高偏差模型可用作boosting ensembles的基础学习者。
再次定义boosting,boosting可以被认为是高偏差,低方差模型(如低深度决策树)的组合,因为增强可以减少模型中的方差而不影响其偏差。
算法
梯度提升决策树(GBDT)
GBDT是一种可以使用scikit-learn轻松实现的提升型集成技术之一。除了所有boosting特征外,scikit-learn还在GBDT中提供行采样,使其成为超强的算法。
根据上述算法,GBDT的最终函数可以如下给出:
这个函数的问题现在是模型开始过度拟合作为基础学习者的加法聚合,因此为了减少过度拟合,我们在这个等式中引入了学习率。
这种学习率的作用是通过学习率时间缩小每棵树的贡献,因此借助于学习率和基础学习者之间的权衡,可以避免模型的过度拟合。
现在我们剩下两个主要的超参数:
- k即基础学习者(决策树)数量
- v即学习率
我们可以计算简单的交叉验证技术来找到超参数的最佳值。
在模型中,树的深度对过拟合影响较大,通常单个树的深度为2、3、4或最大值5。超过5个会导致模型过拟合。
GBDT不仅容易过拟合,而且有更多的局限性:
GBDT被认为是一个缓慢的过程,对于大型数据集,与其他机器学习算法相比,它通常需要很长时间。
GBDT(或其他提升算法)中的并行化任务也是不可能的。
但这一切都归功于XGBoost的另一种提升算法,该算法具有GBDT的所有优点并克服了其时间复杂性限制。
为了实现GBDT,我们可以参考sklearn文档。
Extreme gradient boosting(XGBoost)
XGBoost在GBDT中进行了一些调整,即
Scikit-learn GBDT可进行行采样,但不能方便列采样技术。在不影响模型性能的前提下,列采样fasten GBDT。在XGBoost中,我们可以获得GBDT的所有好处以及列取样技术。
实现
与其他机器学习算法不同,XGBoost到目前为止还不是sklearn的一部分,但我们可以从Python Package Index(PyPI)提供的预构建binary wheel安装XGboost。
用于分类
from sklearn.model_selection import RandomizedSearchCV from xgboost import XGBClassifier as xgbc from scipy import stats classifier = xgbc(random_state = 0) tuned_param = {'n_estimators': [x for x in range(1,101,10) ], 'learning_rate': stats.uniform(0.0095, 0.15)} model = RandomizedSearchCV(classifier , tuned_param, scoring = 'f1' , n_iter = 15 , cv =3) model.fit(X_train , y_train) print(model.best_estimator_)
对于回归
from sklearn.model_selection import RandomizedSearchCV from xgboost import XGBRegressor as xgbr from scipy import stats regressor = xgbr(random_state = 0) tuned_param = {'n_estimators': [x for x in range(1,101,10) ], 'learning_rate': stats.uniform(0.0095, 0.15)} model = RandomizedSearchCV(regressor , tuned_param, scoring = 'explained_variance' , n_iter = 15 , cv =3) model.fit(X_train , y_train) print(model.best_estimator_)
在XGBoost中,learning_rate,max_depth,n_estimators是最常用作超参数的参数。
- learning_rate - 对于XGBoost,学习率可用于为新添加的树设置权重,这是用于管理过度拟合和欠拟合之间权衡的重要超参数。
- max_depth - 树的最大深度。
- n_estimators - 基础学习者数量。
解释
构建一个模型,应用不同的机器学习算法只需要2-3行代码更改,更重要的是解释模型如何训练及其结果。
解释是一个两阶段过程,第一阶段是模型解释,第二阶段是结果解释。
特征重要性图:
特征重要性图是描述特征相对重要性最简单的方法。这幅图展示了不同的特征如何在决策中起作用。
有时候,只针对最重要的特征的训练模型会提供更好的结果。
以上以重要性类型作为权重生成的图,我们也可以使用其他重要性类型来完全确定相对特征的重要性。
三种特征重要性类型是:
- Weight。使用特征在所有树中拆分数据的次数。
- Cover。使用特征对所有树中的数据进行拆分的次数,该数据通过经过这些拆分的训练数据点的数量加权。
- Gain。使用特征进行拆分时平均减少的训练损失。
不同important_type的XGBoost特征重要性图比较
在python中实现特征重要性图
import xgboost def plot_importance(importance_type): xgboost.plot_importance(model_1, importance_type =importance_type, title = 'Feature importance plot with type = ' + importance_type) imp_type = ['weight' , 'gain', 'cover'] for type_ in imp_type: plot_importance(type_)
特征重要性图是多么准确???
好图终归是好图,不管模型是什么,不管我们使用什么超参数值。因此,如果一个图是独立于超参数的,那么使用的算法可以把它称为好图,我们可以依赖它。
考虑下面的图,
在这里我们可以说它们在特征重要性的绝对值上存在一些差异,但相对特征重要性对于所有图都是相同的,因此我们可以完全信任地依赖于上述特征重要性。
用于测试python中的特征重要性图的代码
def fi_plot_comp(base, depth): col = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare'] model = xgbc(learning_rate = 0.1, max_depth = depth , n_estimators = base) model.fit(X_train, y_train) plt.figure(figsize=(4,3)) index = np.arange(len(col)) plt.bar(index, model.feature_importances_) plt.xlabel('Features', fontsize=10) plt.ylabel('Relative importance', fontsize=10) plt.xticks(index, col, fontsize=10, rotation=90) plt.title('feature imp plot for xgboost when max_depth = ' + str(depth) + ' & #estimators= ' + str(base)) plt.show() for x in [50,100]: for y in [3,4]: fi_plot_comp(x,y)
特征影响图 - SHAP值图
该图对于可视化非常有用:
- 如何使用不同的特征为测试数据生成输出。
- 协作预测中每个特征对其成功有多大贡献。
特征影响图可以以两种格式显示:
- (a)分布格式
- (b)条形图格式
比较上述两种格式,分布图似乎更具信息性,这与对输出的特征影响一起说明了不同特征的权重如何分布,关于特征方差。
SHAP值(SHapley Additive exPlanation)
- SHAP值衡量模型中每个特征在任一类(正面或负面)中的成功贡献程度。
SHAP值图-分布格式在python中的实现
import shap import xgboost explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) shap.summary_plot(shap_values, X_test)
SHAP值图的实现 - python中的条形图格式
shap.summary_plot(shap_values, X_test, plot_type="bar")
测试样本解释图
下面是两个测试样本的结果,第一个模型预测1,第二个模型预测0。
考虑分布图,它清楚地告诉特征1和特征0在决定类标签为1时占主导地位,而所有其他特征没有贡献太多。我们可以从条形图中描绘类似的东西。
分布图给出了一个附加信息,即它的特征重要性,它告诉哪个类某个特征正在推动测试样本。
类似地,从标签“0”分布图,其明确的特征1在决定类标签中占主导地位,特征0和特征2也做出了一些贡献,并且沿着剩余特征做出的贡献几乎可以忽略不计。
测试样本图的实现 - 在python中的分布格式
import shap import xgboost explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) test_id = 5 shap.summary_plot(shap_values[test_id:test_id+1], X_test[test_id:test_id+1,:])
测试样本图的实现 - python中的条形图格式
shap.summary_plot(shap_values[test_id:test_id+1], X_test[test_id:test_id+1,:], plot_type="bar")
结论
集成通常会提供一些很好的结果,在集成中,boosting 更受数据科学家的欢迎,但由于其可解释性较低,人们会放弃它。但是Boosting ensembles可以有相应的可视化方式。