决策树&随机森林&GBDT&XGBoost学习笔记以及代码实现

1. 引入

1.1 决策树

为达到目标根据一定的条件进行选择的过程,就是决策树,决策树模型非常经典,在机器学习中常被用于分类,构成它的元素是节点和边,节点会根据样本的特征做出判断,最初的分支点被称为根节点,其余成为子节点,没有分支的点是叶子节点,代表分类结果。
决策树的衡量标准是熵。在热力学中,熵被用来描述一个系统内在的混乱程度;在决策树中,熵代表是分支下样本种类的丰富性,样本种类越多越混乱,熵就越大。如果分支下的样本完全属于同一类,熵就为0。构造树的基本思路就是随着树是深度也就是层数的增加,让熵快速降低,熵降低的速度越快,代表决策树分类效率越高。

优点:是天然可解释性,苹果之所以是好苹果,是因为它又大又红又甜、
缺点:容易过拟合。解决方法很简单:去掉一些分支,剪枝有两种:预剪枝是在训练开始前规定条件,比如树达到某一深度就停止训练;后剪枝则是先找到树,再依据一定条件如限制叶子结点的个数,去掉一部分分支。

1.2 随机森林

森林里有许多数,随机森林里有很多决策树,随机森林是决策树的升级版,随机指的是树的生长过程,世界上没有两片相同的树叶,随机森林中的树也各不相同。
在构建决策树时,我们会从训练数据中有放回的随机选取一部分样本,也不会使用数据的全部特征,而是随机选取部分特征进行训练,每棵树使用的样本和特征各不相同,训练的结果也自然不同。为什么这么做?在训练的最初,我们并不知道哪些是异常样本,也不知道哪些特征对分类结果影响更大,随机的过程降低了两者对分类结果的影响。随机森林的输出结果由投票决定,如果大部分决策树认为测试结果是好苹果,我们就认为他是好苹果。
由于树与树之间的独立,他们可以同时训练,不需要花费太长时间,随机的过程让它不容易过拟合,能处理特征较多的高维数据,也不需要做特征选择,合理训练后准确性很高,不知道用什么分类方法时,先试试随机森林准没错。
在机器学习中,随机森林属于集成学习,也就是将多个模型组合起来解决问题,这些模型会独立学习、预测、再投票出结果,准确度往往比单独的模型高很多。除了决策树,还可以使用神经网络等其他模型,同样的,集成学习内部不必是同样的模型,神经网络和决策树可以共存于一个系统中。

1.3 GBDT(Gradient Boosting Decision Tree)梯度提升决策树

GBDT在搜索、广告、推荐系统等领域有广泛应用,能处理标签、数值等各类数据,解释性强。由于树与树之间的相互依赖,需要较长的训练时间。
运用多个模型共同解决问题,GBDT自然属于集成学习

在集成学习中,一个模型依赖于上一个模型,共同逼近正确答案的方法(如GBDT)被称为Boosting提升模型间相互独立共同投票出结果的方法(如随机森林),则被称为Bagging装袋;还有一种Stacking堆叠,是在多个模型的基础上放置一个更高层的模型,将底层模型的输出作为它的输入,由它给出最终的预测结果。

1.4 XGBoost(eXtreme Gradient Boosting)极端梯度提升

XGBoost是GBDT的优秀版本,是一种基于决策树的集成机器学习算法,使用梯度上升框架,适用于分类和回归问题。

XGBoost的整体结构与GBDT一致,都是在训练出一棵树的基础上,再训练下一棵树,预测它与真实分布间的差距,通过不断训练用来弥补差距的树,最终使用树的组合实现对称式分布。

优点:
它的目标函数包括损失函数和正则项部分。损失函数代表模型拟合数据的程度,我们通常使用一阶导数指出其梯度下降的方向,XGBoost还计算了它的二阶导数,进一步考虑了梯度变化的趋势,收敛更快、精度更高;正则项用来控制模型的复杂程度,叶子节点越多,模型越大,运行时间越长,超过一定限度后模型过拟合会导致精度下降,XGBoost的正则项是一个惩罚机制,叶子节点的数目越多,惩罚力度越大,从而限制他们的数量。
加快了计算速度。树的构建中,最耗时的部分是为确定最佳分裂点而进行的特征值排序,XGBoost在训练前会先将特征进行排序,存储为Block结构,可以实现并行处理,此后重复使用此结构来减少计算量。
③善于捕捉复杂数据间的依赖关系,能从大规模数据中获取有效模型,在实用性上支持多种系统语言。XGBoost 允许⽤户定义⾃定义优化⽬标和评价标准它对模型增加了⼀个全新的维度,所以我们的处理不会受到任何限制,有着高度的灵活性。
④缺失值处理
XGBoost内置处理缺失值的规则。⽤户需要提供⼀个和其它样本不同的值,然后把它作为⼀个参数传进去,以此来作为缺失值的取值。XGBoost在不同节点遇到缺失值时采⽤不同的处理⽅法,并且会学习未来遇到缺失值时的处理⽅法。
⑤内置交叉验证
XGBoost允许在每⼀轮boosting迭代中使⽤交叉验证。因此,可以⽅便地获得最优boosting迭代次数。⽽GBM使⽤⽹格搜索,只能检测有限个值。

缺点:在高维稀疏特征数据集和小规模数据集上表现不是很好。

2. 代码实现

2.1 决策树&随机森林&GBDT&XGBoost

2.1.1 分类

import pandas as pd
# from sklearn.inspection import permutation_importance
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import RandomForestClassifier
from xgboost.sklearn import XGBClassifier

# 处理数据 找出目标值和特征值X, y
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state= 22)

dec = DecisionTreeClassifier()
gbc = GradientBoostingClassifier()
rfc = RandomForestClassifier()
xgbc = XGBClassifier()

dec.fit(X_train,y_train)
rfc.fit(X_train,y_train)
gbc.fit(X_train,y_train)
xgbc.fit(X_train,y_train)

y_pred = dec.predict(X_test)) # 预测测试集
# print("训练集准确率:%s"%clas.score(X_train,y_train)) #输出训练集准确度

print("DecisionTreeClassifier准确率为:",dec.score(X_test,y_test))
print("RandomForestClassifier准确率为:",rfc.score(X_test,y_test))
print("GradientBoostingClassifier准确率为:",gbc.score(X_test,y_test))
print(metrics.classification_report(y_test, y_pred)  # 输出结果,精确度、召回率、f-1分数
print(metrics.confusion_matrix(y_test, y_pred)) # 混淆矩阵

2.1.2 回归

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score,mean_squared_error
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from xgboost import XGBRegressor

# 处理数据 找出目标值和特征值X, y
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.22, random_state= 22)

dtr = DecisionTreeRegressor( criterion='mse', random_state=22)
rfr = RandomForestRegressor(n_estimators=1000, criterion='mse', random_state=22, n_jobs=-1)
gbr = GradientBoostingRegressor(n_estimators=1000, criterion='mse', random_state=22)
xgbr = GradientBoostingRegressor(n_estimators=1000, criterion='mse', random_state=22)

rfr.fit(X_train, y_train)

y_train_pred = rfr.predict(X_train)
y_test_pred = rfr.predict(X_test)

print('MSE train: %.3f, test: %.3f' % (mean_squared_error(y_train, y_train_pred), mean_squared_error(y_test, y_test_pred)))
print('R^2 train: %.3f, test: %.3f' % (r2_score(y_train, y_train_pred), r2_score(y_test, y_test_pred)))

2.1.3 显示模型的特征重要性

# 特征重要性
from xgboost import plot_importance
from matplotlib import pyplot as plt
plot_importance(model)
plt.show()

在这里插入图片描述

2.2 XGBoost参数

分为三大板块
XGBoost本身的核心是基于梯度提升树实现的集成算法,整体来说可以有三个核心部分:
①集成算法本身 ②用于集成的弱评估器 ③应用中的其他过程。
在这里插入图片描述

2.2.1 集成算法

①n_estimators:(弱评估器的个数,即基评估器的数量,默认值=100)
n_estimators对随机森林模型的精确性影响是单调的,n_estimators越大,模型的效果往往越好。但是相应的,任何模型都有决策边界,n_estimators达到一定的程度之后,模型的精确性往往不在上升或开始波动,并且,n_estimators越大,需要的计算量和内存也越大,训练的时间也会越来越长。
②learning_rate
学习率,值一般在0.1以下。控制每个弱学习器的权重缩减系;这个系数会乘以叶子节点的权重值,它的作用在于削弱每个树的影响力,如果学习率小,对应的弱学习器的个数就应该增加。
③silent(默认为0)
当这个参数为1时,静默模式开启,不会输出任何信息。
④subsample(默认为1)
这个参数控制对于每棵树随机采样的⽐例。减⼩这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置得过⼩,它可能会导致⽋拟合,一般设为0.5~1。

2.2.2 弱评估器

①max_depth(树的深度,默认为6)
这个值为树的最⼤深度。这个值也是⽤来避免过拟合的。max_depth越⼤,模型会学到更具体更局部的样本,可以使⽤CV函数来进⾏调优。典型值:3~10。
②objective(默认为reg:linear)
这个参数根据是分类还是回归问题,定义了需要被最⼩化的损失函数。
最常⽤的值有:binary:logistic⼆分类的逻辑回归,返回预测的概率(不是类别)。
multi:softmax 使⽤softmax的多分类器,返回预测的类别(不是概率)。在这种情况下,你还需要多设⼀个参数:num_class(类别数⽬)。
multi:softprob 和multi:softmax参数⼀样,但是返回的是每个数据属于各个类别的概率。
③booster(弱学习器的类型,默认为gbtree)
选择每次迭代的模型,有两种选择:
gbtree:基于树的模型、gbliner:线性模型。
一般tree booster的表现远远胜过linear booster。
④gamma(默认为0)
在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。Gamma指定了节点分裂所需的最⼩损失函数下降值。这个参数的值越⼤,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
⑤min_child_weight(默认为1)
最小节点的权重阈值,小于这个值,节点不会再分裂;
⑥max_delta_step(默认为0)
这参数限制每棵树权重改变的最⼤步长。如果这个参数的值为0,那就意味着没有约束。如果它被赋予了某个正值,那么它会让这个算法更加保守。通常,这个参数不需要设置。但是当各类别的样本⼗分不平衡时,它对逻辑回归是很有帮助的。这个参数⼀般⽤不到,但是你可以挖掘出来它更多的⽤处。
⑦colsample_bytree(默认为1)
⽤来控制每棵随机采样的列数的占⽐(每⼀列是⼀个特征),典型值为0.5-1。
⑧colsample_bylevel(默认为1)
⽤来控制树的每⼀级的每⼀次分裂,对列数的采样的占⽐。⼀般不太⽤这个参数,因为subsample参数和colsample_bytree参数可以起到相同的作⽤。
⑨reg_alpha(即alpha,默认为0)
权重的 L1 正则化项。增加此值将使模型更加保守。(和Lasso regression类似)。可以应⽤在很⾼维度的情况下,使得算法的速度更快。
⑩reg_lambda(即lambda,默认为1)
权重的L2正则化项。(和Ridge regression类似)。这个参数是⽤来控制XGBoost的正则化部分的。虽然⼤部分数据科学家很少⽤到这个参数,但是这个参数在减少过拟合上还是可以挖掘出更多⽤处的。

2.2.3 其他过程nthread

①n_thread(默认值为最⼤可能的线程数)
这个参数⽤来进⾏多线程控制,应当输⼊的核数。如果你希望使⽤CPU全部的核,那就不要输⼊这个参数,算法会⾃动检测它。
②n_jobs(默认为None)
设定所要使用的线程。
通过调节n_jobs参数,将n_jobs参数数值设为和CPU内核数一致,如果不知道内核数量,可以设置n_jobs=-1,此时随机森林会使用CPU的全部内核,速度极大提升。
③scale_pos_weight(默认为1)
在各类别样本⼗分不平衡时,把这个参数设定为⼀个正值,可以使算法更快收敛。
学习⽬标参数。这个参数⽤来控制理想的优化⽬标和每⼀步结果的度量⽅法。
④base_score(默认为0.5)
表示所有实例的初始预测分数,全局偏差;对于足够次数的迭代,更改此值不会产生太大影响。
⑤seed(默认为0)
随机数的种⼦设置它可以复现随机数据的结果,也可以⽤于调整参数
⑥random_state
随机森林生成每棵决策树的方法是随机的。如果不希望建模的结果太过于不稳定,一定要固化random_state这个参数的数值。
⑦missing
⑧importance_type

XGBoost 更高级的分析绘图

3. XGBoost vs GBDT

3.1 比较

• 性质:GBDT是机器学习算法,XGBoost除了算法内容还包括一些工程实现方面的优化。
• 基于二阶导:GBDT使用的是损失函数一阶导数,相当于函数空间中的梯度下降;而XGBoost还使用了损失函数二阶导数,相当于函数空间中的牛顿法。
• 正则化:XGBoost显式地加入了正则项来控制模型的复杂度,能有效防止过拟合。
• 列采样:XGBoost采用了随机森林中的做法,每次节点分裂前进行列随机采样。
• 缺失值处理:XGBoost运用稀疏感知策略处理缺失值,而GBDT没有设计缺失策略。
• 并行高效:XGBoost的列块设计能有效支持并行运算,提高效率。

3.2 优点

• 算法本身的优化:首先GBDT只支持决策树,Xgboost除了支持决策树,可以支持多种弱学习器,可以是默认的gbtree, 也就是CART决策树,还可以是线性弱学习器gblinear以及DART;其次GBDT损失函数化简的时候进行的是一阶泰勒公式的展开,而Xgboost使用的是二阶泰勒公式的展示。还有一点是Xgboost的目标函数加上了正则项,这个正则项是对树复杂度的控制,防止过拟合。
• 可以处理缺失值。尝试通过枚举所有缺失值在当前节点是进入左子树,还是进入右子树更优来决定一个处理缺失值默认的方向
• 运行效率:并行化,单个弱学习器最耗时的就是决策树的分裂过程,对于不同特征的特征分裂点,可以使用多线程并行选择。这里想提一下,我自己理解,这里应该针对的是每个节点,而不是每个弱学习器。这里其实我当时深究了一下,有点混乱。为什么是针对每个节点呢?因为我每个节点也有很多特征,所以在每个节点上,我并行(多线程)除了多个特征,每个线程都在做寻找增益最大的分割点。还有需要注意的一点是Xgboost在并行处理之前,会提前把样本按照特征大小排好序,默认都放在右子树,然后递归的从小到大拿出一个个的样本放到左子树,然后计算对基于此时的分割点的增益的大小,然后记录并更新最大的增益分割点

  • 8
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来包番茄沙司

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值