转载自http://izhaoyi.top/2017/09/23/sklearn-xgboost/
集成方法的目的是结合一些基于某些算法训练得到的基学习器来改进其泛化能力和鲁棒性(相对单个的基学习器而言)
主流的两种做法分别是:
独立的训练一些基学习器(一般倾向于强大而复杂的模型比如完全生长的决策树),然后综合他们的预测结果,通常集成模型的效果会优于基学习器,因为模型的方差有所降低。
学习器
参数
oob_score=True
来通过包外估计来估计模型的泛化误差(也就不需要进行交叉验证了)Note:方差的产生主要是不同的样本训练得到的学习器对于同一组测试集做出分类、预测结果的波动性,究其原因是基学习器可能学到了所供学习的训练样本中的局部特征或者说是拟合了部分噪声数据,这样综合不同的学习器的结果,采取多数表决(分类)或者平均(回归)的方法可以有效改善这一状况
学习器
Notes:
随机森林的行采样(bagging)和列采样(feature bagging)都是为了减小模型之间的相关性使基学习器变得不同从而减小集成模型的方差
Extra-Trees(extremely randomized trees):相较于rf进一步增强了随机性,rf是对各个基学习器随机挑选了部分特征来做维特征子集从中挑选最佳的特征切分,而Extra-Trees更进一步,在特征子集里挑选最佳特征时不是选择最有区分度的特征值,而是随机选择这一划分的阈值(该阈值在子特征集里的特征对应的采样后的样本取值范围里随机选取),而不同的随机阈值下的特征中表现最佳的作为划分特征,这样其实增强了随机性,更进一步整大了基学习器的偏差但降低了整体的方差
调参
方法
特征选择
特征重要性评估:一棵树中的特征的排序(比如深度)可以用来作为特征相对重要性的一个评估,居于树顶端的特征相对而言对于最终样本的划分贡献最大(经过该特征划分所涉及的样本比重最大),这样可以通过对比各个特征所划分的样本比重的一个期望值来评估特征的相对重要性,而在随机森林中,通过对于不同树的特征的期望取一个平均可以减小评估结果的方差,以供特征选择;在sklearn中这些评估最后被保存在训练好的模型的参数featureimportances里,是各个特征的重要性值经过归一化的结果,越高代表特征越匹配预测函数
Notes:
随机森林与KNN
一个接一个的(串行)训练基学习器,每一个基学习器主要用来修正前面学习器的偏差。
_Notes:调参的关键参数是基学习器的数量n_estimators
以及基学习器本身的复杂性比如深度max_depth
或者叶节点所需的最少样本数min_samples_leaf
_
概述
Gradient Tree Boosting或者说GBRT是boosting的一种推广,是的可以应用一般的损失函数,可以处理分类问题和回归问题,应用广泛,常见应用场景比如网页搜索排序和社会生态学
优缺点
学习器
GradientBoostingClassifier
n_estimators
max_depth
或者叶节点数目max_leaf_nodes
来控制(注意两种树的生长方式不同,max_leaf_nodes
是针对叶节点优先挑选不纯度下降最多的叶节点,这里有点LightGBM的’leaf-wise’的意味,而按树深分裂则更类似于原始的以及XGBoost的分裂方式)learning_rate
对应取值范围在(0,1]之间的超参数对应GBRT里的shrinkage来避免过拟合(是sklearn里的GBDT用来进行正则化的一种策略);n_classes
对应每轮迭代的回归树,这样总体树的数目是n_classes*n_estimators
criterion
用来设置回归树的切分策略
friedman_mse
,对应的最小平方误差的近似,加入了Friedman的一些改进mse
对应最小平方误差mae
对应平均绝对值误差subsample
:行采样,对样本采样,即训练每个基学习器时不再使用原始的全部数据集,而是使用一部分,并且使用随机梯度上升法来做集成模型的训练max_features
在训练基学习器时使用一个特征子集来训练,类似随机森林的做法min_impurity_split
(原始)以及min_impurity_decrease
来实现,前者的是根据节点的不纯度是否高于阈值,若不是则停止增长树,作为叶节点;后者则根据分裂不纯度下降值是否超过某一阈值来决定是否分裂(此外这里的early stopping似乎与XGBoost里显示设置的early stopping不同,这里是控制树的切分生长,而XGBoost则是控制基学习器的数目)init
,用来计算初始基学习器的预测,需要具备fit
和predict
方法,若未设置则默认为loss.init_estimator
warm_start
,若设置为True则可以使用已经训练好的学习器,并且在其上添加更多的基学习器presort
,默认设置为自动,对样本按特征值进行预排序从而提高寻找最优切分点的效率,自动模式下对稠密数据会使用预排序,而对稀疏数据则不会loss
)
n_classes
互斥的多分类,提供概率估计,初始模型值设为各类别的先验概率,每一轮迭代需要构建n类回归树可能会使得模型对于多类别的大数据集不太高效feature_importances_
):进行特征重要性的评估oob_improvement_
),使用包外样本来计算每一轮训练后模型的表现提升train_score_
)estimators_
)fit
方法里可以设置样本权重sample_weight
,monitor
可以用来回调一些方法比如包外估计、早停止等GradientBoostingRegressor
ls
train_score_
可获得每轮训练的训练误差,通过方法staged_predict
可以获得每一阶段的测试误差,通过属性feature_importances_
可以输出模型判断的特征相对重要性正则化
learning rate
一种简单的正则化的策略,通过控制每一个基学习器的贡献,会影响到基学习器的数目即n_estimators
,经验性的设置为一个较小的值,比如不超过0.1的常数值,然后使用early stopping来控制基学习器的数目subsample
),一般设置shrinkage比不设置要好,而加上行采样会进一步提升效果,而仅使用行采样可能效果反而不佳;而且进行行采样后可使用包外估计来计算模型每一轮训练的效果提升,保存在属性oob_improvement_
里,可以用来做模型选择,但是包外预估的结果通常比较悲观,所以除非交叉验证太过耗时,否则建议结合交叉验证一起进行模型选择max_features
来实现可解释性
单一的决策树可以通过将树结构可视化来分析和解释,而梯度上升模型因为由上百课回归树组成因此他们很难像单独的决策树一样被可视化,不过也有一些技术来辅助解释模型
Notes:
Voting的基本思想是将不同学习器的结果进行硬投票(多数表决)或者软投票(对预测概率加权平均)来对样本类别做出预估,其目的是用来平衡一些表现相当且都还不错的学习器的表现,以消除它们各自的缺陷
voting
=’hard’):按照多数表决原则,根据分类结果中多数预测结果作为输入样本的预测类别,如果出现类别数目相同的情况,会按照预测类别的升序排序取前一个预测类别(比如模型一预测为类别‘2’,模型二预测为类别‘1’则样本会被判为类别1)wights
为一个列表表示各个基学习器的权重值XGBoost里可以使用两种方式防止过拟合
max_depth
,基学习器的深度,增加该值会使基学习器变得更加复杂,荣易过拟合,设为0表示不设限制,对于depth-wise的基学习器学习方法需要控制深度min_child_weight
,子节点所需的样本权重和(hessian)的最小阈值,若是基学习器切分后得到的叶节点中样本权重和低于该阈值则不会进一步切分,在线性模型中该值就对应每个节点的最小样本数,该值越大模型的学习约保守,同样用于防止模型过拟合gamma
,叶节点进一步切分的最小损失下降的阈值(超过该值才进一步切分),越大则模型学习越保守,用来控制基学习器的复杂度(有点LightGBM里的leaf-wise切分的意味)subsample
colsample_bytree
eta
即shrinkage对于XGBoost来说同样是两种方式
scale_pos_weight
max_delta_step
为一个有限值比如1来加速模型训练的收敛主要用于设置基学习器的类型
booster
nthread
,设置并行的线程数,默认是最大线程数在基学习器确定后,根据基学习器来设置的一些个性化的参数
eta
,步长、学习率,每一轮boosting训练后可以得到新特征的权重,可以通过eta来适量缩小权重,使模型的学习过程更加保守一点,以防止过拟合gamma
,叶节点进一步切分的最小损失下降的阈值(超过该值才进一步切分),越大则模型学习越保守,用来控制基学习器的复杂度(有点LightGBM里的leaf-wise切分的意味)max_depth
,基学习器的深度,增加该值会使基学习器变得更加复杂,荣易过拟合,设为0表示不设限制,对于depth-wise的基学习器学习方法需要控制深度min_child_weight
,子节点所需的样本权重和(hessian)的最小阈值,若是基学习器切分后得到的叶节点中样本权重和低于该阈值则不会进一步切分,在线性模型中该值就对应每个节点的最小样本数,该值越大模型的学习约保守,同样用于防止模型过拟合max_delta_step
,树的权重的最大估计值,设为0则表示不设限,设为整数会是模型学习相对保守,一般该参数不必设置,但是对于基学习器是LR时,在针对样本分布极为不均的情况控制其值在1~10之间可以控制模型的更新subsample
,基学习器使用样本的比重colsample_bytree
,用于每棵树划分的特征比重colsample_bylevel
,用于每层划分的特征比重alpha
lambda
tree_method
,树的构建方法,准确的说应该是切分点的选择算法,包括原始的贪心、近似贪心、直方图算法(可见LightGBM这里并不是一个区别)
auto
,启发式地选择分割方法,近似贪心或者贪心exact
,原始的贪心算法,既针对每一个特征值切分一次approx
,近似的贪心算法选取某些分位点进行切分,使用sketching和histogramhist
,直方图优化的贪心算法,对应的参数有grow_policy
,max_bin
gpu_exact
gpu_hist
scale_pos_weight
,针对数据集类别分布不均,典型的值可设置为 sum(negativecases)sum(positivecases)sum(negativecases)sum(positivecases)
grow_policy
,控制树的生长方式,目前只有当树的构建方法tree_method
设置为hist
时才可以使用所谓的leaf-wise
生长方式
depthwise
,按照离根节点最近的节点进行分裂lossguide
,优先分裂损失变化大的节点,对应的一个参数还有max_leaves
,表示可增加的最大的节点数max_bin
,同样针对直方图算法tree_method
设置为hist
时用来控制将连续特征离散化为多个直方图的直方图数目predictor
,选择使用GPU或者CPU
cpu_predictor
gpu_predictor
根据任务、目的设置的参数,比如回归任务与排序任务的目的是不同的
reg:linear
,线性回归reg:logistic
,逻辑回归binary:logistic
,使用LR二分类,输出概率binary:logitraw
,使用LR二分类,但在进行logistic转换之前直接输出分类得分count:poisson
,泊松回归multi:softmax
,使用softmax进行多分类,需要设置类别数num_class
multi:softprob
rank:pairwise
,进行排序任务,最小化pairwise损失reg:gamma
,gamma回归reg:tweedie
,tweedie回归eval_metric
,默认根据目标函数设置,针对验证集,默认情况下,最小均方误差用于回归,错分用于分类,平均精确率用于排序等,可以同时使用多个评估指标,在python里使用列表来放置
rmse
mae
logloss
,负的对数似然error
,根据0.5作为阈值判断的错分率error@t
merror
mlogloss
auc
主要用来排序ndcg
,normalized discounted cumulative gain及其他的一些针对泊松回归等问题的评价指标num_round
迭代次数,也对应基学习器数目task
当前对模型的任务,包括
train
pred
eval
dump
model_in
和model_out
fmap
,feature map用来导出模型直方图算法,LightGBM提供一种数据类型的封装相对Numpy,Pandas,Array等数据对象而言节省了内存的使用,原因在于他只需要保存离散的直方图,LightGBM里默认的训练决策树时使用直方图算法,XGBoost里现在也提供了这一选项,不过默认的方法是对特征预排序,直方图算法是一种牺牲了一定的切分准确性而换取训练速度以及节省内存空间消耗的算法
对稀疏特征构建直方图时的时间复杂度为O(2*#非零数据)
LEAF-WISE(BEST-FIRST)树生长策略
相对于level-wise的生长策略而言,这种策略每次都是选取当前损失下降最多的叶节点进行分割使得整体模型的损失下降得更多,但是容易过拟合(特别当数据量较小的时候),可以通过设置参数max_depth
来控制树身防止出现过拟合
Notes:XGBoost现在两种方式都是支持的
直接支持类别特征
对于类别类型特征我们原始的做法是进行独热编码,但是这种做法对于基于树的模型而言不是很好,对于基数较大的类别特征,可能会生成非常不平衡的树并且需要一颗很深的树才能达到较好的准确率;比较好的做法是将类别特征划分为两个子集,直接划分方法众多(2^(k-1)-1),对于回归树而言有一种较高效的方法只需要O(klogk)的时间复杂度,基本思想是对类别按照与目标标签的相关性进行重排序,具体一点是对于保存了类别特征的直方图根据其累计值(sum_gradient/sum_hessian)重排序,在排序好的直方图上选取最佳切分位置
使用collective communication算法替代了point-to-point communication算法提升了效率
特征并行
特征并行是为了将寻找决策树的最佳切分点这一过程并行化
Notes:典型的空间换时间,差别就是减少了传输切分结果的步骤,节省了这里的通信消耗
数据并行
上述特征并行的方法并没有根本解决寻找切分点的计算效率问题,当记录数过大时需要考虑数据并行的方法
并行投票
进一步减小了数据并行中的通信代价,通过两轮的投票来减小特征直方图中的通信消耗
直接支持类别(标称)特征
LightGBM可以直接用类别特征进行训练,不必预先进行独热编码,速度会提升不少,参数设置categorical_feature
来指定数据中的类别特征列
早停止
sklearn-GBDT,XGBoost,LightGBM都支持早停止,不过在细节上略有不同
min_impurity_split
(原始)以及min_impurity_decrease
来实现,前者的是根据节点的不纯度是否高于阈值,若不是则停止增长树,作为叶节点;后者则根据分裂不纯度下降值是否超过某一阈值来决定是否分裂(此外这里的early stopping似乎与XGBoost里显示设置的early stopping不同,这里是控制树的切分生长,而XGBoost则是控制基学习器的数目)bst.best_score, bst.best_iteration, bst.best_ntree_limit
,官方的建议是在做预测时设置为bst.best_ntree_limit
,实际使用时感觉bst.best_iteration
和 bst.best_ntree_limit
的表现上区别不大bst.best_iteration
这一种方式实践上
支持的任务
支持的评价指标METRIC
l1
l2
l2_root
binary_logloss
,multi_logloss
binary_error
,multi_error
num_leaves
,与模型复杂度直接相关(leaf-wise)regression
,对应的损失函数如下
regression_l1
,加了l1正则的回归,等同于绝对值误差regression_l2
,等同于均方误差huber
,Huber Lossfair
,Fair Losspoisson
,泊松回归binary
,二分类multiclass
,多分类lambdarank
boosting
gbdt
,传统的梯度提升决策树rf
,随机森林dart
,Dropouts meet Multiple Additive Regression Treesgoss
,Gradient-based One-Side Samplingnum_iterations
,对于多分类问题,LightGBM会构建num_class*num_iterations的树learning_rate
,即shrinkagetree_learner
,主要用来控制树是否并行化训练
serial
,单机的树学习器feature
,特征并行的树学习器data
,数据并行的树学习器num_threads
device
,使用cpu还是gpu
cpu
gpu
防止过拟合
max_depth
,主要用来避免模型的过拟合,设为负数值则表明不限制min_data_in_leaf
min_sum_hessian_in_leaf
feature_fraction
,每棵树的特征子集占比,设置在0~1之间,可以加快训练速度,避免过拟合bagging_fraction
,不进行重采样的随机选取部分样本数据,此外需要设置参数bagging_freq
来作为采样的频率,即多少轮迭代做一次bagging;early_stopping_roung
,在某一验证数据的某一验证指标当前最后一轮迭代没有提升时停止迭代lambda_l1
lambda_l2
min_gain_to_split
直方图相关
max_bin
,特征值装载的最大直方图数目,一般较小的直方图数目会降低训练的准确性但会提升整体的表现,处理过拟合min_data_in_bin
,设置每个直方图中样本数的最小值,同样防止过拟合特征相关
is_pre_partition
is_sparse
categorical_feature
,声明类别特征对应的列(通过索引标记),仅支持int类型weight
,指定一列作为权重列内存相关
two_round
,一般LightGBM将数据载入内存进行处理,这样会提升数据的加载速度,但是对于数据量较大时会造成内存溢出,所以此时需要分阶段载入save_binary
,将数据文件导出为二进制文件,下次加载数据时就会更快一些缺失值
use_missing
zeros_as_missing
sigmoid
,sigmoid函数中的参数,用于二分类和排序任务scale_pos_weight
,设置正例在二分类任务中的样本占比boost_from_average
,调整初始的分数为标签的均值,加速模型训练的收敛速度,仅用于回归任务is_unbalance
num_class
,用于多分类LEAF-WISE
num_leaves
,对于leaf-wise的模型而言该参数是用来控制模型复杂度的主要参数,理论上可以通过设置num_leaves
=2^(max_depth)来设置该参数值,实际是不可取的,因为在节点数目相同的前提下,对于leaf-wise的模型会倾向于生成深度更深的模型,如果生硬的设置为2^(max_depth)可能会造成模型的过拟合,一般设置的值小于2^(max_depth),min_data_in_leaf
,在设置了叶节点数后,该值会对模型复杂度造成影响,若设的较大则树不会生长的很深,但可能造成模型的欠拟合max_depth
效率
bagging_fraction
和bagging_freq
,使用bagging进行行采样提升训练速度(减小了数据集)feature_fraction
,列采样max_bin
save_binary
准确率
max_bin
,当然这样会牺牲训练速度learning_rate
,这样会增加迭代次数num_leaves
,可能造成模型过拟合dart
模型过拟合
max_bin
num_leaves
min_data_in_leaf
和min_sum__hessian_in_leaf
bagging_fraction
和bagging_freq
feature_fraction
,列采样lambda_l1
lambda_l2
min_gain_to_split
max_depth
实际在库的实现层面原始论文里的很多区别是不存在的,差异更多在一些工程上的性能优化
min_impurity_split
即控制了判断叶节点是否进一步切分的不纯度的阈值,若超过该阈值则可以进一步切分,否则不行,故而控制了树的深度即控制了基学习器的复杂度XGBoost目前已经实现了LightGBM之前不同的一些方法比如直方图算法,两者的区别更多的在与LightGBM优化通信的的一些处理上