XGBoost
参考https://mp.weixin.qq.com/s/AnENu0i3i5CdUQkZscMKgQ
XGBoost是boosting算法的其中一种。Boosting算法的思想是将许多弱分类器集成在一起形成一个强分类器。因为XGBoost是一种提升树模型,所以它是将许多树模型集成在一起,形成一个很强的分类器。而所用到的树模型则是CART回归树模型。讲解其原理前,先讲解一下CART回归树。
CART回归树
CART回归树是假设树为二叉树,通过不断将特征进行分裂。比如当前树结点是基于第j个特征值进行分裂的,设该特征值小于s的样本划分为左子树,大于s的样本划分为右子树。
而CART回归树实质上就是在该特征维度对样本空间进行划分,而这种空间划分的优化是一种NP难问题,因此,在决策树模型中是使用启发式方法解决。典型CART回归树产生的目标函数为:
因此,当我们为了求解最优的切分特征j和最优的切分点s,就转化为求解这么一个目标函数:
所以我们只要遍历所有特征的的所有切分点,就能找到最优的切分特征和切分点。最终得到一棵回归树。
XGBoost算法思想
该算法思想就是不断地添加树,不断地进行特征分裂来生长一棵树,每次添加一个树,其实是学习一个新函数,去拟合上次预测的残差。当我们训练完成得到k棵树,我们要预测一个样本的分数,其实就是根据这个样本的特征,在每棵树中会落到对应的一个叶子节点,每个叶子节点就对应一个分数,最后只需要将每棵树对应的分数加起来就是该样本的预测值。
注:w_q(x)为叶子节点q的分数,f(x)为其中一棵回归树
如下图例子,训练出了2棵决策树,小孩的预测分数就是两棵树中小孩所落到的结点的分数相加。爷爷的预测分数同理。
XGBoost原理
XGBoost目标函数定义为:
目标函数由两部分构成,第一部分用来衡量预测分数和真实分数的差距,另一部分则是正则化项。正则化项同样包含两部分,T表示叶子结点的个数,w表示叶子节点的分数。γ可以控制叶子结点的个数,λ可以控制叶子节点的分数不会过大,防止过拟合。yi即为真实值,yi hat为预测值。
正如上文所说,新生成的树是要拟合上次预测的残差的,即当生成t棵树后,预测分数可以写成:
同时,可以将目标函数改写成:
很明显,我们接下来就是要去找到一个f_t能够最小化目标函数。XGBoost的想法是利用其在f_t=0处的泰勒二阶展开近似它。所以,目标函数近似为:
其中g_i为一阶导数,h_i为二阶导数:
由于前t-1棵树的预测分数与y的残差对目标函数优化不影响,可以直接去掉。简化目标函数为:
上式是将每个样本的损失函数值加起来,我们知道,每个样本都最终会落到一个叶子结点中,所以我们可以将所以同一个叶子结点的样本重组起来,过程如下图:
因此通过上式的改写,我们可以将目标函数改写成关于叶子结点分数w的一个一元二次函数,求解最优的w和目标函数值就变得很简单了,直接使用顶点公式即可。因此,最优的w和目标函数公式为
分裂结点算法
在上面的推导中,我们知道了如果我们一棵树的结构确定了,如何求得每个叶子结点的分数。但我们还没介绍如何确定树结构,即每次特征分裂怎么寻找最佳特征,怎么寻找最佳分裂点。
正如上文说到,基于空间切分去构造一颗决策树是一个NP难问题,我们不可能去遍历所有树结构,因此,XGBoost使用了和CART回归树一样的想法,利用贪婪算法,遍历所有特征的所有特征划分点,不同的是使用上式目标函数值作为评价函数。具体做法就是对比分裂后的目标函数值与单子叶子节点的目标函数增益,同时为了限制树生长过深,还加了个阈值,只有当增益大于该阈值才进行分裂。
同时可以设置树的最大深度、当样本权重和小于设定阈值时停止生长去防止过拟合。
Shrinkage and Column Subsampling
XGBoost还提出了两种防止过拟合的方法:Shrinkage and Column Subsampling。
Shrinkage方法就是在每次迭代中对树的每个叶子结点的分数乘上一个缩减权重η,这可以使得每一棵树的影响力不会太大,留下更大的空间给后面生成的树去优化模型。Column Subsampling类似于随机森林中的选取部分特征进行建树。其可分为两种,一种是按层随机采样,在对同一层内每个结点分裂之前,先随机选择一部分特征,然后只需要遍历这部分的特征,来确定最优的分割点。另一种是随机选择特征,建树前随机选择一部分特征然后分裂就只遍历这些特征。一般情况下前者效果更好。
近似算法
对于连续型特征值,当样本数量非常大,该特征取值过多时,遍历所有取值会花费很多时间,且容易过拟合。因此XGBoost思想是对特征进行分桶,即找到l个划分点,将位于相邻分位点之间的样本分在一个桶中。在遍历该特征的时候,只需要遍历各个分位点,从而计算最优划分。从算法伪代码中该流程还可以分为两种,全局的近似是在新生成一棵树之前就对各个特征计算分位点并划分样本,之后在每次分裂过程中都采用近似划分,而局部近似就是在具体的某一次分裂节点的过程中采用近似算法。
针对稀疏矩阵的算法(缺失值处理)
当样本的第i个特征值缺失时,无法利用该特征进行划分时,XGBoost的想法是将该样本分别划分到左结点和右结点,然后计算其增益,哪个大就划分到哪边。
XGBoost的优点
之所以XGBoost可以成为机器学习的大杀器,广泛用于数据科学竞赛和工业界,是因为它有许多优点:
- 使用许多策略去防止过拟合,如:正则化项、Shrinkage and Column Subsampling等。
- 目标函数优化利用了损失函数关于待求函数的二阶导数
- 支持并行化,这是XGBoost的闪光点,虽然树与树之间是串行关系,但是同层级节点可并行。具体的对于某个节点,节点内选择最佳分裂点,候选分裂点计算增益用多线程并行。训练速度快。
- 添加了对稀疏数据的处理。
- 交叉验证,early stop,当预测结果已经很好的时候可以提前停止建树,加快训练速度。
- 支持设置样本权重,该权重体现在一阶导数g和二阶导数h,通过调整权重可以去更加关注一些样本。
百面机器学习的补充 XGBoost的构建过程
假设决策树的结构已知,通过令损失函数相对于wj的导数为0可以求出在最小化损失函数的情况下各个叶子节点上的预测值
然而从所有的树结构中寻找最优树结构是一个NP-hard问题,因此在实际中往往采用贪心法来构建一个次优的树结构,基本思想是从根结点开始,每次对一个叶子节点进行分裂,针对每一种可能的分裂,根据特定的准则选取最优的分裂。XGBoost有特定的准则来选取最优分裂。
将预测值带入到损失函数中可求得损失函数的最小值。
容易计算出分裂前后损失函数的差值。XGBoost采用最大化这个差值作为准则来进行决策树的构建,通过遍历所有特征的所有取值,寻找使得损失函数前后相差最大时对应的分裂方式。此外,由于损失函数前后存在差值一定为正的限制,此时y起到了一定的预剪枝效果。
美团机器学习实践
梯度提升树算法与其他算法的对比如下:
梯度提升树算法与线性模型
梯度提升树可以更好的处理缺失特征和不在同一个区间的特征(年龄特征取值范围为【0,150】,星期几特征取值范围为【0,6】,而转化率特征取值范围为【0,1】),梯度提升树算法也可以更好地应对异常点,更好处理特征间的相关性,处理非线性决策边界的问题。
梯度提升树算法与随机森林
随机森林可以并行训练,较不容易过拟合。梯度提升树可以学习更复杂的决策边界,效果往往会更好。
梯度提升树算法与神经网络
神经网络作为单模型时,参数较多时VC维数也较高,训练较为困难。在中小数据集上,XGBoost可以取得很不错的效果。但是在数据集较大,且选取合适神经网络结构时,神经网络得到的结果往往是更完美的。
XGBoost VS 深度学习
观点1:XGBoost要比深度学习更重要。2016年Kaggle大赛29个获奖方案中,17个用了XGBoost。因为它好用,在很多情况下都更为可靠、灵活,而且准确;在绝大多数的回归和分类问题上,XGBoost的实际表现都是顶尖的.
观点2:针对非常要求准确度的那些问题,XGBoost确实很有优势,同时它的计算特性也很不错。然而,相对于支持向量机、随机森林或深度学习,XGBoost的优势倒也没到那种夸张的程度。特别是当你拥有足够的训练数据,并能找到合适的深度神经网络时,深度学习的效果就明显能好上一大截。
观点3:深度学习和XGBoost并不截然对立(XGBoost发起人-陈天奇博士)。两种方法在其各自擅长领域的性能表现都非常好:
XGBoost专注于模型的可解释性,而基于人工神经网络的深度学习,则更关注模型的准确度。
XGBoost更适用于变量数较少的表格数据,而深度学习则更适用于图像或其他拥有海量变量的数据。
不同的机器学习模型适用于不同类型的任务:
深度神经网络通过对时空位置建模,能够很好地捕获图像、语音、文本等高维数据。
基于树模型的XGBoost则能很好地处理表格数据,同时还拥有一些深度神经网络所没有的特性(如:模型的可解释性、输入数据的不变性、更易于调参等)。
这两类模型都很重要,并广泛用于数据科学竞赛和工业界。我们需要全面理解每一种模型,并能选出最适合你当前任务的那个。XGBoost、深度神经网络与其他经常要用的机器学习算法(如因子分解机、logistic回归分析等),值得机器学习行业的每一位从业者关注。这里没有一药能解百病的说法。
XGBoost为什么要展到二次项
为了可以设置任何可以二阶求导的损失函数,只要该损失函数二阶可导,都可以用泰勒展开式进行近似替代,实现形式上的”统一”