决策树

325 阅读18分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战 决策树-GBDT, Xgboost,LGBM 阴天快乐 阴天快乐 我是旧时代的残党,新时代没有能载我的船。 ​关注他 69 人赞同了该文章 序言:今天系统整理下CART, GBDT, XGBoot, lightGBM. 1.CART(分类和回归树) classification and regression tree. CART结构为二叉树. 1.1 回归树 平方误差最小化,分裂节点。 给定训练集 [公式] 采用启发式搜索,选择第 [公式] 个特征 [公式] 和它取的值 [公式] ,分别作为切分特征和切分点,并将划分的结果分为两个区域: [公式] 和 [公式] 然后寻找最优切分特征 [公式] 和最优切分点 [公式] ,即求解: [公式] 因为最小二乘法,区域 [公式] 最优值即标签 [公式] 的均值: [公式] ,其中 [公式] 遍历所有的切分变量和切分点,可以找到最优的切分变量和切分点,构成对 [公式] ,然后对每个区域重复上述过程,直到满足停止条件。 回归树生成后,将输入空间划分为 [公式] 个单元 [公式] ,即 [公式] 个叶子节点,每个单元 [公式] 都有一个固定的输出值 [公式] ,回归模型可以表示为: [公式] (注意:这里即表示输出 [公式] 对应单元 [公式] 的 [公式] ,为什么用求和符号呢,其实就是数学上表示的问题,意思是逐渐遍历 [公式] 个单元,判断其属于哪一个 [公式] ) 1.2 分类树 基尼指数(Gini Index),分裂节点。 假设分布有 [公式] 类,样本点属于第 [公式] 类的概率为 [公式] ,则概率分布定义的基尼指数为: [公式] 给定样本集合D,其基尼指数为: [公式] 这里, [公式] 是 [公式] 中属于第 [公式] 类的样本子集, [公式] 是类的个数。 如果样本集合 [公式] 根据特征 [公式] 是否取某一可能值 [公式] 被分割成 [公式] 和 [公式] 两部分,即 [公式] 则在特征 [公式] 的条件下,集合 [公式] 的基尼指数定义为: [公式] 基尼指数越大,样本集合的不确定性越大。 在所有可能的特征 [公式] 以及它们所有可能的切分点 [公式] 中,选择基尼指数最小的特征即其对应的切分点作为最优特征和最优切分点,从而从当前节点分裂成两个子结点,将训练数据集依特征分配到两个子结点中去,重复分裂过程直至满足停止条件。 1.3 CART树剪枝 (挺重要的,回头补) 2.Boosting Decision Tree(提升树) 提升树算法:拟合残差 (1) 初始化 [公式] (2) 对于 [公式] (a) 计算残差 [公式] (b) 拟合残差 [公式] 学习一个回归树,得到 [公式] (c) 更新 [公式] (3) 得到回归问题的提升树 [公式] 上式 [公式] 为决策树编号, [公式] 为决策树的数量, [公式] 为样本编号, [公式] 为样本数量。 提升树算法中,假设前一轮得到的强学习器是 [公式] 损失函数是 [公式] 本轮迭代的目标是找到一个弱学习器 [公式] 最小化本轮的损失 [公式] 当采用平方损失函数时 [公式] 这里, [公式] 即 [公式] 是当前模型拟合数据的残差(residual),所有提升树只需要单纯拟合模型的残差。 梯度提升树算法,利用损失函数的负梯度作为提升树算法中残差的近似值。 第 [公式] 轮的第 [公式] 个样本的损失函数负梯度为: [公式] 不同的损失函数会得到不同的负梯度,如果选择平方损失 [公式] 则负梯度为 [公式] 即此时GBDT的负梯度就是残差,即要拟合的就是残差。 3.GBDT(梯度提升树) gbdt使用的决策树为CART回归树,因为gbdt每次迭代要拟合的是梯度值,是连续值。 GBDT算法: (1) 初始化弱学习器 [公式] (2) 对 [公式] 有: (a)对每个样本 [公式] ,计算负梯度,即残差 [公式] (b) 将上一步得到的残差作为样本新的真实值,并将数据 [公式] 作为下棵树的训练数据,得到一颗新的回归树 [公式] ,其对应的叶子节点区域为 [公式] 其中 [公式] 为回归树 [公式] 的叶子节点个数。 (c) 对叶子区域 [公式] 计算最佳拟合值 [公式] (d) 更新强学习器 [公式] (3) 得到最终学习器 [公式] 4.Xgboost(极端梯度提升) 4.1目标函数 [公式] 个弱学习器结果相加,得到输出结果。 [公式] [公式] 为第 [公式] 个样本的预测结果, [公式] 为第 [公式] 个弱学习器。 最小化正则化的目标函数: [公式] 第t轮迭代的目标函数为: [公式] [公式] 是第t-1轮模型给出的预测值,为常数。 二阶泰勒公式展开: [公式] 对 [公式] 使用二阶泰勒公司近似,将 [公式] 视为 [公式] , [公式] 视为 [公式] ,得到 [公式] 其中 [公式]为一阶导, [公式] 为二阶导,求导 [公式] 是对 [公式] 进行求导,即: [公式] 由于第 [公式] 轮时, [公式] 和 [公式] 为常数,其对函数优化不会产生影响,所以目标函数可以写成: [公式] 定义 [公式] 为叶子节点 [公式] 的样本集合,目标函数从叶子节点角度,写成: [公式] 为了简化表达式,记 [公式] , [公式] ,则目标函数为: [公式] 在第 [公式] 轮时, [公式] 为已知结果,即常数。目标函数对 [公式] 求一阶导,并令导数为0,可以得到最优的解 [公式] . [公式] 所以,目标函数可以化简为: [公式] [公式] 可以作为决策树结构的评分函数(scoring function),是由目标函数派生得到。该值越小,树结构越好。 使用贪心算法生长树,从单一的叶子节点开始,递归的产生分支。 假设加入分裂后, [公式] 和 [公式] 分别为左节点和右节点上的样本集合,有 [公式] 。 上面得到的评分函数为: [公式] 分裂前分数为: [公式] 分裂后的分数为: [公式] 分裂前的分数,减去分裂前的分数,得到: [公式] 上式为分裂增益,节点分裂需要最大化增益,该式用来作为分裂评估准则。 4.2 Shrinkage and Column Subsampling Xgboost防止过拟合的方法:正则化,shrinkage和column (feature) subsampling. shrinkage: Shrinkage scales newly added weights by a factor [公式] after each step of tree boosting.Similar to a learning rate in tochastic optimization, shrinkage reduces the influence of each individual tree and leaves space for future trees to improve the model. 即对每一轮学习的结果乘以因子 [公式] 进行缩放,就像梯度下降的学习率,降低单棵树的影响,为后面生成的树留下提升模型性能的空间。 column subsampling:像随机森林那样,对列进行抽样(也支持行抽样)。既能防止过拟合,又能减少计算量,加速并行算法的计算。 4.3 最优切分点发现算法 find the best split。xgboost支持两种分裂节点的方法:贪心算法和近似算法。 1)贪心算法 从深度为 0 的树开始,对每个叶节点枚举所有的可用特征; 针对每个特征,把属于该节点的训练样本根据该特征值进行升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的分裂收益; 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,在该节点上分裂出左右两个新的叶节点,并为每个新节点关联对应的样本集 回到第 1 步,递归执行到满足特定条件为止 收益计算为上面推导的公式: [公式] 为什么需要对样本根据特征值进行排序呢? In order to do so efficiently, the algorithm must first sort the data according to feature values and visit the data in sorted order to accumulate the gradient statistics for the structure score in Eq7. 为了更高效地枚举所有分割方案.(比如样本在某特征为6,3,7,8,2,那么我们分割点取x,需要对每个样本进行判断是否大于x,然后决定分配到左节点还是右节点。而排序后,样本特征为2,3,6,7,8,则直接知道,x左边的分配到左结点,右边的分配到右节点。这样只需要从左到右一遍线性扫描即可。) 比如我们要枚举所有 x < a 这样的条件,对于某个特定的分割点 a 我们要计算 a 左边和右边的导数和。 我们可以发现对于所有的分裂点 a,我们只要做一遍从左到右的扫描就可以枚举出所有分割的梯度和 [公式] 和 [公式] 。然后用上面的公式计算每个分割方案的分数就可以了。 2)近似算法 贪婪算法可以的到最优解,但当数据量太大时则无法读入内存进行计算,近似算法主要针对贪婪算法这一缺点给出了近似最优解。 该算法会首先根据特征分布的分位数提出候选划分点,然后将连续型特征映射到由这些候选点划分的桶中,然后汇总统计信息找到所有区间的最佳分裂点。 在提出候选切分点时有两种策略: Global:学习每棵树前就提出候选切分点,并在每次分裂时都采用这种分割; Local:每次分裂前将重新提出候选切分点。 Global策略计算步骤更少,而因为节点划分后没有重新调整(refine)候选点,因此需要更多的候选点。 Local策略因为每次分割后对候选点进行调整,所以可能更加适合深一点的树。 Local 策略需要更多的计算步骤,而 Global 策略因为节点没有划分所以需要更多的候选点。 eps 为近似算法的精度,其倒数为桶的数量。Global 策略在候选点数多时(eps 小)可以和 Local 策略在候选点少时(eps 大)具有相似的精度。此外我们还发现,在 eps 取值合理的情况下,分位数策略可以获得与贪婪算法相同的精度。 3)稀疏感知算法 数据缺失的处理: 本身在节点分类时不考虑特征缺失样本的数值。缺失值数据会被分到左子树和右子树分别计算损失,选择增益大的划分方式。如果训练中没有数据损失,预测时出现了数据损失,那么默认被分类到右子树。 4) 用于并行学习列块(column block) 决策树的学习最耗时的一个步骤就是在每次寻找最佳分裂点是都需要对特征的值进行排序。而 XGBoost 在训练之前对根据特征对数据进行了排序,然后保存到块结构中,并在每个块结构中都采用了稀疏矩阵存储格式(Compressed Sparse Columns Format,CSC)进行存储,后面的训练过程中会重复地使用块结构,可以大大减小计算量。 每一个块结构包括一个或多个已经排序好的特征; 缺失特征值将不进行排序; 每个特征会存储指向样本梯度统计值的索引,方便计算一阶导和二阶导数值 这种块结构存储的特征之间相互独立,方便计算机进行并行计算。在对节点进行分裂时需要选择增益最大的特征作为分裂,这时各个特征的增益计算可以同时进行,这也是 Xgboost 能够实现分布式或者多线程计算的原因。 其他如缓存访问设计、用于额外计算块等细节略。 5.lightGBM(轻量级的高效梯度提升树) 决策树学习的两种方法: leaf-wise learning:a. choose a leaf with max delta loss. b. split it into 2 leaves.即不断寻找分裂后收益最大的叶子节点,将其分裂成两个节点,从而生长决策树。(生长过程是顺序的,不方便加速) level-wise learning: split all leaves into 2 leaves. 按层生长,不需要每次去挑选节点,在每一个level中各个节点的分裂可以并行完成。(但是会产生很多没有必要的分裂,有更多的计算代价。) LightGBM的改进: 直方图算法 xgboost采用预排序的方法,计算过程中则是按照feature value的排序,逐个数据样本计算当前feature value的分裂收益。这样能够精确找到最佳分裂点。 lightGBM采用直方图算法,将连续的特征离散化为 k 个离散特征,同时构造一个宽度为 k 的直方图用于统计信息(含有 k 个 bin)。利用直方图算法我们无需遍历数据,只需要遍历 k 个 bin 即可找到最佳分裂点。 使用直方图优化的好处: 降低内存的使用。Xgboost按照feature value对数据排序,用32位整型去存储排序后的索引值,32位整型去存储特征值,而lightgbm只需要8位去存储分桶后的bin value,内存下降了1/8. 降低计算代价。计算特征分裂增益时,XGBoost 需要遍历一次数据找到最佳分裂点,而 LightGBM 只需要遍历一次 k 次,直接将时间复杂度从 O(#data * #feature) 降低到 O(k * #feature) ,而我们知道 #data >> k 。 带深度限制的leaf-wise算法 XGBoost 采用 Level-wise 的增长策略,方便并行计算每一层的分裂节点,提高了训练速度,但同时也因为节点增益过小增加了很多不必要的分裂,降低了计算量;LightGBM 采用 Leaf-wise 的增长策略减少了计算量,配合最大深度的限制防止过拟合,由于每次都需要计算增益最大的节点,所以无法并行分裂。 直方图的差加速 在构建叶节点的直方图时,我们还可以通过父节点的直方图与相邻叶节点的直方图相减的方式构建,从而减少了一半的计算量。在实际操作过程中,我们还可以先计算直方图小的叶子节点,然后利用直方图作差来获得直方图大的叶子节点。可以达到2倍加速的效果。 提升cache命中率 xgboost对cache优化不够好。在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。 基于直方图的算法简单的提高cache命中率。 所有的feature采用相同方法访问梯度(区别于不同特征通过不同的索引获得梯度),只需要对梯度进行一次重新排序,所有特征能够连续地访问梯度。不需要使用行索引到叶子索引的数组。 数据量很大的时候,相对于随机访问,顺序访问能够提升速度4倍以上。这个速度的差异基本上是由cache miss所带来的。 直接支持类别特征作为输入 经过实验,直接使用类别特征比one-hot特征速度快8倍以上。 支持并行 特征并行 传统的特征并行算法在于对数据进行垂直划分,然后使用不同机器找到不同特征的最优分裂点,基于通信整合得到最佳划分点,然后基于通信告知其他机器划分结果。传统的特征并行方法有个很大的缺点:需要告知每台机器最终划分结果,增加了额外的复杂度(因为对数据进行垂直划分,每台机器所含数据不同,划分结果需要通过通信告知)。 LightGBM 则不进行数据垂直划分,每台机器都有训练集完整数据,在得到最佳划分方案后可在本地执行划分而减少了不必要的通信。传统的特征并行算法在于对数据进行垂直划分,然后使用不同机器找到不同特征的最优分裂点,基于通信整合得到最佳划分点,然后基于通信告知其他机器划分结果。传统的特征并行方法有个很大的缺点:需要告知每台机器最终划分结果,增加了额外的复杂度(因为对数据进行垂直划分,每台机器所含数据不同,划分结果需要通过通信告知)。 LightGBM 则不进行数据垂直划分,每台机器都有训练集完整数据,在得到最佳划分方案后可在本地执行划分而减少了不必要的通信。 数据并行 传统的数据并行策略主要为水平划分数据,然后本地构建直方图并整合成全局直方图,最后在全局直方图中找出最佳划分点。 这种数据划分有一个很大的缺点:通讯开销过大。如果使用点对点通信,一台机器的通讯开销大约为 O(#machine * #feature *#bin ) ;如果使用集成的通信,则通讯开销为 O(2 * #feature *#bin ) 。 LightGBM 采用分散规约(Reduce scatter)的方式将直方图整合的任务分摊到不同机器上,从而降低通信代价,并通过直方图做差进一步降低不同机器间的通信。 投票并行 针对数据量特别大特征也特别多的情况下,可以采用投票并行。投票并行主要针对数据并行时数据合并的通信代价比较大的瓶颈进行优化,其通过投票的方式只合并部分特征的直方图从而达到降低通信量的目的。大致步骤为两步: 本地找出 Top K 特征,并基于投票筛选出可能是最优分割点的特征; 合并时只合并每个机器选出来的特征。 5.面试问题总结 5.1 XGBoost的优点和缺点: 优点: 精度高:GBDT 只用到一阶泰勒展开,而 XGBoost 对损失函数进行了二阶泰勒展开。引入二阶导一方面是为了增加精度,另一方面也是为了能够自定义损失函数。 灵活性更强:传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这时xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。 正则化:在目标函数中加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、叶子节点权重的 L2 范式。正则项降低了模型的方差,使学习出来的模型更加简单,有助于防止过拟合。 Shrinkage:相当于学习速率。XGBoost 在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间 列抽样:借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算; 缺失值处理:对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。 可以并行化操作:块结构可以很好的支持并行计算。 可并行的近似直方图算法:树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。 相当于预剪枝:当增益大于阈值时才让节点分裂,上式中的gamma即阈值,它是正则项里叶子节点数T的系数,所以xgboost在优化目标函数的同时相当于做了预剪枝。 缺点: 节点分类需要遍历数据集:虽然利用预排序和近似算法可以降低寻找最佳分裂点的计算量,但在节点分裂过程中仍需要遍历数据集; 预排序空间复杂度高:预排序过程的空间复杂度过高,不仅需要存储特征值,还需要存储特征对应样本的梯度统计值的索引,相当于消耗了两倍的内存。 找到特别精确的分割点,可能存在过拟合。 5.2 XGBoost和lightGBM怎么调参 5.2.1 XGBoost (1) XGBoost重要参数 xgboost主要分为三类参数: 1.通用参数 general parameter booster: 每次迭代的模型选择,gbtree或者gbliner silent: 控制打印信息,(过时,被verbosity代替) nthread:并行的线程数,默认使用最大的核数 2.Booster参数:Parameters for Tree Booster eta: shinkage防止过拟合,默认0.3 gamma:公式中叶子节点个数的参数,也就是分类后损失函数的增益,增益大于这个阈值,才会对节点进行分裂。 max_depth:默认为0,树的最大深度,用来避免过拟合。 min_child_weight: 最小的叶子节点样本权重和,如果节点分裂造成一个叶子节点的样本权重和小于该值,则放弃分裂。 max_delta_step: 该参数仙子每棵树权重改变的最大步长。一般用不到,但是在数据样本极度不平衡时,可能对逻辑回归有帮助。 subsample:训练样本随机采样的比例。 colsample_bytree, colsample_bylevel, colsample_bynode: 列采样的参数设置。bytree表示在构建每棵树的时候使用。bylevel表示构建每层节点的时候使用,bynode在每次分裂的时候使用。 lambda: L2正则化项。默认为1. alpha:L1的正则化项. scale_pos_weight: 控制正负样本的平衡,用于不平衡数据。 3.学习任务参数:控制训练目标的表现 objective:定义损失函数。常用值有binary:logistic; multi:softmax; multi:softprob eval_metic: 验证集的评估指标。rmse, mae, logloss, error, merror, mlogloss, auc seed:随机数的种子,设置它可以复现随机数的结果,也可以用于调整参数。 (2) XGBoost调参技巧 a.当出现过拟合时,有两类参数可以缓解: 第一类参数:用于直接控制模型的复杂度。包括max_depth, min_child_weight, gamma等参数 第二类参数:用于增加随机性,从而使得模型在训练时对于噪声不敏感,包括subsample, colsample_bytree. 也可以直接检查步长eta,此时需要增加num_round参数. b.当遇到数据不平衡时(如广告点击率预测任务),有两种方式提高模型的预测性能: 如果关心的是预测的AUC. 可以通过scale_pos_weight参数来平衡正负样本的权重; 使用AUC来评估。 如果关心的是预测的正确率 不能重新平衡正负样本;设置max_delta_step为一个有限的值(如1),从而有助于收敛 5.2.2 lightGBM: (1)lightGBM重要参数: (2)lightGBM调参技巧: 针对更快的训练速度: 通过设置bagging_fraction和bagging_feq参数来使用Bagging方法 通过设置feature_fraction参数来使用特征抽样 使用较小的max_bin 使用save_binary将数据保存为二进制文件,来加速数据加载 使用parallel learning 针对更好的准确率: 使用较小的learning_rate和较大的num_iterations. 使用更大的num_leaves(可能导致过拟合) 使用较大的max_bin(学习速度可能变慢) 使用更大的训练数据集 尝试dart-训练时候是有用dropout 交叉验证 缓解过拟合: 使用较小的max_bin (分桶粗一些) small num_leaves (不要在单棵树上分的太细) 使用min_datai_in_leaf和min_sum_hessian_in_leaf(确保叶子节点还有足够多的数据) 通过bagging_fractontion和bagging_freq来使用bagging 通过featrure_fration来使用特征抽样 使用更大的训练数据 使用lambda_l1,,lambda_l2和min_gain_to_split来使用正则 尝试使用max_depth来避免使用过深的树. 参考论文: [1] CART: Classification and regression trees (参考李航博士的《统计学习方法》) [2] gbdt : Greedy Function Approximate : A Gradient Boosting Machine statweb.stanford.edu/~jhf/ftp/tr… [3] xgboost : XGBoost: A Scalable Tree Boosting System arxiv.org/pdf/1603.02… [4] lightGBM : LightGBM: A Highly Efficient Gradient Boosting Decision Tree papers.nips.cc/paper/6907-… [5] lightGBM : www.bilibili.com/video/av474… [6] 阿泽:zhuanlan.zhihu.com/p/87885678 [7] lightGBM博客:www.cnblogs.com/jiangxinyan… [8] XGBoost document:xgboost.readthedocs.io/en/latest/p… [9] LightGBM document: lightgbm.readthedocs.io/en/latest/P… 编辑于 2019-11-14 决策树 梯度提升 机器学习 ​赞同 69​ ​3 条评论 ​分享 ​喜欢 ​收藏 ​申请转载 ​ 赞同 69 ​ 分享 文章被以下专栏收录 算法笔记 算法笔记 推荐阅读 决策树系列--从决策树到LightGBM 0. 模型简述1. 特征选择1.1 信息增益1.2 信息增益比 2 决策树的生成2.1 ID3算法2.2 ID3算发的缺陷2.3 C4.5算法2.4 C4.5与ID3树的不足与思考 3 决策树的剪枝4 CART算法4.1 CART生成 5 GBDT模… 刘佳 【机器学习】决策树(下)——XGBoost、LightGBM(非常详细) 【机器学习】决策树(下)——XGBoost、LightGBM(非常详细) 阿泽 发表于机器学习算... 再从GBDT到XGBoost! 再从GBDT到XGBoost! 挂枝儿 发表于好好学习天... 从决策树、GBDT到XGBoost/lightGBM/CatBoost 决策树如下图,对于给定一组样本数据X及其加标Y,根据相应算法(如Cart)生成一颗回归树(树的生成详情不在此展开); 2. GBDT 对于上图中的样本数据X及其加标Y,生成的回归树定义为T1,T1… Frank Cao 3 条评论 ​切换为时间排序 写下你的评论... 发布 hhh hhh04-05 梯度提升树 解释的好清楚! ​赞 ​回复 ​踩 ​ 举报 roy young roy young03-03 想请问您,lightgbm 采用rf的话是CART回归树换成了random forest 了吗? ​赞 ​回复 ​踩 ​ 举报 简单聊 简单聊2020-12-21 工程化的部分讲的很好 ​赞 ​回复 ​踩 ​ 举报 选择语言