使用xgboost库

使用xgboost库

目录

  • xgboost中的参数
  • 使用sklearn中xgboostAPI
    • 绘制学习曲线
    • 进化的学习曲线:方差与泛化误差
  • 使用xgboost.train()
  • 使用xgboost.cv()
    • 案例:在波士顿数据集上,使用xgb.cv这个类进行调参
  • 分类案例:XGB中样本不均衡问题

xgboost中的参数

sklearn中参数xgboost库中对应的参数名集成算法弱评估器其他过程含义
n_estimatorsnum_round--默认为100
建议优先调整n_estimators
一般不会建议太大的数目,以300以内为佳
learning_rateeta--集成中的学习率
与n_estimators联合控制调参
取值范围[0,1]
设置太大模型可能无法收敛,设置太小模型速度非常缓慢
silentsilent--建议为True
True:不打印每次训练的结果
subsamplesubsample--默认为1
随机抽样的时候抽取的样本比例,范围(0,1]
通常是在样本量本身很大的时候调整和使用
max_depthmax_depth--默认为6
objectiveobj--确定使用的损失函数类型
可选的输入
reg:linear(使用线性回归的损失函数,均方误差)
binary:logistic(使用逻辑回归的损失函数,对数损失)
binary:hinge(使用支持向量机的损失函数,HingeLoss)
multi:softmax(使用softmax损失函数,多分类时使用)
boosterxgb_model--使用哪种弱评估器
默认为"gbtree"
可以输入gbtree(梯度提升树),gblinear(线性模型),dart(抛弃提升树,在建树的过程中会抛弃一部分树,更好的防过拟合)
gammagamma--“复杂度控制”,用来防止过拟合的重要参数。
同时还是让树停止生长的重要参数。
默认为0
取值范围[0,inf)
gamma越大,算法越保守,树的叶子数量越少,复杂度越低
min_child_weightmin_child_weight--默认为1
一个叶子结点上所需要的最小hi,即叶子结点上的二阶导数之和(类似于样本权重)
max_delta_stepmax_delta_setp--在保证正确的概率的基础上,减轻样本不平衡问题带来的影响
树的权重估计中允许的单次最大增量
可以考虑成是影响wj的参数
可以将其设定为有限的数(比如1)来帮助收敛
很少使用
colsample_bytreecolsample_bytree--默认为1
每次生成树时随机抽样特征的比例
colsample_bylevelcolsample_bylevel--默认为1
每次生成树的一层时,随机抽样特征的比例
-colsample_bynode--默认为1
每次生成一个叶子节点时,随机抽样特征的比例
reg_alphaalpha--默认为0
取值范围为[0,inf)
正则化参数
reg_lambdalambda--默认为1
取值范围为[0,inf)
正则化参数
nthreadnthread--用于运行xgboost的并行线程数(已弃用,请使用n_jobs)
n_jobsn_jobs--用于运行xgboost的并行线程数
scale_pos_weightscale_pos_weight--默认为1
调节样本不平衡的参数
类似随机森林和支持向量机中的class_weight参数
通常我们在参数中输入的是负样本量与正样本量之比
base_scorebase_score--所有实例的初始预测分数,全局偏差
分类问题中,它是分类的先验概率
通常不使用这个参数
对于严重的样本不均衡问题,设置一个正确的base_score取值是很有必要的
seedseed--随机数种子(已弃用,请使用random_state)
random_staterandom_state--随机种子
missingmissing--需要作为缺失值存在的数据中的值
如果为None,默认为np.nan
输入一个对象或者数据的任意取值,表示将所有含有这个对象的数据作为空值处理
importance_typeimportance_type--feature_importances_属性的特征重要性类型

正则化参数往往不是我们调参的最优选择,如果真的希望控制模型的复杂度,我们会调整 γ \gamma γ而不是调整这两个正则化参数.
如果我们希望调整 α \alpha α, λ \lambda λ,往往会使用网格搜索来帮助我们。

参数min_child_weight不太常用,它时一片叶子上的二阶导数 h i h_i hi之和。当样本对应的二阶导数很小时,比如为0.01,min_child_weight若设定为1,则说明一片叶子上至少需要100个样本。
本质上说,这个参数其实是在控制叶子上所需的最小样本量。因此对样本量很大的数据会比较有效。

调参的过程
通常在我们获得了一个数据集后,我们先使用网格搜索找出比较合适的n_estimators和eta组合
然后使用gamma或者max_depth观察模型处于什么样的状态(过拟合还是欠拟合,处于方差-偏差图像的左边还是右边?)
最后再决定是否要进行剪枝

使用sklearn中xgboostAPI

import xgboost
from sklearn.datasets import load_boston
from sklearn.model_selection import cross_val_score,KFold,train_test_split
from time import time
import datetime
boston = load_boston()
X = boston.data
y = boston.target
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=420)
reg = xgboost.XGBRegressor(n_estimators=100).fit(X_train,y_train)
reg.score(X_test,y_test)
0.9197580267581366
[*zip(boston.feature_names,reg.feature_importances_)]
[('CRIM', 0.02474326),
 ('ZN', 0.0023391892),
 ('INDUS', 0.008951775),
 ('CHAS', 0.01757721),
 ('NOX', 0.048474625),
 ('RM', 0.25909728),
 ('AGE', 0.012036602),
 ('DIS', 0.042923097),
 ('RAD', 0.013585145),
 ('TAX', 0.025586879),
 ('PTRATIO', 0.04455473),
 ('B', 0.01763431),
 ('LSTAT', 0.48249587)]

可以查看模型的重要性分数,使用嵌入法进行特征选择

绘制学习曲线

from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
import numpy as np
train_sizes,train_scores,test_scores = learning_curve(xgboost.XGBRegressor(n_estimators=100),X_train,y_train,shuffle=True,cv=5,scoring="r2",random_state=420)
plt.grid()
plt.xlabel("training examples")
plt.ylabel("Score")
plt.plot(train_sizes,np.mean(train_scores,axis=1),"o-",label="Training score")
plt.plot(train_sizes,np.mean(test_scores,axis=1),"o-",label="Test score")
plt.legend(loc="best")

在这里插入图片描述

<matplotlib.legend.Legend at 0x1a16c9fa20>

进化的学习曲线:方差与泛化误差

衡量模型在未知数据上的准确率的指标叫做,泛化误差(Genelization error)
一个模型在位置数据集(D)上的泛化误差E,由方差(var),偏差(bais)和噪声( / e p s i l o n /epsilon /epsilon)共同决定。
其中偏差就是训练集上的拟合程度决定,方差是模型的稳定性决定,噪声是不可控的。
泛化误差越小,模型越理想。
E ( f ; D ) = b i a s 2 + v a r + ϵ 2 E(f;D)=bias^2+var+\epsilon^2 E(f;D)=bias2+var+ϵ2

改进后的学习曲线,即考虑偏差也考虑方差

#改进后的学习曲线,将方差也考虑其中
cv = KFold(n_splits=5, shuffle = True, random_state=42) #交叉验证模式
n_estimators = np.arange(100,300,10)
bias = []#记录偏差
var = []#记录方差
Err = []#记录泛化误差中可控的部分

for i in n_estimators:
    reg = xgboost.XGBRegressor(n_estimators=i,random_state=420)
    CVresult = cross_val_score(reg,X_train,y_train,cv=cv)
    bias.append(CVresult.mean()) #记录偏差
    var.append(CVresult.var()) #记录方差
    Err.append((1-CVresult.mean())**2+CVresult.var())

bias = np.array(bias)
var = np.array(var)
Err = np.array(Err)
print("when bias is min",n_estimators[np.argmax(bias)],max(bias),var[np.argmax(bias)])
print("when var is min",n_estimators[np.argmin(var)],bias[np.argmin(var)],min(var))    
print("when Err is min",n_estimators[np.argmin(Err)],bias[np.argmin(Err)],var[np.argmin(Err)])

plt.figure(figsize=(20,5))
plt.plot(n_estimators,bias,c="black",label="XGB")
plt.plot(n_estimators,bias+var*0.05,c="red",linestyle="-.")
plt.plot(n_estimators,bias-var*0.05,c="red",linestyle="-.")
plt.legend()
plt.show()
when bias is min 180 0.8038787848970184 0.00959321570484315
when var is min 180 0.8038787848970184 0.00959321570484315
when Err is min 180 0.8038787848970184 0.00959321570484315

在这里插入图片描述

xgboost.train()的使用

使用xgboost库的建模流程

  1. 读取数据 xgboost.DMatrix()
  2. 设置参数 param={}
  3. 训练模型 bst = xgboost.train(param)
  4. 预测结果 bst.predict()
import xgboost
#使用DMatrix类读取数据
dtrain = xgboost.DMatrix(X_train,y_train)
dtest = xgboost.DMatrix(X_test,y_test)

#写明参数
param = {
    'silent':False,
    "objective":"reg:linear",
    "eta":0.1
}
num_round = 180

#训练模型
bst = xgboost.train(param,dtrain,num_round)

#预测结果
predict = bst.predict(dtest)
from sklearn.metrics import r2_score
r2_score(y_test,predict)
0.9260984298390122

使用xgboost.cv()类

为了调整gamma,使用xgboost库中的类xgboost.cv
xgboost.cv中用于回归和分类的评估指标有:

  • rmse 均方根误差
  • mae 绝对平均误差
  • logloss 对数损失(二分类用)
  • mlogloss 对数损失(多分类用)
  • error 分类误差(1-准确率)
  • auc AUC面积

在param中{“eval_metric”:“mae”}进行修改

#使用Dmatrix类读取数据
dfull = xgboost.DMatrix(X,y)

#设定参数
param_0 = {
'silent':True,'obj':'reg:linear',"gamma":0
#     "eval_metric":"rmse"
}
param_20 = {
    "silent":True,"obj":"reg:linear","gamma":20
}

num_round=180
n_fold=5

#使用类xgb.cv
time0 = time()
CVresult_0 = xgboost.cv(param_0,dfull,num_round,n_fold)
CVresult_20 = xgboost.cv(param_20,dfull,num_round,n_fold)
print(datetime.datetime.fromtimestamp(time()-time0).strftime("%M:%s:%f"))

#看看类xgb.cv生成的结果
CVresult_0.head()
00:1:237792
train-rmse-meantrain-rmse-stdtest-rmse-meantest-rmse-std
017.1055770.12911717.1632150.584297
112.3379720.09755612.5197360.473458
28.9940710.0657569.4045340.472310
36.6294800.0503237.2503350.500342
44.9544070.0332095.9208120.591874
plt.figure(figsize=(20,5))
plt.grid()
plt.plot(range(1,181),CVresult_0.iloc[:,0],c = "red",label="train,gamma=0")
plt.plot(range(1,181),CVresult_0.iloc[:,2],c = "orange",label="test,gamma=0")

plt.plot(range(1,181),CVresult_20.iloc[:,0],c = "g",label="train,gamma=20")
plt.plot(range(1,181),CVresult_20.iloc[:,2],c = "b",label="test,gamma=20")


plt.xlabel("n_estimators")
plt.ylabel("rmse")
plt.legend()
plt.show()

在这里插入图片描述

案例:在波士顿数据集上,使用xgb.cv这个类进行调参

dfull = xgboost.DMatrix(X,y)

param = {
    "silent":True,
    "obj":"reg:linear",#确定xgb所用的损失函数
    "subsample":1,
    "max_depth":6,
    "eta":0.3,
    "gamma":0,
    "lambda":1,
    "alpha":0,
    "colsample_bytree":1,
    "colsample_bylevel":1,
    "colsample_bynode":1,
    "nfold":5,
#     "eval_metric":"rmse"
}
num_round=200

time0 = time()
CVresult = xgboost.cv(param,dfull,num_round)
print(datetime.datetime.fromtimestamp(time()-time0).strftime("%M:%s:%f"))
00:0:331057
plt.figure(figsize=(20,5))
plt.grid()
plt.plot(range(1,201),CVresult.iloc[:,0],c = "red",label="train,original")
plt.plot(range(1,201),CVresult.iloc[:,2],c = "orange",label="test,original")

plt.xlabel("n_estimators")
plt.ylabel("rmse")
plt.legend(fontsize="xx-large")#让图例的字体最大

plt.show()

在这里插入图片描述

从曲线上可以看出,模型现在处于过拟合的状态,我们决定剪枝。
我们的目标是:训练集和测试集的结果尽量接近。
在这里我们使用三组曲线,一组用于展示原式数据集上的结果,一组用于展示上一个参数调整完毕后的结果,最后一组用于展示现在我们在调节的参数的结果

param_original = {
    "silent":True,
    "obj":"reg:linear",#确定xgb所用的损失函数
    "subsample":1,
    "max_depth":6,
    "eta":0.3,
    "gamma":0,
    "lambda":1,
    "alpha":0,
    "colsample_bytree":1,
    "colsample_bylevel":1,
    "colsample_bynode":1,
    "nfold":5,
#     "eval_metric":"rmse"
}
num_round=200

time0 = time()
CVresult_original = xgboost.cv(param_original,dfull,num_round)
print(datetime.datetime.fromtimestamp(time()-time0).strftime("%M:%s:%f"))

plt.figure(figsize=(20,5))
plt.grid()
plt.plot(range(1,201),CVresult.iloc[:,0],c = "red",label="train,original")
plt.plot(range(1,201),CVresult.iloc[:,2],c = "orange",label="test,original")


param_last = {
    "silent":True,
    "obj":"reg:linear",#确定xgb所用的损失函数
    "subsample":1,
    "max_depth":4,
    "eta":0.05,
    "gamma":20,
    "lambda":3.5,
    "alpha":0.2,
    "colsample_bytree":0.4,
    "colsample_bylevel":0.6,
    "colsample_bynode":1,
    "nfold":5,
#     "eval_metric":"rmse"
}


param_now = {
    "silent":True,
    "obj":"reg:linear",#确定xgb所用的损失函数
    "subsample":1,
    "max_depth":2,
    "eta":0.05,
    "gamma":0,
    "lambda":1,
    "alpha":0,
    "colsample_bytree":1,
    "colsample_bylevel":0.4,
    "colsample_bynode":1,
    "nfold":5,
#     "eval_metric":"rmse"
}

CVresult_last = xgboost.cv(param_last,dfull,num_round)
CVresult_now = xgboost.cv(param_now,dfull,num_round)

plt.plot(range(1,201),CVresult_last.iloc[:,0],label="train,last")
plt.plot(range(1,201),CVresult_last.iloc[:,2],label="test,last")

plt.plot(range(1,201),CVresult_now.iloc[:,0],"o-",label="train,now")
plt.plot(range(1,201),CVresult_now.iloc[:,2],"o-",label="test,now")


plt.xlabel("n_estimators")
plt.ylabel("rmse")
plt.legend(fontsize="xx-large")#让图例的字体最大
plt.show()
00:0:332620

在这里插入图片描述
调整中的问题:

  1. 一个个参数调整太麻烦,可不可以使用网格搜索?
    建议先使用xgboost.cv来确认参数的范围,否则很可能花很长时间做了无用功。
    并且,在使用网格搜索的时候,最好不要一次性将所有的参数都放入进行搜索,最多一次两三个。
    一些互相影响的参数需要放在一起使用,比如学习率eta和n_estimators

  2. 调参的顺序会影响调参结果吗?
    会影响
    在现实中,我们会优先调整那些对模型影响巨大的参数。

建议的剪枝调参顺序为

  • n_estimators与eta共同调节
  • gamma或者max_depth
  • 采样和抽样参数(纵向抽样影响更大)
  • 正则化的两个参数

分类案例:XGB中样本不均衡问题

通过调节scale_pos_weight参数来进行
通常scale_pos_weight=负样本数之和/正样本数之和

#创建样本不均衡的数据集
from sklearn.datasets import make_blobs
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix,recall_score,roc_auc_score

class_1 = 500 #类别1有500个样本
class_2 = 50 #类别2有50个样本
centers = [[0,0],[2,2]] #设定两个类别的中心
clusters_std = [1.5,0.5] #设定两个类别的方差,通常来说,样本量比较大的类别会更加松散

X,y = make_blobs(
    n_samples=[class_1,class_2],
    centers = centers,
    cluster_std = clusters_std,
    random_state = 0,
    shuffle = False
)

X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.3,random_state=420)

在数据集上建模:sklearn模式

clf = xgboost.XGBClassifier()
clf.fit(X_train,y_train)
predict = clf.predict(X_test)
clf.score(X_test,y_test)
0.9272727272727272
confusion_matrix(y_test,predict,labels=[1,0])
array([[  9,   4],
       [  8, 144]])
recall_score(y_test,predict)
0.6923076923076923
roc_auc_score(y_test,predict)
0.819838056680162
## 调整scale_pos_weight参数
clf_ = xgboost.XGBClassifier(scale_pos_weight=10).fit(X_train,y_train)
predict_ = clf_.predict(X_test)
clf_.score(X_test,y_test)
0.9515151515151515
confusion_matrix(y_test,predict_,labels=[1,0])
array([[ 13,   0],
       [  8, 144]])
recall_score(y_test,predict_)
1.0
roc_auc_score(y_test,predict_)
0.9736842105263158

调整scale_pos_weight后,模型的准确率有了很大提高

在数据集上建模:xgboost模式

dtrain = xgboost.DMatrix(X_train,y_train)
dtest = xgboost.DMatrix(X_test)

param={
    "slient":True,
    "objective":"binary:logistic",
    "eta":0.1,
    "scale_pos_weight":1
}
num_round=100

bst = xgboost.train(param,dtrain,num_round)
preds = bst.predict(dtest)
preds[:5]
array([0.00110357, 0.00761518, 0.00110357, 0.00110357, 0.93531454],
      dtype=float32)

返回的是预测概率,需要改成类别

preds[preds > 0.5] = 1
preds[preds != 1] = 0
from sklearn.metrics import accuracy_score
accuracy_score(y_test,preds)
0.9272727272727272

修改scale_pos_weight

param={
    "slient":True,
    "objective":"binary:logistic",
    "eta":0.1,
    "scale_pos_weight":10
}
num_round=100

bst = xgboost.train(param,dtrain,num_round)
preds = bst.predict(dtest)

preds[preds > 0.5] = 1
preds[preds != 1] = 0

accuracy_score(y_test,preds)
0.9515151515151515

也可以通过调整不同的阈值来进行调整

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值