scikit-learn(sklearn)GBDT算法类库介绍

梯度提升树(GBDT)原理一文中介绍了GBDT的原理。本文将介绍scikit-learn中GBDT算法类库的使用和调参。

 
1. scikit-learn GBDT类库概述
在scikit-learn中,GBDT类库包含GradientBoostingClassifier和GradientBoostingRegressor,其中GradientBoostingClassifier用于分类, 而GradientBoostingRegressor用于回归。它们的参数完全相同,不过有些参数比如损失函数loss的可选择项并不相同。我们把重要的参数分为两类,第一类是Boosting框架的重要参数,第二类是弱学习器CART回归决策树的重要参数。
下面我们就从这两方面来介绍这些参数的使用和调参。
 
2. GBDT类库Boosting框架参数
首先介绍Boosting框架的重要参数。GradientBoostingClassifier和GradientBoostingRegressor的绝大部分参数都相同,我们用下面的表格来详细说明。
参数 GradientBoostingClassifier GradientBoostingRegressor
n_estimators 弱学习器的最大迭代次数,或者说最大的弱学习器个数。一般来说n_estimators太小,容易欠拟合,而n_estimators太大,又容易过拟合,通常需要选择一个适中的数值,默认值是50。在实际的调参过程中,常常将它和参数learning_rate一起来考虑。
learning_rate 弱学习器的权重缩减系数ν,原始强学习器的迭代公式加上正则化项以后,变成了scikit-learn(sklearn)GBDT算法类库介绍。ν的取值范围是0<ν≤1。对于同样的训练集拟合效果,较小的ν意味着需要进行更多的弱学习器迭代次数。通常用步长和迭代最大次数一起来决定算法的拟合效果。所以参数n_estimators和learning_rate需要一起来调参。一般来说,可以从一个小一点的ν开始调参,其默认值是1。
subsample 梯度提升树(GBDT)原理一文中正则化章节讲到的子采样比例,取值为(0,1]。这里的子采样和随机森林不一样,随机森林使用的是有放回采样,而这里使用的是无放回采样。如果取值为1,则使用全部样本,等于没有使用子采样。如果取值小于1,则只有一部分样本会去拟合GBDT的决策树。选择小于1的值可以减少方差,防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低,推荐在[0.5, 0.8]之间选择。
init 初始化的弱学习器,对应梯度提升树(GBDT)原理一文中的scikit-learn(sklearn)GBDT算法类库介绍,如果不输入,则用训练集样本来做样本集的初始化分类回归预测,否则使用init参数提供的学习器来做初始化分类回归预测。一般用在我们对数据有先验知识或者之前做过拟合的时候,否则就不用考虑这个参数了。
loss GradientBoostingClassifier类的损失函数有对数似然损失函数"deviance"和指数损失函数"exponential"两个选项。默认值是对数似然损失函数"deviance"。一般来说,推荐使用默认的对数似然损失函数"deviance",它对于二元分类和多元分类都有较好的优化效果。而指数损失函数"exponential"相当于执行了Adaboost算法。 GradientBoostingRegressor类的损失函数有均方差损失函数"ls"、绝对损失函数"lad"、Huber损失函数"huber"和分位数损失函数"quantile"。默认是均方差损失函数"ls"。一般来说,如果数据的噪声点不多,用默认的均方差损失函数"ls"比较好。如果噪声点较多,则推荐使用抗噪声的Huber损失函数"huber"。如果需要对训练集进行分段预测,则推荐使用分位数损失函数"quantile"。
alpha GradientBoostingClassifier类没有这个参数。 当使用Huber损失函数"huber"和分位数损失函数"quantile"时,需要指定分位数的值。默认值是0.9,如果噪声点较多,可以适当降低这个参数的值。
3. GBDT类库弱学习器参数
接下来介绍GradientBoostingClassifier和GradientBoostingRegressor的弱学习器参数,由于GBDT使用了CART回归决策树作为弱学习器,因此它的参数基本上来源于决策树类,也就是说,与DecisionTreeClassifier和DecisionTreeRegressor的参数基本相同。在scikit-learn(sklearn)决策树算法类库介绍一文中已经对这两个类的参数做了详细的解释。这里我们只是强调一下其中需要注意的几个最重要的参数:
  1) 划分时考虑的最大特征数max_features:可以使用多种类型值,默认是"None",意味着划分时考虑所有的特征数;如果是"log2",意味着划分时最多考虑log2N(以2为底N的对数)个特征;如果是"sqrt"或者"auto",意味着划分时最多考虑N的平方根个特征;如果是整数,代表考虑的特征绝对数;如果是浮点数,代表考虑特征数的百分比,即考虑(百分比xN)取整后的特征数。其中N是样本总特征数。一般来说,如果样本特征数不多,比如小于50,使用默认值"None"就可以了,如果特征数非常多,则可以灵活地使用上述其它取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。
  2) 决策树的最大深度max_depth:默认可以不输入,如果不输入,则不会限制决策树的深度。一般来说,数据少或者特征少的时候可以不用管这个值。如果训练集样本量大,特征多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取10-100之间。
  3) 内部节点再划分所需最小样本数min_samples_split:这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会再进行划分,默认值是2。如果样本量不大,不需要管这个值;如果样本数量级非常大,则推荐增大这个值。
  4) 叶子节点最少样本数min_samples_leaf:这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于该值,则会和兄弟节点一起被剪枝。 默认值是1,可以输入最少样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本数量级非常大,则推荐增大这个值。
  5) 叶子节点最小的样本权重和min_weight_fraction_leaf:这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认值是0,就是不考虑样本权重。一般来说,如果较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要考虑这个参数了。
  6) 最大叶子节点数max_leaf_nodes:通过限制最大叶子节点数,可以防止过拟合,默认值是"None",即不限制最大的叶子节点数。如果增加了限制,算法会创建在最大叶子节点数内最优的决策树。如果特征不多,可以不用考虑这个值,但是如果特征多的话,需要加以限制,具体的值可以通过交叉验证得到。
  7) 节点划分最小不纯度min_impurity_split:这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,均方差)小于这个阈值,则该节点不再生成子节点,也就是说,该节点将成为叶子节点 。一般不推荐改动默认值1e-7。
 
4. 使用Mnist数据集测试scikit-learn的GradientBoostingClassifier
代码如下所示:
---------------------------------------------------------------------------------------------------
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score
from time import time
import numpy as np
import mnist
import roc
 
if __name__ == "__main__":
   # 读取Mnist数据集, 测试GBDT的分类模型
   mnistSet = mnist.loadLecunMnistSet()
   train_X, train_Y, test_X, test_Y = mnistSet[0], mnistSet[1], mnistSet[2], mnistSet[3]
 
   m, n = np.shape(train_X)
   idx = range(m)
   np.random.shuffle(idx)
 
   print "\n**********测试GradientBoostingClassifier类**********"
   t = time()
   model = GradientBoostingClassifier(max_features=90, max_depth=40, min_samples_split=8, min_samples_leaf=3,
                                n_estimators=1200, learning_rate=0.05, subsample=0.95)
   # 拟合训练数据集
   model.fit(train_X, train_Y)
   # 预测训练集
   train_Y_hat = model.predict(train_X[idx])
   print "训练集精确度: ", accuracy_score(train_Y[idx], train_Y_hat)
   # 预测测试集
   test_Y_hat = model.predict(test_X)
   print "测试集精确度: ", accuracy_score(test_Y, test_Y_hat)
   print "总耗时:", time() - t, "秒"
   # 绘制ROC曲线
   n_class = len(np.unique(train_Y))
   roc.drawROC(n_class, test_Y, test_Y_hat)
---------------------------------------------------------------------------------------------------
 
5. 使用CCPP数据集测试scikit-learn的GradientBoostingRegressor
代码如下所示:
---------------------------------------------------------------------------------------------------
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import GridSearchCV, train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from time import time
import numpy as np
import pandas as pd
 
if __name__ == "__main__":
   # 读取CCPP数据集, 测试GBDT的回归模型
   data = pd.read_excel("data/CCPP/Folds5x2_pp.xlsx")
   # AT:温度, V:压力, AP:湿度, RH:压强, PE:输出电力
   # 样本特征X
   X = data[['AT', 'V', 'AP', 'RH']]
   # 数据归一化
   X = StandardScaler().fit_transform(X)
   # 样本输出Y
   Y = data[['PE']]
   # 划分训练集和测试集,将数据集的70%划入训练集,30%划入测试集
   train_X, test_X, train_Y, test_Y = train_test_split(X, Y, test_size=0.3, random_state=1)
 
   m, n = np.shape(train_X)
   idx = range(m)
   np.random.shuffle(idx)
 
   print "\n**********测试GradientBoostingRegressor类**********"
   t = time()
   model = GradientBoostingRegressor(learning_rate=0.1, n_estimators=1500, max_depth=5, min_samples_split=9,
                               min_samples_leaf=2, subsample=0.95)
   # 拟合训练数据集
   model.fit(train_X, train_Y.values.ravel())
   # 预测测试集
   test_Y_pred = model.predict(test_X)
   print "测试集MSE:", mean_squared_error(test_Y, test_Y_pred)
   print "测试集RMSE:", np.sqrt(mean_squared_error(test_Y, test_Y_pred))
   print "总耗时:", time() - t, "秒"
---------------------------------------------------------------------------------------------------
 
参考:http://www.cnblogs.com/pinard/p/6143927.html
发布了44 篇原创文章 · 获赞 130 · 访问量 137万+

猜你喜欢

转载自blog.csdn.net/gb4215287/article/details/105159607
今日推荐