【Python机器学习实战】决策树与集成学习(五)——集成学习(3)GBDT应用实例
前面对GBDT的算法原理进行了描述,通过前文了解到GBDT是以回归树为基分类器的集成学习模型,既可以做分类,也可以做回归,由于GBDT设计很多CART决策树相关内容,就暂不对其算法流程进行实现,本节就根据具体数据,直接利用Python自带的Sklearn工具包对GBDT进行实现。
数据集采用之前决策树中的红酒数据集,之前的数据集我们做了类别的处理(将连续的数据删除了,且小批量数据进行了合并),这里做同样的处理,将其看为一个多分类问题。
首先依旧是读取数据,并对数据进行检查和预处理,这里就不再赘述,所得数据情况如下:
wine_df = pd.read_csv('./winequality-red.csv', delimiter=';', encoding='utf-8')
columns_name = list(wine_df.columns)
for name in columns_name:
q1, q2, q3 = wine_df[name].quantile([0.25, 0.5, 0.75])
IQR = q3 - q1
lower_cap = q1 - 1.5 * IQR
upper_cap = q3 + 1.5 * IQR
wine_df[name] = wine_df[name].apply(lambda x: upper_cap if x > upper_cap else (lower_cap if (x < lower_cap) else x))
sns.countplot(wine_df['quality'])
wine_df.describe()
接下来就是先导入使用GBDT所需要用到的工具包:
# 这里采用的是回归,因此是GradientBoostingRegressor,如果是分类则使用GradientBoostingClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.metrics import mean_squared_error
from sklearn import metrics
from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt
然后依旧是对数据进行切分,将数据分为训练集和测试集:
trainX, testX, trainY, testY = train_test_split(wine_df.drop(['quality']), wine_df['quality'], test_size=0.3, random_state=22)
然后就是建立模型:
model = GradientBoostingClssifier()
这里模型就有很多可选参数,用于调整模型,下面进行具体介绍:
首先是Boosting的框架的参数,这里在使用GradientBoostingRegressor和GradientBoostingClassifier是一样的,具体包括:
- n_estimators:弱分类器的最大迭代次数,也就是多少个弱分类器组成,默认值为100。当该值越小时容易欠拟合,太大又会过拟合;
- learning_rate:学习率,这在前面原理部分有进行介绍,默认值为1,较小的learning_rate意味着步长较小,需要更多的分类器才能够达到效果,通常需要与上面n_eatimators结合共同调参;
- subsample:这也是一种正则化的方法,在正则化中有提到过,取值为(0,1],默认值为1,即不进行子采样;
- init:初始化的弱分类器,即f0(x),默认为采用训练样本初始化的分类回归预测,若赋予值需要根据一定的先验知识或者预拟合;
- loss:即损失函数,在原理篇介绍过相关损失函数,对于分类和回归中损失函数是不相同的:
- 在分类模型中,有对数似然损失函数“deviance”和指数损失函数“exponential”,默认为对数似然损失函数,一般选择默认,因为选择指数损失函数“exponential”又退回到AdaBoost了;
- 在回归模型中,有方差损失“ls”、绝对损失“lad”、Huber损失“huber”和分位数损失“quantile”,默认为均方差损失“ls”,一般来说,数据的噪音不多,采用均方差损失即可,噪音点较多,则推荐使用抗噪能力较强的Huber损失,如果需要对训练集进行分段预测时则采用分位数损失“quantile”;
- alpha:这个参数只存在于GradientBoostingRegressor中,当使用Huber损失和分位数损失时,需要指定分位数的值,默认为0.9,如果噪音数据较多,可以适当降低这个值。
然后就是弱分类器有关的参数值,弱分类器采用的CART回归树,决策树中的相关参数在决策树实现部分已经进行介绍,这里主要对其中一些重要的参数再进行解释:
- max_features:划分树时所用到的最大特征数,默认为None,即使用全部的特征,当取值为“log2”时,划分时使用log2N个特征,如果是“sqrt”和“auto”则分别对应着最多考虑√N¯个特征,如果是整数,则代表考虑特征的绝对数,如果是浮点数,则代表考虑总特征数的百分比。一般来说样本总特征数小于50,直接采用50即可,当样本特征数量较大时,再考虑其他特征数;
- max_depth:每个弱分类器的最大深度,默认为不输入,树的深度为3,一般对于数据较少或者特征较少,该值不需要输入,当样本数量和特征数量过于庞大,推荐使用最大深度限制,一般选择10~100;
- min_samples_split:内部节点再划分所需最小的样本数,它限制了子树进一步划分的条件,如果节点的样本数小于min_samples_split则不再进行分裂。默认值为2,若样本数量较大,则推荐增大该值;
- min_samples_leaf:叶子节点最小样本数,该值限定了叶子节点的最小样本数,默认值为1,如果叶子节点样本数量小于该值,则会和兄弟节点一起被剪枝,如果样本量巨大,则推荐增加该值;
- min_weight_fraction_leaf:叶子节点最小样本权重和,该值限制了叶子节点所有样本权重和的最小值,若小于该值,则会和兄弟节点被剪枝,默认值为0,即不考虑权重。当样本分类问题中类别分布偏差较大,则会引入样本权重,需要调整该值;
- max_leaf_nodes:最大叶子节点数,通过限制最大叶子结点数防止过拟合,默认为None。如果加入了限制,则算法会建立在最大叶子节点数内最优的决策树,当样本特征数量过多的话,可以限制该值;
- min_impurity_split:节点划分最小不纯度,这个值限定了决策树的生长,若节点的不纯度(即基尼系数)小于这个值,则该节点不再生长,即为叶子结点,默认值为1e-7,一般不推荐修改。
上述即为模型的主要参数,这里首先全部使用默认值,对样本进行训练:
model.fit(trainX, trainY)
print("模型在训练集上分数为%s"%model.score(trainX, trainY))
pred_prob = model.predict_proba(trainX)
print('AUC:', metrics.roc_auc_score(np.array(trainY), pred_prob, multi_class='ovo'))
模型在训练集上分数为0.8817106460418562
AUC: 0.9757763363472337
可以看到在训练集上AUC表现还不错,模型的分数但并不高,尝试调整训练参数,首先对于迭代次数和学习率共同进行调整:
param_test1 = {'n_estimators': range(10, 501, 10), 'learning_rate': np.linspace(0.1, 1, 10)}
gsearch = GridSearchCV(estimator=GradientBoostingClassifier(learning_rate=1,
min_samples_split=2,
min_samples_leaf=1,
max_depth=3,
max_features=None,
subsample=0.8,
), param_grid=param_test1, cv=5)
gsearch.fit(trainX, trainY) means = gsearch.cv_results_['mean_test_score']
params = gsearch.cv_results_['params']
for i in range(len(means)):
print(params[i], means[i]) print(gsearch.best_params_)
print(gsearch.best_score_) # {'learning_rate': 0.2, 'n_estimators': 100}
找出最好的n_estimators=100和learning_rate=0.2,将其定下来,带回模型,再次验证:
model = GradientBoostingClassifier(n_estimators=100, learning_rate=0.2,subsample=0.8)
model.fit(trainX, trainY)
print("模型在训练集上分数为%s"%model.score(trainX, trainY))
pred_prob = model.predict_proba(trainX)
print('AUC:', metrics.roc_auc_score(np.array(trainY), pred_prob, multi_class='ovo'))
模型在训练集上分数为0.9663330300272975
AUC: 0.9977791940084874
可以看到拟合效果已经很好了,再次调整参数,接下来调整弱分类器中的参数,max_depth和min_samples_split:
param_test1 = {'max_depth': range(1, 6, 1), 'min_samples_split': range(1, 101, 10)}
gsearch2 = GridSearchCV(estimator=GradientBoostingClassifier(n_estimators=100,
learning_rate=0.2,
max_features=None,
min_samples_leaf=1,
subsample=0.8,
), param_grid=param_test1, cv=5)
gsearch2.fit(trainX, trainY)
means = gsearch2.cv_results_['mean_test_score']
params = gsearch2.cv_results_['params']
for i in range(len(means)):
print(params[i], means[i]) print(gsearch2.best_params_)
print(gsearch2.best_score_)
找出了树的最大深度为5,由于最小样本划分数量同叶子节点最小样本数量有一定关系,暂时不能定下min_samples_split,将其同min_samples_leaf共同调整:
param_test1 = {'min_samples_leaf': range(1, 101, 10), 'min_samples_split': range(1, 101, 10)}
gsearch3 = GridSearchCV(estimator=GradientBoostingClassifier(n_estimators=100,
learning_rate=0.2,
max_features=None,
max_depth=5,
subsample=0.8,
), param_grid=param_test1, cv=5)
gsearch3.fit(trainX, trainY)
means = gsearch3.cv_results_['mean_test_score']
params = gsearch3.cv_results_['params']
for i in range(len(means)):
print(params[i], means[i]) print(gsearch3.best_params_)
print(gsearch3.best_score_) # {'min_samples_leaf': 21, 'min_samples_split': 41}
可以找出最小样本划分数量21和叶子节点最小数量,我们将这些参数再带回模型:
model = GradientBoostingClassifier(n_estimators=100, learning_rate=0.2, max_depth=5, min_samples_leaf=21, min_samples_split=41, subsample=0.8)
model.fit(trainX, trainY)
print("模型在训练集上分数为%s"%model.score(trainX, trainY))
pred_prob = model.predict_proba(trainX)
print('AUC:', metrics.roc_auc_score(np.array(trainY), pred_prob, multi_class='ovo'))
模型在训练集上分数为1.0
AUC: 1.0
可以看到在训练集上已经完美拟合了,但为了验证模型,我们需要再分离出一部分用于验证模型的数据集:
validX, tX, validY, tY = train_test_split(testX, testY, test_size=0.2)
然后使用验证集,验证模型:
print("模型在测试集上分数为%s"%metrics.accuracy_score(validY, model.predict(validX)))
pred_prob = model.predict_proba(validX)
print('AUC test:', metrics.roc_auc_score(np.array(validY), pred_prob, multi_class='ovo'))
模型在测试集上分数为0.726790450928382
AUC test: 0.8413890948027345
可以看到模型在验证集上表现并不是很好,上面模型存在一定的过拟合问题,继续调整参数,通过调整max_features来提高模型的泛华能力:
param_test1 = {'max_features': range(3, 12, 1)}
gsearch4 = GridSearchCV(estimator=GradientBoostingClassifier(n_estimators=100,
learning_rate=0.2,
min_samples_leaf=21,
min_samples_split=41,
max_depth=5,
subsample=0.8,
), param_grid=param_test1, cv=5)
gsearch4.fit(trainX, trainY)
means = gsearch4.cv_results_['mean_test_score']
params = gsearch4.cv_results_['params']
for i in range(len(means)):
print(params[i], means[i]) print(gsearch4.best_params_)
print(gsearch4.best_score_) # {'max_features': 5}
进一步调整subsamples:
param_test1 = {'subsample': np.linspace(0.1, 1, 10)}
gsearch5 = GridSearchCV(estimator=GradientBoostingClassifier(n_estimators=100,
learning_rate=0.2,
min_samples_leaf=21,
min_samples_split=41,
max_depth=5,
max_features=5
), param_grid=param_test1, cv=5)
gsearch5.fit(trainX, trainY)
means = gsearch5.cv_results_['mean_test_score']
params = gsearch5.cv_results_['params']
for i in range(len(means)):
print(params[i], means[i]) print(gsearch5.best_params_)
print(gsearch5.best_score_) # {'subsample': 0.7}
到这里基本主要参数都进行了调整,带回到模型中:
model = GradientBoostingClassifier(n_estimators=100, learning_rate=0.2, max_depth=5, min_samples_leaf=21, min_samples_split=41, max_features=5, subsample=0.7)
model.fit(trainX, trainY)
print("模型在训练集上分数为%s"%model.score(trainX, trainY))
pred_prob = model.predict_proba(trainX)
print('AUC:', metrics.roc_auc_score(np.array(trainY), pred_prob, multi_class='ovo'))
模型在训练集上分数为0.9990900818926297
AUC: 0.9999992641648271
有略微下降,因为通过提高模型的泛华能力,会增大模型的偏差,然后利用验证集验证模型:
print("模型在测试集上分数为%s"%metrics.accuracy_score(validY, model.predict(validX)))
pred_prob = model.predict_proba(validX)
print('AUC test:', metrics.roc_auc_score(np.array(validY), pred_prob, multi_class='ovo')) 模型在测试集上分数为0.7161803713527851
AUC test: 0.8429467644071055
进一步将模型的迭代次数增加一倍,学习率减半:
model = GradientBoostingClassifier(n_estimators=200, learning_rate=0.1, max_depth=5, min_samples_leaf=21, min_samples_split=41, max_features=5, subsample=0.7)
model.fit(trainX, trainY)
print("模型在训练集上分数为%s"%model.score(trainX, trainY))
pred_prob = model.predict_proba(trainX)
print('AUC:', metrics.roc_auc_score(np.array(trainY), pred_prob, multi_class='ovo'))
# validX, tX, validY, tY = train_test_split(testX, testY, test_size=0.2)
print("模型在测试集上分数为%s"%metrics.accuracy_score(validY, model.predict(validX)))
pred_prob = model.predict_proba(validX)
print('AUC test:', metrics.roc_auc_score(np.array(validY), pred_prob, multi_class='ovo'))
模型在训练集上分数为0.9990900818926297
AUC: 1.0
模型在测试集上分数为0.7427055702917772
AUC test: 0.851199242237048
可以看到模型泛化能力有略微增强,可以尝试进一步上述步骤,当迭代次数增加到一定程度,学习率减小到一定程度,模型泛化能力下降,可能是由于步长过小导致拟合和泛化能力下降。
以上就是GBDT的一个实例和参数调整过程,这里使用的是CvGrid网格遍历搜索调参的方法,从结果来看并不理想,可能是由于样本分布的问题,还有就是在进行数据处理的时候采用了replace直接更改了样本的标签,在测试集中这部分数据可能会预测错误。 后面会继续查找原因,调整数据集再次进行训练。
本例仅作为一个调参的学习过程,主要对GBDT中的参数有一个初步的了解,也是刚开始学习调参的方法,参数设置的也比较粗糙,后续会找一些新的数据集进一步对调参进行学习。
【Python机器学习实战】决策树与集成学习(五)——集成学习(3)GBDT应用实例的更多相关文章
- 【Python机器学习实战】决策树和集成学习(一)
摘要:本部分对决策树几种算法的原理及算法过程进行简要介绍,然后编写程序实现决策树算法,再根据Python自带机器学习包实现决策树算法,最后从决策树引申至集成学习相关内容. 1.决策树 决策树作为一种常 ...
- 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试
机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...
- Python 机器学习实战 —— 监督学习(下)
前言 近年来AI人工智能成为社会发展趋势,在IT行业引起一波热潮,有关机器学习.深度学习.神经网络等文章多不胜数.从智能家居.自动驾驶.无人机.智能机器人到人造卫星.安防军备,无论是国家级军事设备还是 ...
- Python 机器学习实战 —— 无监督学习(上)
前言 在上篇<Python 机器学习实战 -- 监督学习>介绍了 支持向量机.k近邻.朴素贝叶斯分类 .决策树.决策树集成等多种模型,这篇文章将为大家介绍一下无监督学习的使用.无监督学习顾 ...
- Python 机器学习实战 —— 监督学习(上)
前言 近年来AI人工智能成为社会发展趋势,在IT行业引起一波热潮,有关机器学习.深度学习.神经网络等文章多不胜数.从智能家居.自动驾驶.无人机.智能机器人到人造卫星.安防军备,无论是国家级军事设备还是 ...
- Python 机器学习实战 —— 无监督学习(下)
前言 在上篇< Python 机器学习实战 -- 无监督学习(上)>介绍了数据集变换中最常见的 PCA 主成分分析.NMF 非负矩阵分解等无监督模型,举例说明使用使用非监督模型对多维度特征 ...
- python机器学习实战(一)
python机器学习实战(一) 版权声明:本文为博主原创文章,转载请指明转载地址 www.cnblogs.com/fydeblog/p/7140974.html 前言 这篇notebook是关于机器 ...
- python机器学习实战(二)
python机器学习实战(二) 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7159775.html 前言 这篇noteboo ...
- python机器学习实战(四)
python机器学习实战(三) 版权声明:本文为博主原创文章,转载请指明转载地址 www.cnblogs.com/fydeblog/p/7364317.html 前言 这篇notebook是关于机器学 ...
- 机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据
机器学习实战(Machine Learning in Action)学习笔记————09.利用PCA简化数据 关键字:PCA.主成分分析.降维作者:米仓山下时间:2018-11-15机器学习实战(Ma ...
随机推荐
- 【Azure 应用服务】App Service 通过配置web.config来添加请求返回的响应头(Response Header)
问题描述 在Azure App Service上部署了站点,想要在网站的响应头中加一个字段(Cache-Control),并设置为固定值(Cache-Control:no-store) 效果类似于本地 ...
- 抽奖动画 - lao虎机抽奖
本文介绍一个lao虎机抽奖动画的实现,lao虎机抽奖在各类商家营销活动中非常常见,这里主要介绍动画的实现过程,其他细节不做详细分析. ps:lao虎机是敏感词,博客园不允许出现,所有老用拼音. 1. ...
- Netty入门(三):EventLoop
前言 Netty系列索引: 1.Netty入门(一):ByteBuf 2.Netty入门(二):Channel IO相关: 1.Java基础(一):I/O多路复用模型及Linux中的应用 上文提到,早 ...
- js遍历终极大法--再也不用苦逼的for循环了
while循环 while后面跟循环条件和执行语句,只要满足条件,就会一直执行里面的执行 var i = 0 while(i<10){ console.log(i) i++ } do...whi ...
- SpringBoot 如何进行参数校验,老鸟们都这么玩的!
大家好,我是飘渺. 前几天写了一篇 SpringBoot如何统一后端返回格式?老鸟们都是这样玩的! 阅读效果还不错,而且被很多号主都转载过,今天我们继续第二篇,来聊聊在SprinBoot中如何集成参数 ...
- SpringBoot | 4.1 SpringMVC的自动配置
目录 前言 1. SpringMVC框架的设计与流程 1.1 SpringMVC框架的示意图 1.2 SpringMVC的组件流程 2. *自动配置的源码分析 2.1 导入Web场景启动器 2.2 找 ...
- spring-security oauth2.0简单集成
github地址:https://github.com/intfish123/oauth.git 需要2个服务,一个认证授权服务,一个资源服务 认证授权服务为客户端颁发令牌,资源服务用于客户端获取用户 ...
- Android WorkManager使用入门
WorkManager使用入门 WorkManager提供了任务调度功能,我们可以对工作进行标记或命名. 我们用一个示例来演示如何使用WorkManager.本文使用Kotlin. 入门示例 grad ...
- python爬虫:了解JS加密爬取网易云音乐
python爬虫:了解JS加密爬取网易云音乐 前言 大家好,我是"持之以恒_liu",之所以起这个名字,就是希望我自己无论做什么事,只要一开始选择了,那么就要坚持到底,不管结果如何 ...
- ATM取款机优化需求的用例设计
案例设计需求 有一个ATM取款系统,现对于取款功能进行了如何需求变更:碑只能取面额是100元(如取500,输出5张100元),现在功能修改为,可以取面额是10元.50元和100元的,其余功能不变,用户 ...