机器学习算法(六)XGBoost算法

集成学习方法简介

XGBoost 是一种 Boosting 方法,而 Boosting 方法又是集成学习的一个分支。

集成学习是机器学习领域的一个重要的分支,它不是一种具体的算法,而是一种“兄弟同心,其利断金”的思想。主要分为两种重要的方法:BaggingBoosting 。它们都是通过某种策略把多个弱学习器组合起来,形成一个具有很高预测准确率的强学习算法。

Bagging 方法

Bagging 即套袋法,其算法过程如下:

  1. 从原始样本集中抽取训练集。每轮从原始样本集中使用 Bootstraping 的方法抽取 n 个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行 k 轮抽取,得到 k 个训练集(k 个训练集之间是相互独立的)。
  2. 每次使用一个训练集得到一个模型,k 个训练集共得到 k 个模型(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等)。
  3. 对分类问题:将上步得到的 k 个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果(所有模型的重要性相同)。

Boosting 方法

提升(Boosting)是集成学习方法里的一个重要方法,其主要思想是将弱分类器组装成一个强分类器。在 PAC(概率近似正确)学习框架下,则一定可以将弱分类器组装成一个强分类器。

关于 Boosting 的两个核心问题:

  1. 通过提高那些在前一轮被弱分类器分错样例的权值,减小前一轮分对样例的权值,来使得分类器对误分的数据有较好的效果。
  2. 通过加法模型将弱分类器进行线性组合,比如 AdaBoost 通过加权多数表决的方式,即增大错误率小的分类器的权值,同时减小错误率较大的分类器的权值。

而提升树通过拟合残差的方式逐步减小残差,将每一步生成的模型叠加得到最终模型。

提升树模型

提升方法实际采用的是加法模型(即基函数的线性组合)与前向分步算法。而以决策树为基函数的提升方法称为提升树(Boosting Tree)。对分类问题,决策树是二叉分类树,对回归问题决策树是二叉回归树。提升树模型可以表示为决策树的加法模型:
image.png

image.png
是当前模型拟合数据的残差(Residual)。因此,对回归树的提升算法而言,只需要简单的拟合当前模型的残差。这样使得算法过程变得十分简单,形式化的过程描述如下:
image.png

XGBoost 原理详解

image.png
XGBoost 的目标函数
image.png
下面我们来一同学习一下 XGBoost 是如何学习的。
image.png
泰勒展开式近似损失函数
image.png
image.png
正则化项的处理
目标函数中正则化项存在的原因是为了限制模型的复杂度,让模型在训练集上能够取得较好的结果的前提下尽可能地简单。而前面我们也提到了,在 XGBoost 中,对于采用前向分布方法一步步迭代的优化时,我们模型的复杂度就是当前要定义的决策树的复杂度。

决策树函数的定义
为此,我们首先重新定义树:我们将树定义为一个该树中所有叶子节点的值的向量。并且,每个叶子的索引映射函数映射实例到每个叶子节点上:

定义决策树的复杂度
image.png

新目标函数的优化
image.png
image.png

至此,对于第 t 轮的一颗已经分裂好的决策树,我们能够求出其对应的最小化的目标函数。但是到目前为止,到底如何进行分裂我们还不知道具体的做法,接下来让我们一起学习 XGBoost 是如何寻找分裂点的。

构建决策树
决策树的生成策略
image.png

寻找最优分裂点

image.png

离散型类别变量的处理

传统的 GBDT 算法对连续型变量和离散型变量是进行分开处理的。例如 Spark 中的 GBDT 就是这样的,当我们的实例特征中有离散型变量的时候,就需要通过参数指定该离散型变量的种类,这样使得算法的用户友好性变得十分的糟糕。

而 XGBoost 在设计时就考虑到了这一点。实际上,我们不需要将离散型特征变量进行分开处理,XGBoost 使用 one-hot 编码的方式对离散型变量进行处理。
image.png
image.png
image.png

XGBoost 算法流程
XGBoost 中的提升树算法形式化的描述过程如下:
image.png

XGBoost 的优缺点

XGBoost 的优点

1.正则化

XGBoost 在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的 score 的 L2 模的平方和。从 Bias-variancetradeoff 角度来讲,正则项降低了模型的 variance,使学习出来的模型更加简单,防止过拟合,这也是 XGBoost 优于传统 GBDT 的一个特性。

2.并行处理

XGBoost 工具支持并行。Boosting 不是一种串行的结构吗?怎么并行的?注意 XGBoost 的并行不是 tree 粒度的并行,XGBoost 也是一次迭代完才能进行下一次迭代的(第 t 次迭代的代价函数里包含了前面 t-1 次迭代的预测值)。XGBoost 的并行是在特征粒度上的。

我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),XGBoost 在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个 block 结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。

3.灵活性

XGBoost 支持用户自定义目标函数和评估函数,只要目标函数二阶可导就行。

4.缺失值的处理

对于特征的值有缺失的样本,XGBoost 可以自动学习出它的分裂方向。

5.剪枝

XGBoost 先从顶到底建立所有可以建立的子树,再从底到顶反向进行剪枝。比起 GBM,这样不容易陷入局部最优解。

6.内置交叉验证

XGBoost 允许在每一轮 Boosting 迭代中使用交叉验证。因此,可以方便地获得最优 Boosting 迭代次数。而 GBM 使用网格搜索,只能检测有限个值。

缺点或不足

1.算法参数过多

调参复杂,需要对 XGBoost 原理十分清楚才能很好的使用 XGBoost。

2.只适合处理结构化数据

相对于深度学习算法来说,XGBoost 算法只适合处理结构化的特征数据,而对于类似图像中的目标检测等任务重的非结构化数据没有很好的处理能力。

3.不适合处理超高维特征数据

XGBoost 算法对于中低维数据具有很好的处理速度和精度,但是对于例如大规模图像物体识别,或者是推荐算法的某些场景中会出现的超高维特征的数据就无能为力了,这时候我们就需要借助于深度学习等算法。

XGBoost 实战

from sklearn.datasets import load_iris
import xgboost as xgb
from xgboost import plot_importance
from matplotlib import pyplot as plt
from sklearn.model_selection import train_test_split

# read in the iris data
iris = load_iris()

X = iris.data
y = iris.target

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

# 训练模型
model = xgb.XGBClassifier(max_depth=5, learning_rate=0.1, n_estimators=160, silent=True, objective='multi:softmax')
model.fit(X_train, y_train)

# 对测试集进行预测
ans = model.predict(X_test)

# 计算准确率
cnt1 = 0
cnt2 = 0
for i in range(len(y_test)):
    if ans[i] == y_test[i]:
        cnt1 += 1
    else:
        cnt2 += 1

print("Accuracy: %.2f %% " % (100 * cnt1 / (cnt1 + cnt2)))

# 显示重要特征
plot_importance(model)
plt.show()

运行结果

Accuracy: 100.00 % 

猜你喜欢

转载自blog.csdn.net/datawhale/article/details/81207641