目录:
0x00 前言
0x01 AdaBoost思想及算法流程回顾
1.1 AdaBoost思想
1.2 AdaBoost算法流程
0x02 AdaBoost分类及回归参数
2.1 AdaBoostClassifier
2.2 AdaBoostRegressor
2.3 默认决策树的重要参数
0x03 sklearn中的使用
3.1 数据准备
3.2 调用Adaboost分类器
3.3 调参
0xFF 总结
在前一篇文章《入门数据竞赛系列(4):AdaBoost算法思想及推导》中我们已经学习到了AdaBoost算法的思想及其公式推导。下面我们就以scikit-learn中Adaboost类库为例,重点对调参的注意事项进行学习。
AdaBoost算法是一种模型是加法模型、损失函数为指数函数、学习算法为前向分步算法的学习方法。在每一轮训练中,当前若分类器都会针对于先前分类器分类错误的样本实例而进行调整。通过对之前分类结果不对的训练实例多加关注,使新的预测因子越来越多地聚焦于之前错误的情况。
在上图中,我们每次分类都会调整分类所谓的点(符号变大),进而将t个弱分类器再乘以其相应权重累加起来,得到强分类器:
现在,我们已经复习了Adoost算法的基本内容。接下来我们就看看AdaBoost算法在解决分类和回归问题时在sklearn中的具体应用
我们已经知道,AdaBoost算法及可以用来解决分类问题,也可以用来解决回归问题。在sklearn中对应的就是AdaBoostClassifier和AdaBoostRegressor。下面来看一下这两个类所对应的参数。
AdaBoostClassifier是集成学习的一种集成方法,其采用的基础分类器默认为决策树,在sklearn库中该分类器有如下参数:
from sklearn.ensemble import AdaBoostClassifier;
model = AdaBoostClassifier(
base_estimator=None,
n_estimators=-50,
learning_rate=1.0,
algorithms='SAMME.R',
random_state=None);
base_estimator
:基分类器,即我们的弱分类学习器。理论上可以选择任何一个分类或者回归学习器,不过需要支持样本权重。我们常用的一般是CART决策树或者神经网络MLP。默认是决策树,即AdaBoostClassifier默认使用CART分类树DecisionTreeClassifier。
n_estimators
:基分类器boost最大迭代次数,默认是50次,这个值过大,模型容易过拟合;值过小,模型容易欠拟合。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。
learning_rate
:学习率,表示梯度收敛速度,即每个弱学习器的权重缩减系数,默认为1。如果过大,容易错过最优值,如果过小,则收敛速度会很慢;该值需要和n_estimators
进行一个权衡,当分类器迭代次数较少时,学习率可以小一些,当迭代次数较多时,学习率可以适当放大。
algorithm
:boosting算法,即模型提升准则。scikit-learn实现了两种Adaboost分类算法,SAMME和SAMME.R(默认)。两者的区别主要是弱学习器权重的度量,前者是对样本集分类效果作为弱学习器权重;后者是使用了对样本集分类的预测概率大小来作为弱学习器权重。要注意的是使用了SAMME.R,则弱分类学习器参数base_estimator必须限制使用支持概率预测的分类器。
关于Adaboost模型本身的参数并不多,但是我们在实际中除了调整Adaboost模型参数外,还可以调整基分类器的参数,关于基分类的调参,和单模型的调参是完全一样的,比如默认的基分类器是决策树,那么这个分类器的调参和我们之前的Sklearn参数详解——决策树是完全一致。
base_estimator
:弱回归学习器。理论上可以选择任何一个回归学习器,不过需要支持样本权重。我们常用的一般是CART决策树或者神经网络MLP。默认是决策树,即AdaBoostRegressor默认使用CART回归树DecisionTreeRegressor。
n_estimators
:基分类器boost最大迭代次数,默认是50次,这个值过大,模型容易过拟合;值过小,模型容易欠拟合。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。learning_rate
:学习率,表示梯度收敛速度,即每个弱学习器的权重缩减系数,默认为1。如果过大,容易错过最优值,如果过小,则收敛速度会很慢;该值需要和n_estimators
进行一个权衡,当分类器迭代次数较少时,学习率可以小一些,当迭代次数较多时,学习率可以适当放大。
loss
:该参数对应了我们对第k个弱分类器的中第i个样本的误差的处理(每个样本的相对误差)。有线性linear
, 平方square
和指数exponential
三种选择,默认是线性(一般使用线性就足够了,除非怀疑这个参数导致拟合程度不好)。
由于AdaBoost的弱分类器默认使用CART分类树DecisionTreeClassifier
和CART回归树DecisionTreeRegressor
,因为对其重要参数进行说明。
max_depth
:决策树最大深度。默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。注意,需要的就是弱分类器,千万不要让树太深,否则极易出现过拟合。
min_samples_split
:内部节点再划分所需最小样本数。这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
min_samples_leaf
:叶子节点最少样本数。这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。
min_weight_fraction_leaf
:叶子节点最小的样本权重和。这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。
max_leaf_nodes
:最大叶子节点数。通过限制最大叶子节点数,可以防止过拟合,默认是None,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。
下面我们在sklearn中具体使用AdaBoost算法。
我们首先随机生成一些数据,并对数据进行可视化:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_gaussian_quantiles
# 生成的数据按分位数分为两类,500个样本,2个样本特征,协方差系数为2
X1, y1 = make_gaussian_quantiles(cov=2.0,n_samples=500, n_features=2,n_classes=2, random_state=666)
# 生成的数据按分位数分为两类,400个样本,2个样本特征均值都为3,协方差系数为2
X2, y2 = make_gaussian_quantiles(mean=(3, 3), cov=1.5,n_samples=400, n_features=2, n_classes=2, random_state=666)
#将两组数据合成一组数据
X = np.concatenate((X1, X2))
y = np.concatenate((y1, - y2 + 1))
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y)
下面用Adaboost来做分类拟合。根据我们在1.1节介绍的分类参数,传入决策树作为基分类器。设置决策树最大深度为2;某节点小于20则不会进行划分;叶子结点最小样本数为5;然后选择SAMME算法,构造200个弱分类器,不算多,因此可以将学习率调小一些,也就是权重系数衰减的慢一些,设置为0.8。
bdt = AdaBoostClassifier(
DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5),
algorithm="SAMME",n_estimators=200, learning_rate=0.8)
bdt.fit(X, y)
然后就可以打印输出一下当前参数的模型分数:
print("Score:", bdt.score(X,y))
# 输出:Score: 0.9133333333333333
单纯从分数上来看,该模型拟合训练集数据的分数还不错。当然了,分数高并不一定好,也有可能是过拟合。
下面我们调整n_estimators
参数以及learning_rate
,观察其对效果的影响。
将最大弱分离器个数从200增加到300。再来看看拟合分数。
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5),
algorithm="SAMME",n_estimators=300, learning_rate=0.8)
bdt.fit(X, y)
print("Score:", bdt.score(X,y))
# 输出:Score: 0.9622222222222222
弱分离器个数越多,则拟合程度越好,当然也越容易过拟合。
现在我们降低学习率,从上面的0.8减少到0.5,再来看看拟合分数。
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5),
algorithm="SAMME",n_estimators=300, learning_rate=0.5)
bdt.fit(X, y)
print("Score:", bdt.score(X,y))
# 输出:Score: 0.8944444444444445
由此可见,可见在同样的弱分类器的个数情况下,如果减少学习率,拟合效果会下降。也就是增加弱分类器的个数倾向于过拟合,减少学习率倾向于欠拟合。
最后我们看看当弱分类器个数为700,学习率为0.7时候的情况:
bdt = AdaBoostClassifier(DecisionTreeClassifier(max_depth=2, min_samples_split=20, min_samples_leaf=5),
algorithm="SAMME",n_estimators=600, learning_rate=0.7)
bdt.fit(X, y)
print("Score:", bdt.score(X,y))
此时的拟合分数和我们最初的300弱分类器,0.8学习率的拟合程度相当。也就是说,在这个例子中,如果学习率从0.8降到0.7,则弱分类器个数要从300增加到700才能达到类似的拟合效果。
这篇文章参考了刘建平老师的博客:https://www.cnblogs.com/pinard/p/6136914.html
AdaBoost算法即可以用来做回归,也可以用来做分类。对于sklearn中模型的参数,我们要做到心中有数,设置参数及不要过拟合,也不要欠拟合。当然了,掌握模型最好的办法就是使用它!加油,奥利给!