AdaBoost提升树原理
提升树算法与线性回归模型模型的思想类似,所不同的是该算法实现了多棵基础决策树f(x)的加权运算。最具代表性的提升树为AdaBoost算法。
对于AdaBoost算法而言,每棵基础决策树都是基于前一棵基础决策树的分类结果对样本点设置不同的权重。
如果在前一棵基础决策树中将某样本点预测错误,就会增大该样本点的权重,否则会相应降低样本点的权重。
再构建下一棵基础决策树时更加关注权重大的样本点。
函数介绍
# AdaBoost分类
AdaBoostClassifier(base_estimator=None, n_estimators=50,
learning_rate=1.0, algorithm='SAMME.R', random_state=None)
# AdaBoost回归
AdaBoostRegressor(base_estimator=None, n_estimators=50,
learning_rate=1.0, loss='linear', random_state=None)
base_estimator:用于指定提升算法所应用的基础分类器,默认为分类决策树(CART),
也可以是其他基础分类器,但分类器必须支持带样本权重学习,如神经网络。
n_estimators:用于指定基础分类器的数量,默认为50个。但模型在训练集中得到完美的拟合后,
可以提前结束算法,不一定非得构建完指定个数的基础分类器。
learning_rate:用于指定模型迭代的学习率或步长,默认值为1;对于较小的学习率而言,
则需要迭代更多次的基础分类器,通常情况下需要利用交叉验证法确定合理的基础分类器个数和学习率。
algorithm:⽤于指定AdaBoostClassifier分类器的算法,默认为'SAMME.R',也可以使⽤
'SAMME';使⽤'SAMME.R'时,基础模型必须能够计算类别的概率值;⼀般⽽⾔,'SAMME.R'算法
相⽐于'SAMME'算法,收敛更快、误差更⼩、迭代数量更少。
loss:⽤于指定AdaBoostRegressor回归提升树的损失函数,可以是'linear',表示使⽤线性损失函
数;也可以是'square',表示使⽤平⽅损失函数;还可以是'exponential',表示使⽤指数损失函数;
该参数的默认值为'linear'。
random_state:⽤于指定随机数⽣成器的种⼦。
GBDT梯度提升树算法
梯度提升树算法实际上是提升算法的扩展版。在原始的提升算法中,如果损失函数为平⽅损失或指数损失,求解损失函数的最⼩值问题会⾮常简单。
但如果损失函数为更⼀般的函数,⽬标值的求解就会相对复杂很多。GBDT就是⽤来解决这个问题,利⽤损失函数的负梯度值作为该轮基础模型损失值的近似,并利⽤这个近似值构建下⼀轮基础模型。
函数介绍
GradientBoostingClassifier(loss='ls',learning_rate=0.1,n_estimators=100,
min_samples_split=2,min_samples_leaf=1,max_depth=3,
nim_impurity_decrease=0.0,init=None,
max_features=None,max_leaf_nodes=None)
loss:用于指定GBDT算法的损失函数,对于分类的GBDT,可以选择'deviance'和'exponential',
分别表示对数似然损失函数和指数损失函数;对于预测的GBDT,可以选择'ls'、'lad'、'huber'和
'quantile',分别表示平方损失函数、绝对值损失函数、HUber损失函数(前两种损失函数的结合,
当误差较小时,使用平方损失函数,否则使用绝对值损失函数。误差大小的度量可以使用alpha参数指定)
和分为数回归损失函数(需通过alpha参数设置分位数)。
learning_rate:用于指定模型迭代的学习率或步长,默认值为1;对于较小的学习率而言,
则需要迭代更多的基础分类器,通常情况下需要利用交叉验证法确定合理的基础模型的个数与学习率。
n_estimators:用于指定基础模型的数量,默认为100个。
min_samples_split:用于指定每个基础模型的根节点或中间节点能够继续切分的最小样本量,默认为2。
min_samples_leaf:用于指定每个基础模型的叶子节点所包含的最小样本量,默认为1。
nim_impurity_decrease:用于指定每个基础模型叶子节点的样本权重,默认为0,
表示不考虑叶子结点的样本权重。
max_depth:用于指定每个基础模型所包含的最大深度,默认为3层。
nim_impurity_decrease:用于指定每个基础模型的节点是否继续分割的最小不纯度值,默认为0;
如果不纯度超过指定的阈值,则节点需要分割,否则不分割。
init:用于指定初始的基础模型,由于执行初始的分类或预测。
max_features:用于指定每个基础模型所包括的最多分割字段数,默认为None,
表示分割时使用所有字段;如果为具体的整数,这考虑使用对应的分割字段数;如果为0~1的浮点数,
则考虑对应百分比的字段数;如果为'sqrt',则表示最多考虑根号p个字段,与指点'auto'效果一致;
如果为'log2',则表示最多使用log2为底p的对数个字段。其中p表示数据集所有自变量的个数。
max_leaf_nodes:用于指定每个基础模型最大的叶节点个数,默认为None,表示对叶节点个数不做任何限制。
非平衡数据的特征
在实际应⽤中,类别型的因变量可能存在严重的偏倚,即类别之间的⽐例严重失调。如欺诈问题中,欺诈类观测在样本集中毕竟占少数;客户流失问题中,忠实的客户往往也是占很少⼀部分;在某营销活动的响应问题中,真正参与活动的客户也同样只是少部分。
如果数据存在严重的不平衡,预测得出的结论往往也是有偏的,即分类结果会偏向于较多观测的类。为了解决数据的⾮平衡问题,2002年Chawla提出了SMOTE算法,即合成少数过采样技术,它是基于随机过采样算法的⼀种改进⽅案。
SMOTE算法的基本思想就是对少数类别样本进⾏分析和模拟,并将⼈⼯模拟的新样本添加到数据集中,进⽽使原始数据中的类别不再严重失衡。
SMOTE算法的步骤
- 采样最邻近算法,计算出每个少数类样本的K个近邻。
- 从K个近邻中随机挑选N个样本进⾏随机线性插值。
- 构造新的少数类样本。
- 将新样本与原数据合成,产⽣新的训练集。
函数介绍
SMOTE(ratio='auto', random_state=None, k_neighbors=5, m_neighbors=10)
ratio:⽤于指定重抽样的⽐例,如果指定字符型的值,可以是'minority'(表示对少数类别的样本进
⾏抽样)、'majority'(表示对多数类别的样本进⾏抽样)、'not minority'(表示采⽤⽋采样⽅
法)、'all'(表示采⽤过采样⽅法),默认为'auto',等同于'all'和'not minority'。如果指定
字典型的值,其中键为各个类别标签,值为类别下的样本量。
random_state:⽤于指定随机数⽣成器的种⼦,默认为None,表示使⽤默认的随机数⽣成器。
k_neighbors:指定近邻个数,默认为5个。
m_neighbors:指定从近邻样本中随机挑选的样本个数,默认为10个。
XGBoost算法的介绍
XGBoost是由传统的GBDT模型发展⽽来的,GBDT模型在求解最优化问题时应⽤了⼀阶导技术,⽽XGBoost则使⽤损失函数的⼀阶和⼆阶导,⽽且可以⾃定义损失函数,只要损失函数可⼀阶和⼆阶求导。
XGBoost算法相⽐于GBDT算法还有其他优点,例如⽀持并⾏计算,⼤⼤提⾼算法的运⾏效率;XGBoost在损失函数中加⼊了正则项,⽤来控制模型的复杂度,进⽽可以防⽌模型的过拟合;XGBoost除了⽀持CART基础模型,还⽀持线性基础模型;XGBoost采⽤了随机森林的思想,对字段进⾏抽样,既可以防⽌过拟合,也可以降低模型的计算量。
函数介绍
XGBClassifier(max_depth=3,learning_rate=0.1,n_estimators=100,
objective='binary:logistic',booster='gbtree',gamma=0,
min_child_wight=1,reg_alpha=0,reg_lambda=1,missing=None)
max_depth:用于指定每个基础模型所包括的最大深度,默认为3层。
learning_rate:用于指定模型迭代的学习率或步长,默认为0.1。
n_estimators:用于指定基础模型的数量,默认为100个。
objective:用于指定目标函数中的损失函数类型,对于分类型的XGBoost算法,
默认的损失函数为二分类的Logistics损失(模型返回概率值);也可以是'multi:softmax',
表示用于处理多类的损失函数(模型返回类别值);还可以是'multi:softprob',与'multi:softmax'相同,所不同的是模型返回各类别对应的概率值;对于预测型的XGBoost算法,
默认的损失函数为线性回归损失。
booster:用于指定基础模型的类别,默认为'gbtree',即CART模型,也可以是'gblinear',
表示基础模型为线性模型。
gamma:用于指定节点分割所需要的最小损失函数下降值,即增益值Gain的阈值,默认为0。
min_child_wight:用于指定叶子节点中各样本点二阶导之和的最小值,默认为1。该参数的值越小
,模型越容易过拟合。
reg_alpha:用于指定L1正则项的系数,默认为0。
reg_lambda:用于指定L2正则项的系数,默认为1。
missing:用于指定缺失值的表示方法,默认为None,表示NaN即为默认值。
代码演示
# 导入第三方包
import pandas as pd
import matplotlib.pyplot as plt
# 读入数据
default = pd.read_excel(r'default of credit card.xls')
# 数据集中是否违约的客户比例
# 为确保绘制的饼图为圆形,需执行如下代码
plt.axes(aspect = 'equal')
# 中文乱码和坐标轴负号的处理
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
# 统计客户是否违约的频数
counts = default.y.value_counts()
# 绘制饼图
plt.pie(x = counts, # 绘图数据
labels=pd.Series(counts.index).map({0:'不违约',1:'违约'}), # 添加文字标签
autopct='%.1f%%' # 设置百分比的格式,这里保留一位小数)
# 显示图形
plt.show()
# 将数据集拆分为训练集和测试集
# 导入第三方包
from sklearn import model_selection
from sklearn import ensemble
from sklearn import metrics
# 排除数据集中的ID变量和因变量,剩余的数据用作自变量X
X = default.drop(['ID','y'], axis = 1)
y = default.y
# 数据拆分
X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size = 0.25, random_state = 1234)
# 构建AdaBoost算法的类
AdaBoost1 = ensemble.AdaBoostClassifier()
# 算法在训练数据集上的拟合
AdaBoost1.fit(X_train,y_train)
# 算法在测试数据集上的预测
pred1 = AdaBoost1.predict(X_test)
# 返回模型的预测效果
print('模型的准确率为:\n',metrics.accuracy_score(y_test, pred1))
print('模型的评估报告:\n',metrics.classification_report(y_test, pred1))
# 计算客户违约的概率值,用于生成ROC曲线的数据
y_score = AdaBoost1.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()
# 自变量的重要性排序
importance = pd.Series(AdaBoost1.feature_importances_, index = X.columns)
importance.sort_values().plot(kind = 'barh')
plt.show()
# 取出重要性比较高的自变量建模
predictors = list(importance[importance>0.02].index)
predictors
# 通过网格搜索法选择基础模型所对应的合理参数组合
# 导入第三方包
from sklearn.model_selection import GridSearchCV
from sklearn.tree import DecisionTreeClassifier
max_depth = [3,4,5,6]
params1 = {'base_estimator__max_depth':max_depth}
base_model = GridSearchCV(estimator = ensemble.AdaBoostClassifier(base_estimator = DecisionTreeClassifier()),
param_grid= params1, scoring = 'roc_auc', cv = 5, n_jobs = 4, verbose = 1)
base_model.fit(X_train[predictors],y_train)
# 返回参数的最佳组合和对应AUC值
base_model.best_params_, base_model.best_score_
# 通过网格搜索法选择提升树的合理参数组合
# 导入第三方包
from sklearn.model_selection import GridSearchCV
n_estimators = [100,200,300]
learning_rate = [0.01,0.05,0.1,0.2]
params2 = {'n_estimators':n_estimators,'learning_rate':learning_rate}
adaboost = GridSearchCV(estimator = ensemble.AdaBoostClassifier(base_estimator = DecisionTreeClassifier(max_depth = 3)),
param_grid= params2, scoring = 'roc_auc', cv = 5, n_jobs = 4, verbose = 1)
adaboost.fit(X_train[predictors] ,y_train)
# 返回参数的最佳组合和对应AUC值
adaboost.best_params_, adaboost.best_score_
# 使用最佳的参数组合构建AdaBoost模型
AdaBoost2 = ensemble.AdaBoostClassifier(base_estimator = DecisionTreeClassifier(max_depth = 3),
n_estimators = 300, learning_rate = 0.01)
# 算法在训练数据集上的拟合
AdaBoost2.fit(X_train[predictors],y_train)
# 算法在测试数据集上的预测
pred2 = AdaBoost2.predict(X_test[predictors])
# 返回模型的预测效果
print('模型的准确率为:\n',metrics.accuracy_score(y_test, pred2))
print('模型的评估报告:\n',metrics.classification_report(y_test, pred2))
# 计算正例的预测概率,用于生成ROC曲线的数据
y_score = AdaBoost2.predict_proba(X_test[predictors])[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()
# 运用网格搜索法选择梯度提升树的合理参数组合
learning_rate = [0.01,0.05,0.1,0.2]
n_estimators = [100,300,500]
max_depth = [3,4,5,6]
params = {'learning_rate':learning_rate,'n_estimators':n_estimators,'max_depth':max_depth}
gbdt_grid = GridSearchCV(estimator = ensemble.GradientBoostingClassifier(),
param_grid= params, scoring = 'roc_auc', cv = 5, n_jobs = 4, verbose = 1)
gbdt_grid.fit(X_train[predictors],y_train)
# 返回参数的最佳组合和对应AUC值
gbdt_grid.best_params_, gbdt_grid.best_score_
# 基于最佳参数组合的GBDT模型,对测试数据集进行预测
pred = gbdt_grid.predict(X_test[predictors])
# 返回模型的预测效果
print('模型的准确率为:\n',metrics.accuracy_score(y_test, pred))
print('模型的评估报告:\n',metrics.classification_report(y_test, pred))
# 计算违约客户的概率值,用于生成ROC曲线的数据
y_score = gbdt_grid.predict_proba(X_test[predictors])[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()
# 读入数据
creditcard = pd.read_csv(r'creditcard.csv')
# 为确保绘制的饼图为圆形,需执行如下代码
plt.axes(aspect = 'equal')
# 统计交易是否为欺诈的频数
counts = creditcard.Class.value_counts()
# 绘制饼图
plt.pie(x = counts, # 绘图数据
labels=pd.Series(counts.index).map({0:'正常',1:'欺诈'}), # 添加文字标签
autopct='%.2f%%' # 设置百分比的格式,这里保留一位小数
)
# 显示图形
plt.show()
# 将数据拆分为训练集和测试集
# 删除自变量中的Time变量
X = creditcard.drop(['Time','Class'], axis = 1)
y = creditcard.Class
# 数据拆分
X_train,X_test,y_train,y_test = model_selection.train_test_split(X,y,test_size = 0.3, random_state = 1234)
# 导入第三方包
from imblearn.over_sampling import SMOTE
# 运用SMOTE算法实现训练数据集的平衡
over_samples = SMOTE(random_state=1234)
# over_samples_X,over_samples_y = over_samples.fit_sample(X_train, y_train)
over_samples_X, over_samples_y = over_samples.fit_sample(X_train.values,y_train.values.ravel())
# 重抽样前的类别比例
print(y_train.value_counts()/len(y_train))
# 重抽样后的类别比例
print(pd.Series(over_samples_y).value_counts()/len(over_samples_y))
# https://www.lfd.uci.edu/~gohlke/pythonlibs/
# 导入第三方包
import xgboost
import numpy as np
# 构建XGBoost分类器
xgboost = xgboost.XGBClassifier()
# 使用重抽样后的数据,对其建模
xgboost.fit(over_samples_X,over_samples_y)
# 将模型运用到测试数据集中
resample_pred = xgboost.predict(np.array(X_test))
# 返回模型的预测效果
print('模型的准确率为:\n',metrics.accuracy_score(y_test, resample_pred))
print('模型的评估报告:\n',metrics.classification_report(y_test, resample_pred))
# 计算欺诈交易的概率值,用于生成ROC曲线的数据
y_score = xgboost.predict_proba(np.array(X_test))[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()
# 构建XGBoost分类器
import xgboost
xgboost2 = xgboost.XGBClassifier()
# 使用非平衡的训练数据集拟合模型
xgboost2.fit(X_train,y_train)
# 基于拟合的模型对测试数据集进行预测
pred2 = xgboost2.predict(X_test)
# 混淆矩阵
pd.crosstab(pred2,y_test)
# 返回模型的预测效果
print('模型的准确率为:\n',metrics.accuracy_score(y_test, pred2))
print('模型的评估报告:\n',metrics.classification_report(y_test, pred2))
# 计算欺诈交易的概率值,用于生成ROC曲线的数据
y_score = xgboost2.predict_proba(X_test)[:,1]
fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)
# 计算AUC的值
roc_auc = metrics.auc(fpr,tpr)
# 绘制面积图
plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')
# 添加边际线
plt.plot(fpr, tpr, color='black', lw = 1)
# 添加对角线
plt.plot([0,1],[0,1], color = 'red', linestyle = '--')
# 添加文本信息
plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)
# 添加x轴与y轴标签
plt.xlabel('1-Specificity')
plt.ylabel('Sensitivity')
# 显示图形
plt.show()