gbdt算法原理
1. xgboost/gbdt在调参时为什么树的深度很少就能达到很高的精度
考虑这个简化的操作:试想把树的深度设为2,那么gbdt里面的基学习器都是二分类决策树,然后自己在二维坐标系上画很多点,然后不停的用boosting的方法用二分类决策树去进行分类,不同的是,我们简化权重的计算方式,初始化权重都为1,每次分错权重不变,分对则权重将为原来的一半,最终能用深度为2的树成功对很多不规则的点进行分类。
然而用深度为2的树,用类似RF的bagging方法也能成功对不规则的点分类。
所以到这里,我们实际操作了,用深度低的树通过ensemble对于不规则的点的分类这种“黑科技”。
那么为什么gbdt在树的深度很小的时候能很快达到很高的预测或分类精度呢?或者说,它比RF明显。
我的理解是,因为gbdt更多的是一种优化算法。具体怎么优化的,期待牛人用公式解答。
2. matlab中怎么使用gbdt
1 机器学习是万能的?
当然不是,如果你认为可以简单地把一堆特征样本扔给机器学习,就期望它给一个好的模型,那是不可能。在使用机器学习之前,一定要对所使用的模型有个基本的了解,最好能够知道它的计算原理。如果你都不知道treelink为何物,那些参数大概是个什么意思,你最好就不要用了,用也是在拼人品。
2 使用机器学习的同时做好数据分析工作
就算使用机器学习,数据的分析工作也是省不了的,做好了分析工作,你会发现自己都可以像机器一样找到那些规律。其实机器学习本身也就是统计,帮你找数据之间的规律,并把这些规律做成规则。好莱坞奥斯卡金像奖电影《美丽心灵》中的男主人翁,诺贝尔经济学奖得主数学家约翰纳什在电影中被称为最厉害的人肉密码破译者,充分向我们展现了how people learning beats machine learning,当然是有些夸张的成份。下面是一些可以做的最基本的数据分析工作:
1) 特征的分布:按特征的取值分段,每一段包含的样本数量,特征均值,方差。
2) 目标分布同上
3) 特征目标关系:特征分段,每段中包含的样本的目标取值。
4) 目标特征关系:目标分段,每段中包含的样本的特征取值
3 模型在训练数据上效果不错,但做Cross-validation效果不佳
主要原因有两个:
1) 选取的样本数据太少,覆盖度不够,考虑增加训练样本
2) 样本特征过多,可以考虑减少一些特征,只留下重要的特征
4 模型在类似Cross-validation这样的封闭测试上效果不错,但在开放测试上效果不佳
1) 选取的训练数据覆盖度不够,不具备代表性,不能体现真实数据的分布。
2) 模型迁移(Model drift),随着时间变化,特征数据也随之变化。比如3个月前做的模型对现在的特征可能不会有好的效果。
3. 机器学习中GBDT和XGBoosts的区别是
首先来了解一下boosting思想,每次训练单个弱分类器时,都将上一次分错的数据权重提高一点再进行当前单个弱分类器的学习,这样往后执行,训练出来的单个弱分类器就会越在意那些容易分错的点,最终通过加权求和的方式组合成一个最终的学习器,gradent boosting 是boosting的一种,每一次构建单个学习器时,是在之前建立的模型的损失函数的梯度下降方向, GB与Adaboost的区别在于:
AdaBoost是通过提升错分数据点的权重来定位模型的不足。
Gradient Boosting是通过算梯度(gradient)来定位模型的不足。
主要思想是,每一次建立单个学习器时,是在之前建立的模型的损失函数的梯度下降方向,损失函数越大,说明模型越容易出错,如果我们的模型能够让损失函数持续的下降,则说明我们的模型在不停的改进,而最好的方式就是让损失函数在其梯度方向上下降。
GBDT=GB+DT(decision tree),即基分类器为决策树时,这里的决策树是回归树。
Xgboost 是GB算法的高效实现,其中基分类器除了可以使CART也可以是线性分类器。
几大区别:
传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯帝回归或者线性回归
传统GBDT在优化时只用到了一阶导数,而xgboost对代价函数进行了二阶泰勒展开,用到了一阶和二阶导数
xgboost加入了正则项,防止过拟合
shrinkage,相当于学习率,在每完成一次迭代后,会乘上这个系数,削减每棵树的影响
列抽样,借鉴随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算。
4. 从原理上来说,GBDT 和 SVM 哪个更强为什么
为了简单,只讨论一下分类的情况。
算法很难比较说谁更强,而是谁更适应业务场景。
主要是特征数量、训练过程、可解释性上面有很大的差异。
SVM 能够训练大量(上万的词)特征,不用考虑特征离散化或者分段,非线性映射可以很好的分类。
GBDT在特征较少的时候(200以内),能够高效bootstrap 抽取样本和特征,训练多颗树。能够自动做特征重要性排序,通过gini系数等指标判断分割点。能够表达非常复杂的规则。
作者:秉机夜读
来源:知乎
5. scikit-learn怎样使用gbdt算法
你好,你有读写的权限吗?尝试普通的文件读写操作: f=open('a.txt', 'w') 如果不能正常运行,那么尝试用管理员权限运行你的程序。或者,修改保存的文件名,'iris.doct'修改为其它的名字,如'abcd.dot'.
6. GBDT预测时每一棵树是否能并行
传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。
传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)
列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
对缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。
xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。
可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。
7. GBDT 如何实现特征组合提取
以python调用sklearn为例,在你建立GBDT对象并作fit之后,可以使用如下代码获得你要的规则代码:
dot_data = tree.export_graphviz(model_tree, out_file=None,
max_depth=5, feature_names=names_list, filled=True, rounded=True) # 将决策树规则生成dot对象
其中tree就是你的数对象,如果你的out_file后面是一个文件名,那么你的规则会输出到文件中;如果是None(就像上面代码),那么值会保存在dot_data中。
无论哪种方法,你都能获得规则文本。然后剩下的就是普通的文本解析的事情了。
在决策树算法对象的tree_属性中,存储了所有有关决策树规则的信息(示例中的决策树规则存储在model_tree.tree_中)。最主要的几个属性:
children_left:子级左侧分类节点
children_right:子级右侧分类节点
feature:子节点上用来做分裂的特征
threshold:子节点上对应特征的分裂阀值
values:子节点中包含正例和负例的样本数量
上述属性配合节点ID、节点层级便迭代能得到如下的规则信息:
1 [label="rfm_score <= 7.8375
gini = 0.1135
samples =
14581
value = [13700, 881]", fillcolor="#e58139ef"] ;
其中规则开始的1代表节点ID,rfm_score是变量名称,rfm_score
<= 7.8375是分裂阀值,gini = 0.1135是在当前规则下的基尼指数,nsamples是当前节点下的总样本量,nvalue为正例和负例的样本数量。
来源:知乎
8. LightGBM 如何确定最佳迭代次数
LightGBM中实现了哪些梯度增强方法,它们有什么区别?一般来说,哪些参数是重要的?哪些正则化参数需要调整?如何调整lightGBM参数在python?梯度提升的方法
使用LightGBM,你可以运行不同类型的渐变增强提升方法。你有:GBDT、DART和GOSS,这些可以通过“boosting”参数指定。
在下一节中,我将对这些方法进行解释和比较。
梯度提升决策树(GBDT)
该方法是本文首先提出的传统梯度提升决策树,也是XGBoost和pGBRT等优秀库背后的算法。
由于其精度高、效率高、稳定性好,目前已得到广泛的应用。你可能知道gbdt是一个决策树的集合模型但是它到底是什么意思呢?
让我来告诉你要点。
它基于三个重要原则:
弱学习者(决策树)梯度优化提升技术所以在gbdt方法中,我们有很多决策树(弱学习者)。这些树是按顺序构建的:
首先,树学习如何适应目标变量第二棵树学习如何适合残差(差异)之间的预测,第一棵树和地面真相第三棵树学习如何匹配第二棵树的残差,以此类推。所有这些树都是通过传播整个系统的误差梯度来训练的。
gbdt的主要缺点是,在每个树节点中找到最佳分割点非常耗时,而且会消耗内存。其他的提升方法试图解决这个问题。
DART梯度提升
在这篇优秀的论文中(arxiv/1505.01866),你可以学习所有关于DART梯度提升的东西,这是一种使用dropout(神经网络中的标准)的方法,来改进模型正则化和处理一些其他不太明显的问题。
也就是说,gbdt存在过度专门化(over-specialization)的问题,这意味着在以后的迭代中添加的树往往只会影响对少数实例的预测,而对其余实例的贡献则可以忽略不计。添加dropout会使树在以后的迭代中更加难以专门化那些少数的示例,从而提高性能。
lgbm goss基于梯度的单边采样
事实上,将该方法命名为lightgbm的最重要原因就是使用了基于本文的Goss方法。Goss是较新的、较轻的gbdt实现(因此是“light”gbm)。
标准的gbdt是可靠的,但在大型数据集上速度不够快。因此goss提出了一种基于梯度的采样方法来避免搜索整个搜索空间。我们知道,对于每个数据实例,当梯度很小时,这意味着不用担心数据是经过良好训练的,而当梯度很大时,应该重新训练。这里我们有两个方面,数据实例有大的和小的渐变。因此,goss以一个大的梯度保存所有数据,并对一个小梯度的数据进行随机抽样(这就是为什么它被称为单边抽样)。这使得搜索空间更小,goss的收敛速度更快。
让我们把这些差异放在一个表格中:
注意:如果你将增强设置为RF,那么lightgbm算法表现为随机森林而不是增强树! 根据文档,要使用RF,必须使用baggingfraction和featurefraction小于1。
正则化
在这一节中,我将介绍lightgbm的一些重要的正则化参数。显然,这些是您需要调优以防止过拟合的参数。
您应该知道,对于较小的数据集(<10000条记录),lightGBM可能不是最佳选择。在这里,调优lightgbm参数可能没有帮助。
此外,lightgbm使用叶向树生长算法,而xgboost使用深度树生长算法。叶向方法使树的收敛速度更快,但过拟合的几率增加。
注意:如果有人问您LightGBM和XGBoost之间的主要区别是什么?你可以很容易地说,它们的区别在于它们是如何实现的。
根据lightGBM文档,当面临过拟合时,您可能需要做以下参数调优:
使用更小的max_bin使用更小的num_leaves使用mindatainleaf和minsumhessianin_leaf通过设置baggingfraction和baggingfreq使用bagging_freq通过设置feature_fraction使用特征子采样使用更大的训练数据尝试lambdal1、lambdal2和mingainto_split进行正则化尝试max_depth以避免树的深度增长在下面的部分中,我将更详细地解释这些参数。
lambda_l1
Lambdal1(和lambdal2)控制l1/l2,以及mingainto_split用于防止过拟合。我强烈建议您使用参数调优(在后面的小节中讨论)来确定这些参数的最佳值。
num_leaves
numleaves无疑是控制模型复杂性的最重要参数之一。通过它,您可以设置每个弱学习者拥有的叶子的最大数量。较大的numleaves增加了训练集的精确度,也增加了因过度拟合而受伤的几率。根据文档,一个简单的方法是numleaves = 2^(maxdepth)但是,考虑到在lightgbm中叶状树比层次树更深,你需要小心过度拟合!因此,必须同时使用maxdepth调优numleaves。
子采样
通过子样例(或bagging_fraction),您可以指定每个树构建迭代使用的行数百分比。这意味着将随机选择一些行来匹配每个学习者(树)。这不仅提高了泛化能力,也提高了训练速度。
我建议对基线模型使用更小的子样本值,然后在完成其他实验(不同的特征选择,不同的树结构)时增加这个值。
feature_fraction
特征分数或子特征处理列采样,LightGBM将在每次迭代(树)上随机选择特征子集。例如,如果将其设置为0.6,LightGBM将在训练每棵树之前选择60%的特性。
这个功能有两种用法:
可以用来加速训练吗可以用来处理过拟合吗
max_depth
该参数控制每棵经过训练的树的最大深度,将对:
num_leaves参数的最佳值模型的性能训练时间注意,如果您使用较大的max_depth值,那么您的模型可能会对于训练集过拟合。
max_bin
装箱是一种用离散视图(直方图)表示数据的技术。Lightgbm在创建弱学习者时,使用基于直方图的算法来寻找最优分割点。因此,每个连续的数字特性(例如视频的视图数)应该被分割成离散的容器。
此外,在这个GitHub repo(huanzhang12/lightgbm-gpu)中,你可以找到一些全面的实验,完全解释了改变max_bin对CPU和GPU的影响。
如果你定义maxbin 255,这意味着我们可以有255个唯一的值每个特性。那么,较小的maxbin会导致更快的速度,较大的值会提高准确性。
训练参数
当你想用lightgbm训练你的模型时,一些典型的问题可能会出现:
训练是一个耗时的过程处理计算复杂度(CPU/GPU RAM约束)处理分类特征拥有不平衡的数据集定制度量的需要需要对分类或回归问题进行的调整在本节中,我们将尝试详细解释这些要点。
num_iterations
Num_iterations指定增强迭代的次数(要构建的树)。你建立的树越多,你的模型就越精确,代价是:
较长的训练时间过拟合的可能性更高从较少的树开始构建基线,然后当您想从模型中挤出最后的%时增加基线。
建议使用更小的learningrate和更大的numiteration。此外,如果您想要更高的numiteration,那么您应该使用earlystopping_rounds,以便在无法学习任何有用的内容时停止训练。
earlystoppingrounds
如果验证度量在最后一轮停止后没有改进,此参数将停止训练。这应该与一些迭代成对地进行定义。如果你把它设置得太大,你就增加了过拟合的变化(但你的模型可以更好)。
经验法则是让它占num_iterations的10%。
lightgbm categorical_feature
使用lightgbm的优势之一是它可以很好地处理分类特性。是的,这个算法非常强大,但是你必须小心如何使用它的参数。lightgbm使用一种特殊的整数编码方法(由Fisher提出)来处理分类特征
实验表明,该方法比常用的单热编码方法具有更好的性能。
它的默认值是“auto”,意思是:让lightgbm决定哪个表示lightgbm将推断哪些特性是绝对的。
它并不总是工作得很好,我强烈建议您简单地用这段代码手动设置分类特性
cat_col = dataset_name.select_dtypes(‘object’).columns.tolist()
但是在幕后发生了什么,lightgbm是如何处理分类特征的呢?
根据lightgbm的文档,我们知道树学习器不能很好地使用一种热编码方法,因为它们在树中深度生长。在提出的替代方法中,树形学习器被最优构造。例如,一个特征有k个不同的类别,有2^(k-1) -1个可能的划分,通过fisher方法,可以改进到k * log(k),通过找到分类特征中值排序直方图的最佳分割方式。
isunbalance vs scalepos_weight
其中一个问题,你可能面临的二分类问题是如何处理不平衡的数据集。显然,您需要平衡正/负样本,但如何在lightgbm中做到这一点呢?
lightgbm中有两个参数允许你处理这个问题,那就是isunbalance和scalepos_weight,但是它们之间有什么区别呢?
当您设置Is_unbalace: True时,算法将尝试自动平衡占主导地位的标签的权重(使用列集中的pos/neg分数)
如果您想改变scaleposweight(默认情况下是1,这意味着假设正负标签都是相等的),在不平衡数据集的情况下,您可以使用以下公式来正确地设置它
sample_pos_weight = number of negative samples / number of positive samples
lgbm函数宏指令(feaval)
有时你想定义一个自定义评估函数来测量你的模型的性能,你需要创建一个“feval”函数。
Feval函数应该接受两个参数:
preds 、train_data
并返回
evalname、evalresult、ishigherbetter
让我们一步一步地创建一个自定义度量函数。
定义一个单独的python函数
def feval_func(preds, train_data): # Define a formula that evaluates the results return ('feval_func_name', eval_result, False)
使用这个函数作为参数:
print('Start training...') lgb_train = lgb.train(..., metric=None, feval=feval_func)
注意:要使用feval函数代替度量,您应该设置度量参数 metric “None”。
分类参数与回归参数
我之前提到的大多数事情对于分类和回归都是正确的,但是有些事情需要调整。
具体你应该:
lightgbm最重要的参数
我们已经在前面的部分中回顾并了解了有关lightgbm参数的知识,但是如果不提及Laurae令人难以置信的基准测试,那么关于增强树的文章将是不完整的。
您可以了解用于lightGBM和XGBoost的许多问题的最佳默认参数。
你可以查看这里,但一些最重要的结论是:
注意:绝对不要理会任何参数值的默认值,并根据您的问题进行调整。 也就是说,这些参数是超参数调整算法的一个很好的起点。
Python中的Lightgbm参数调整示例
最后,在解释完所有重要参数之后,该进行一些实验了!
我将使用最受欢迎的Kaggle竞赛之一:Santander Customer Transaction Prediction. 交易预测
我将使用本文介绍如何在任何脚本中的Python中运行超参数调整。
在开始之前,一个重要的问题! 我们应该调整哪些参数?
请注意您要解决的问题,例如,Santander 数据集高度不平衡,在调整时应考虑到这一点!
一些参数是相互依赖的,必须一起调整。 例如,mindatainleaf取决于训练样本和numleaves的数量。
注意:为超参数创建两个字典是一个好主意,一个字典包含您不想调整的参数和值,另一个字典包含您想要调整的参数和值范围。
SEARCH_PARAMS = {'learning_rate': 0.4, 'max_depth': 15, 'num_leaves': 20, 'feature_fraction': 0.8, 'subsample': 0.2} FIXED_PARAMS={'objective': 'binary', 'metric': 'auc', 'is_unbalance':True, 'boosting':'gbdt', 'num_boost_round':300, 'early_stopping_rounds':30}
9. 机器学习算法中GBDT和XGBOOST的区别有哪些
GBDT是一种算法,XGBOOST是GBDT的一种实现。
除了XGBOOST,还有LightGBM,也支持GBDT算法,具体可参见:https://github.com/Microsoft/LightGBM