最近在准备秋招,所以先将一些问题理一遍。主要借鉴了以下文章。
目录
xgboost 和 random forest 的相同和差异
xgboost 原理
xgboost 是一种boosting的集成算法,是对gbdt模型的一种改进。gbdt也是一种boosting集成算法,采用前向分布算法进行贪婪的学习,每次迭代都生成一颗cart树来拟合前t-1棵树的预测结果和真实结果之间的残差,所有树的预测结果之和作为最后的预测结果。
xgboost在gbdt的基础上,对损失函数进行了二阶泰勒展开,在目标函数中加入了正则项,支持并行化处理和处理缺失值等。核心思想没有变化,只是在扩展性、精确性和训练速度上进行了改进。
xgboost 和GBDT有什么不同?
- 基学习器:不管是分类还是回归,gbdt的基学习器都是CART回归树,而xgboost既可以用CART数作为基学习器,也可以用线性分类器,相当于加入正则化项的线性回归或者逻辑回归。
- 损失函数:GBDT的损失函数只用了一阶导数信息,xgboost则对gbdt的损失函数进行了二阶泰勒展开,支持一阶可导和二阶可导的损失函数,也支持自定义损失函数。
- 正则化:xgboost在目标函数中加入了正则化项,相当于剪枝,防止过拟合。
- 列抽样:xgboost类似随机森林,对列进行列抽样,用于防止过拟合。
- 行采样:gbdt每次计算使用所有样本,而xgboost允许行抽样,即每次建树只取一部分样本。
- 缺失值处理:xgboost对缺失值有自己的处理逻辑。
- 并行化:特征维度的并行,对每个特征中的值进行预排序,再存储为block,分裂节点时可以多线程并行计算每个特征的最佳分裂点,极大提升了训练速度。
xgboost为什么使用泰勒二阶展开
- 可扩展性:不仅支持一阶可导损失函数,也支持二阶可导损失函数,支持损失函数自定义,只要是满足一阶可导或者二阶可导;
- 精确性:二阶展开更接近于真实的损失函数
xgboost是如何防止过拟合的
- 加入了正则化项,对叶子结点的数目和叶子结点的权重大小进行限制,降低模型复杂度。
- 列抽样,每次只取一部分特征进行训练
- 行采样,每轮计算可以不使用全部样本
-
shrinkage: 可以叫学习率或步长,对于每次学习到的树权重,都乘以系数来降低这个权重,为了给后面的训练留出更多的学习空间
如何解决xgboost的过拟合(注意和上面这个问题区分)
- 控制模型复杂度
- 限制树深: max_depth
- 越大越容易过拟合
- 调整正则项系数:gamma,alpha,lambda
- gamma: 控制叶子节点数量的系数,它规定了分裂叶子节点的最小损失函数下降值,只有分裂后损失下降大于等于这个数才能分裂。gamma越大模型越保守。
- alpha: L1正则化项,用在高维数据中用于加快速度
- lambda:L2正则化项,用于防止过拟合
- 限制叶子节点样本数量:min_child_weight
- 最小叶子节点样本权重和,当它值较大时,避免学习到局部的特殊样本。但是值过高也会导致欠拟合,需要通过交叉验证来调整。
- 限制树深: max_depth
- 增加随机性使得模型对噪声鲁棒
- 调整学习率eta
- 通过减少每一步的权重提高鲁棒性
- 控制随机抽样比例
- subsample:随机样本采样的比例,越大越容易过拟合,但是太小也会欠拟合
- colsample_bytree:特征随机选择的比例。
- 调整学习率eta
- 早停
xgboost如何处理缺失值
xgboost是允许缺失值的存在的。
xgboost在对列寻找分割点时,不会遍历所有样本,而是跳过这列特征为缺失值的样本,只对这列特征没有缺失值的样本进行遍历,在高维稀疏的数据中能大大缩短遍历时间。
具体在实现过程中,当遇见缺失值,则将缺失值的样本分别放在左子树和右子树进行计算,最后放入增益较大的一边。当训练集没有缺失值而测试集有缺失值时,则默认放入右子树。
xgboost如何实现并行化
xgboost对每个特征按特征值对样本进行预排序,再存储为block,可以使用多线程并行查找每个特征的最优分割点。
xgboost 和 random forest 的相同和差异
相同:
- xgboost和随机森林都是以决策树作为基学习器
- 都有列抽样,即随机选择部分特征进行计算
不同:
- xgboost是boosting算法,基学习器具有强依赖关系,模型进行加权求和,最终的结果由每棵树的预测结果相加得到,而随机森林是bagging算法,模型之间不存在依赖关系,而是相互并列的,最终结果是对每棵树的结果投票法或者求平均值得到。
- 随机森林对异常值不敏感,xgboost对异常值敏感
- 随机森林是基于cart树,当用于回归则回归树,分类则分类树;xgboost不管是分类还是回归都用分类树;
xgboost如何调参
- eta:学习速率,用来控制每次学习的权重缩减,为后面的模型提供更多的学习空间
- gamma:正则化中控制叶子节点数量复杂度的系数,越大叶子越难分裂,可用用于防止过拟合
- subsample:随机抽样的比例,可以用于防止过拟合
- max_depth:最大树深,控制树的最大深度,可以用于防止过拟合
xgboost 为什么速度快:
- 并行化
- 候选分割点:每个特征采用常数个分位点作为候选分割点
-
CPU cache 命中优化: 使用缓存预取的方法,对每个线程分配一个连续的buffer,读取每个block中样本的梯度信息并存入连续的Buffer中。
-
Block 处理优化:Block预先放入内存;Block按列进行解压缩;将Block划分到不同硬盘来提高吞吐
xgboost的树停止生长的条件
- 超出设定的最大树深max_depth
- 当引入新的分裂不能带来增益,即gain<0,则放弃当前分裂,防止复杂度过高
- 引入新的分裂后计算左右子节点的样本权重和,若任一叶子节点的样本权重和小于设定的最小样本权重和min_child_weight,则放弃此处分裂。
xgboost如何处理不平衡数据
xgboost有两个参数可以处理不平衡数据:max_delta_step, scale_pos_weight.
- max_delta_step本意是限制每棵树权重改变的最大步长,设置为正数使得算法更加保守,当某类样本极度不平衡时,这个参数对基模型是逻辑回归时很有帮助;(当在意得到的概率时,不能改变正负样本比例)
- scale_pos_weight:当各样本极度不平衡时,设置为正数可以平衡正负样本的权重,通常设置为正负样本的比例,例如正负样本为1:10时,可设置为10. 通常用于使用例如AUC等指标评估模型。
除此之外,也能用其他常见的处理不平衡数据的方法,如上采样、下采样、SMOTE算法或者自定义代价函数的方式。
xgboost如何计算最佳分割点
xgboost先对每个特征根据特征值进行预排序,再分成block进行存储,每次计算可以重复使用。然后通过多线程分别计算每个特征的最佳分割点,根据每次分裂后的增益,选择增益最大的特征值作为最佳分割点。
计算每个特征的最佳分割点时,xgboost提供了直方图近似算法,对特征排序后只选取常数个分位点作为候选分裂点进行分裂,极大提升了分裂效率。
xgboost如何体现特征的重要性
- weight: 该特征在所有树中被用来分割样本的总次数
- gain:该特征在所有树中用于分割后产生的平均增益
- cover:该特征在所有树种用于分割后影响的样本数量的平均值
xgboost的scalable如何体现
- xgboost既能支持树模型作为基模型,也能支持线性模型作为基模型
- xgboost对gbdt的损失函数进行了泰勒二项展开,既支持一阶损失函数,也支持二阶损失函数,支持自定义损失函数。
- Block结构支持并行化,支持 Out-of-core计算。
为什么xgboost相较于一些模型对缺失值不敏感
对于某些模型例如KNN和SVM,它们的模型原理中涉及了对距离的度量,所以对特征值的要求比较高,如果对缺失值处理不当,会导致模型的预测效果比较差;
而xgboost以树模型为主,缺失值对于树模型的影响不大,因为树模型在寻找最佳分割点时,通常计算的是某个特征的最佳分割点,可以忽略每个特征中值为缺失的样本。
xgboost中如何进行剪枝
-
在目标函数中增加了正则项:使用叶子结点的数目和叶子结点权重的L2模的平方,控制树的复杂度。
-
在结点分裂时,定义了一个阈值gamma,如果分裂后损失减少量小于该阈值,则不分裂。
-
当引入一次分裂后,重新计算新生成的左、右两个叶子结点的样本权重和。如果任一个叶子结点的样本权重低于某一个阈值(最小样本权重和min_child_weight),也会放弃此次分裂。
-
XGBoost 先从顶到底建立树直到最大深度,再从底到顶反向检查是否有不满足分裂条件的结点,进行剪枝。