②机器学习分类算法之XGBoost(集成学习算法)

简介: 机器学习分类算法之XGBoost(集成学习算法)

调参步骤及思想

选择较高的学习速率(learning rate)。一般情况下,学习速率的值为0.1。但是,对于不同的问题,理想的学习速率有时候会在0.05到0.3之间波动。选择对应于此学习速率的理想决策树数量。XGBoost有一个很有用的函数“cv”,这个函数可以在每一次迭代中使用交叉验证,并返回理想的决策树数量。


对于给定的学习速率和决策树数量,进行决策树特定参数调优(max_depth, min_child_weight, gamma, subsample, colsample_bytree)。在确定一棵树的过程中,我们可以选择不同的参数,待会儿我会举例说明。


xgboost的正则化参数的调优。(lambda, alpha)。这些参数可以降低模型的复杂度,从而提高模型的表现。


降低学习速率,确定理想参数。


XGBoost代码案例

XGBoost效果确实不错,但是前提是要将参数不断地优化和调整,这样最终才能得到一个较好的模型,下面依然以一个实际的案例进行XGBoost代码演示


#导入所需要的包
from sklearn.metrics import precision_score
from sklearn.model_selection import train_test_split
import xgboost as xgb
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report
from sklearn.model_selection import GridSearchCV #网格搜索
import matplotlib.pyplot as plt#可视化
import seaborn as sns#绘图包
# 忽略警告
import warnings
warnings.filterwarnings("ignore")

相关性分析

plt.figure(figsize=(20,20))
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
sns.heatmap(df.corr(),cmap="YlGnBu",annot=True)
plt.title("相关性分析图")

image.png

XGBoost无参数模型


model=xgb.XGBClassifier()
# 训练模型
model.fit(X_train,y_train)
# 预测值
y_pred = model.predict(X_test)
'''
评估指标
'''
# 求出预测和真实一样的数目
true = np.sum(y_pred == y_test )
print('预测对的结果数目为:', true)
print('预测错的的结果数目为:', y_test.shape[0]-true)
# 评估指标
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('预测数据的精确率为:{:.4}%'.format(
      precision_score(y_test,y_pred)*100))
print('预测数据的召回率为:{:.4}%'.format(
      recall_score(y_test,y_pred)*100))
# print("训练数据的F1值为:", f1score_train)
print('预测数据的F1值为:',
      f1_score(y_test,y_pred))
print('预测数据的Cohen’s Kappa系数为:',
      cohen_kappa_score(y_test,y_pred))
# 打印分类报告
print('预测数据的分类报告为:','
',
      classification_report(y_test,y_pred))

效果还是不错,比之前用其他的模型反复的调优的效果还好,但是这不是XGBoost的最终效果

image.png

n_estimators(学习曲线)

scorel = []
for i in range(0,300,10):
    model = xgb.XGBClassifier(n_estimators=i+1,
                                 n_jobs=--4,
                                 random_state=90).fit(X_train,y_train)
    score = model.score(X_test,y_test)
    scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*10)+1)  #作图反映出准确度随着估计器数量的变化,51的附近最好
plt.figure(figsize=[20,5])
plt.plot(range(1,300,10),scorel)
plt.show()


image.png

继续迭代优化,缩小范围


scorel = []
for i in range(0,20,1):
    model = xgb.XGBClassifier(n_estimators=i+1,
                                 n_jobs=--4,
                                 random_state=90).fit(X_train,y_train)
    score = model.score(X_test,y_test)
    scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*1)+1)  #作图反映出准确度随着估计器数量的变化,51的附近最好
plt.figure(figsize=[20,5])
plt.plot(range(0,20,1),scorel)
plt.show()

image.png

max_depth(学习曲线)

scorel = []
for i in range(0,20,1):
    model = xgb.XGBClassifier(max_depth =i,
                                 n_estimators=8,
                                 n_jobs=--4,
                                 random_state=90).fit(X_train,y_train)
    score = model.score(X_test,y_test)
    scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*1)+1)  #作图反映出准确度随着估计器数量的变化,51的附近最好
plt.figure(figsize=[20,5])
plt.plot(range(0,20,1),scorel)
plt.show()


image.png


效果有所提升,继续调优,但是我们知道XGBoost的参数过于的多,如果按照传统的学习曲线迭代调优,效果可能局限在局部最优 ,下面试试XGBoost的交叉验证


调整max_depth 和min_child_weight

param_test1 = {
# 'n_estimators':list(range(3,15,1)),
 'max_depth':list(range(3,10,2)),
 'min_child_weight':list(range(1,6,2))
}
gsearch1 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=8, max_depth=8,
 min_child_weight=1, gamma=0, subsample=0.8, colsample_bytree=0.8,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27), 
 param_grid = param_test1, scoring='roc_auc',iid=False, cv=5)
gsearch1=gsearch1.fit(X,y)
gsearch1.best_params_, gsearch1.best_score_
({'max_depth': 3, 'min_child_weight': 5}, 0.9200952807471878)

进一步调整


param_test1 = {
 'max_depth':list(range(8,11,1)),
 'min_child_weight':list(range(1,4,1))
}
gsearch1 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=7, max_depth=3,
 min_child_weight=5, gamma=0, subsample=0.8, colsample_bytree=0.8,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1, seed=27), 
 param_grid = param_test1, scoring='roc_auc',iid=False, cv=5)
gsearch1.fit(X,y)
gsearch1.best_params_, gsearch1.best_score_
({'max_depth': 8, 'min_child_weight': 3}, 0.9158850465045336)

调整gamma

param_test3 = {
 'gamma':[i/10.0 for i in range(0,5)]
}
gsearch3 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=8, max_depth=8,
 min_child_weight=3, gamma=0, subsample=0.8, colsample_bytree=0.8,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27), 
 param_grid = param_test3, scoring='roc_auc',iid=False, cv=5)
gsearch3.fit(X,y)
gsearch3.best_params_, gsearch3.best_score_

({'gamma': 0.4}, 0.9103697321364825)

调整subsample 和colsample_bytree

param_test5 = {
 'subsample':[i/100.0 for i in range(75,90,5)],
 'colsample_bytree':[i/100.0 for i in range(75,90,5)]
}
gsearch5 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=8, max_depth=8,
 min_child_weight=3, gamma=0.4, subsample=0.8, colsample_bytree=0.8,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27), 
 param_grid = param_test5, scoring='roc_auc',iid=False, cv=5)
gsearch5.fit(X_train,y_train)
gsearch5.best_params_, gsearch5.best_score_
({'colsample_bytree': 0.85, 'subsample': 0.85}, 0.9420290874342445)

效果一下就有了显著的提升,继续调参,因为这个参数还是比较的重要有放回随机抽样


调整正则化参数

param_test6 = {
 'reg_alpha':[1e-5, 1e-2, 0.1, 1, 100]
}
gsearch6 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=8, max_depth=8,
 min_child_weight=3, gamma=0.2, subsample=0.85, colsample_bytree=0.85,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27), 
 param_grid = param_test6, scoring='roc_auc',iid=False, cv=5)
gsearch6.fit(X_train,y_train)
gsearch6.best_params_, gsearch6.best_score_
({'reg_alpha': 1e-05}, 0.9426155352636133)
param_test6 = {
 'learning_rate':[0.01, 0.02, 0.1, 0.2]
}
gsearch6 = GridSearchCV(estimator = xgb.XGBClassifier( learning_rate =0.1, n_estimators=8, max_depth=8,
 min_child_weight=1, gamma=0.2, subsample=0.8, colsample_bytree=0.85,
 objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27), 
 param_grid = param_test6, scoring='roc_auc',iid=False, cv=5)
gsearch6.fit(X_train,y_train)
gsearch6.best_params_, gsearch6.best_score_
({'learning_rate': 0.1}, 0.9506471151048836)

网格搜索

根据前面所出来的参数,可以进一步的缩放数值,最后采用暴力搜索网格调参,但是由于XGBoost本身就是一个运行速度慢,占据CPU的一个模型,加上网格搜索速度反而变的更慢了,所以这里需要谨慎设置参数,不然电脑会跑的嗡嗡响


# learning_rate =0.1, n_estimators=8, max_depth=8,
#  min_child_weight=1, gamma=0.2, subsample=0.8, colsample_bytree=0.85,
#  objective= 'binary:logistic', nthread=4, scale_pos_weight=1,seed=27
import numpy as np
from sklearn.model_selection import GridSearchCV
parameters = {'n_estimators':np.arange(6,10,1)
              ,'max_depth':np.arange(6,10,1)
              ,"colsample_bytree":np.arange(0.8,0.9,0.05)
              ,"subsample":np.arange(0.8,0.9,0.05)
              ,'gamma':np.arange(0.1,0.5,0.1)
              ,'min_child_weight':np.arange(1,3,1)
}
clf = xgb.XGBClassifier(random_state=25)
GS = GridSearchCV(clf, parameters, cv=5) # cv交叉验证
GS.fit(X_train,y_train)
print(GS.best_params_)
print(GS.best_score_)
{'colsample_bytree': 0.8, 'gamma': 0.4, 'max_depth': 7, 'min_child_weight': 1, 'n_estimators': 8, 'subsample': 0.8}
0.9048780487804878

额,这么说呢,网格搜索的效果还不如自己之前的参数靠谱,事实上说明,我们在优化参数的时候,按照固定思维得出的数值只是一个参考值,我们自己还可以做一些调整(细微的)


最终模型代码

model=xgb.XGBClassifier(eta =0.1, n_estimators=8, max_depth=8,
 min_child_weight=2, gamma=0.8, subsample=0.85, colsample_bytree=0.8)
# 训练模型
model.fit(X_train,y_train)
# 预测值
y_pred = model.predict(X_test)
'''
评估指标
'''
# 求出预测和真实一样的数目
true = np.sum(y_pred == y_test )
print('预测对的结果数目为:', true)
print('预测错的的结果数目为:', y_test.shape[0]-true)
# 评估指标
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('预测数据的准确率为: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('预测数据的精确率为:{:.4}%'.format(
      precision_score(y_test,y_pred)*100))
print('预测数据的召回率为:{:.4}%'.format(
      recall_score(y_test,y_pred)*100))
# print("训练数据的F1值为:", f1score_train)
print('预测数据的F1值为:',
      f1_score(y_test,y_pred))
print('预测数据的Cohen’s Kappa系数为:',
      cohen_kappa_score(y_test,y_pred))
# 打印分类报告
print('预测数据的分类报告为:','
',
      classification_report(y_test,y_pred))

image.png


效果还是不错的,和随机森林有点相近,从这里也可以看出集成学习的优势所在


绘制特征重要性图

from xgboost import plot_importance
# plt.figure(figsize=(15,15))
plt.rcParams["figure.figsize"] = (14, 8)
plot_importance(model)

image.png

XGBoost可视化

xgboosts=xgb.to_graphviz(model)
xgboosts.format = 'png'
xgboosts.view('./xgboost')

image.png


这里绘制来一个树的过程,其中leaf代表预测分数

ROC曲线AUC面积

# ROC曲线、AUC
from sklearn.metrics import precision_recall_curve
from sklearn import metrics
# 预测正例的概率
y_pred_prob=model.predict_proba(X_test)[:,1]
# y_pred_prob ,返回两列,第一列代表类别0,第二列代表类别1的概率
#https://blog.csdn.net/dream6104/article/details/89218239
fpr, tpr, thresholds = metrics.roc_curve(y_test,y_pred_prob, pos_label=2)
#pos_label,代表真阳性标签,就是说是分类里面的好的标签,这个要看你的特征目标标签是0,1,还是1,2
roc_auc = metrics.auc(fpr, tpr)  #auc为Roc曲线下的面积
# print(roc_auc)
plt.figure(figsize=(8,6))
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.plot(fpr, tpr, 'r',label='AUC = %0.2f'% roc_auc)
plt.legend(loc='lower right')
# plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1.1])
plt.ylim([0, 1.1])
plt.xlabel('False Positive Rate') #横坐标是fpr
plt.ylabel('True Positive Rate')  #纵坐标是tpr
plt.title('Receiver operating characteristic example')
plt.show()


image.png

在使用XGBoost的过程中,遇到了很多的参数调优问题,其次就是CPU不足,运行网格搜索的时候,最后有人推荐去使用lightGBM这种轻量级的,但是好像也有数据量的局限性,后期可以测试一下效果。


数据的数量每天都在增加,对于传统的数据科学算法来说,很难快速的给出结果。LightGBM的前缀‘Light’表示速度很快。LightGBM可以处理大量的数据,运行时占用很少的内存。另外一个理由,LightGBM为什么这么受欢迎是因为它把重点放在结果的准确率上。LightGBM还支持GPU学习,因此,数据科学家广泛的使用LightGBM来进行数据科学应用的部署。

不建议在小数据集上使用LightGBM。LightGBM对过拟合很敏感,对于小数据集非常容易过拟合。对于多小属于小数据集,并没有什么阈值,但是从我的经验,我建议对于10000+以上的数据的时候,再使用LightGBM。


相关文章
|
4月前
|
机器学习/深度学习 算法 数据挖掘
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
没发论文的注意啦!重磅更新!GWO-BP-AdaBoost预测!灰狼优化、人工神经网络与AdaBoost集成学习算法预测研究(Matlab代码实现)
170 0
|
2月前
|
机器学习/深度学习 数据采集 人工智能
【机器学习算法篇】K-近邻算法
K近邻(KNN)是一种基于“物以类聚”思想的监督学习算法,通过计算样本间距离,选取最近K个邻居投票决定类别。支持多种距离度量,如欧式、曼哈顿、余弦相似度等,适用于分类与回归任务。结合Scikit-learn可高效实现,需合理选择K值并进行数据预处理,常用于鸢尾花分类等经典案例。(238字)
|
3月前
|
机器学习/深度学习 运维 算法
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
【微电网多目标优化调度】多目标学习者行为优化算法MOLPB求解微电网多目标优化调度研究(Matlab代码实现)
232 1
|
7月前
|
机器学习/深度学习 数据采集 人工智能
20分钟掌握机器学习算法指南
在短短20分钟内,从零开始理解主流机器学习算法的工作原理,掌握算法选择策略,并建立对神经网络的直观认识。本文用通俗易懂的语言和生动的比喻,帮助你告别算法选择的困惑,轻松踏入AI的大门。
|
9月前
|
算法 数据可视化 开发者
为什么要学习数据结构与算法
今天,我向大家介绍一门非常重要的课程——《数据结构与算法》。这门课不仅是计算机学科的核心,更是每一位开发者从“小白”迈向“高手”的必经之路。
为什么要学习数据结构与算法
|
8月前
|
机器学习/深度学习 存储 Kubernetes
【重磅发布】AllData数据中台核心功能:机器学习算法平台
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
AI训练师入行指南(三):机器学习算法和模型架构选择
从淘金到雕琢,将原始数据炼成智能珠宝!本文带您走进数字珠宝工坊,用算法工具打磨数据金砂。从基础的经典算法到精密的深度学习模型,结合电商、医疗、金融等场景实战,手把手教您选择合适工具,打造价值连城的智能应用。掌握AutoML改装套件与模型蒸馏术,让复杂问题迎刃而解。握紧算法刻刀,为数字世界雕刻文明!
325 6
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
1208 6
|
10月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于机器学习的人脸识别算法matlab仿真,对比GRNN,PNN,DNN以及BP四种网络
本项目展示了人脸识别算法的运行效果(无水印),基于MATLAB2022A开发。核心程序包含详细中文注释及操作视频。理论部分介绍了广义回归神经网络(GRNN)、概率神经网络(PNN)、深度神经网络(DNN)和反向传播(BP)神经网络在人脸识别中的应用,涵盖各算法的结构特点与性能比较。
|
11月前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
2013 13
机器学习算法的优化与改进:提升模型性能的策略与方法