选择弱评估器:参数booster

在XGB中,除了使用梯度提升树(默认gbtree)以外,还可以使用gbtlineardart
在原库中,在xgb.train()中输入xgb_model进行选择(但是注意这个参数只能由params参数导入!);sklearn中在xgb.XGBregressor()输入booster进行选择。
如果数据是线性的,可以使用gbtlinear

XGB目标函数:重要参数objective

XGB的损失函数不仅仅考虑了传统的误差函数,还考虑了模型的复杂度
XGBRegressor哪些参数需要调参_损失函数
第一项是针对每一个样本进行计算误差函数,第二项针对每一棵树计算模型复杂度,可以有多种计算定义。
第一项中的预测值XGBRegressor哪些参数需要调参_复杂度_02实际上是一些列树的预测结果之和:
XGBRegressor哪些参数需要调参_损失函数_03
第一项描述模型的偏差情况,第二项描述模型的复杂度,其实同时可以衡量方差的情况,方式过拟合,从而实现整体泛化误差最小,非常巧妙!
在XGB中,目标函数可以选择的是第一项。

xgb.train()

xgb.XGBregressor()

xgb.XGBClassifier()

obj:默认binary:logistic

objective:默认reg:linear

objective:默认binary:logistic

注意xgb库本身默认的参数,要做回归的话需要修改改参数。
binary:logistic指的是二分类时逻辑回归损失函数,即交叉熵。
常见的输入有以下几种:

输入

选用的损失函数

reg:linear

使用线性回归的损失函数,均方误差,回归时使用

binary:logistic

使用逻辑回归的损失函数,对数损失log_loss,二分类时使用

binary:hinge

使用支持向量机的损失函数,Hinge Loss,二分类时使用

multi:softmax

使用softmax损失函数,多分类时使用

直接调用xgb的库

import xgboost as xgb

在这个库中需要用**xgb.DMatrix()**读取数据,必须同时输入特征和标签。

#使用类DMatrix读取数据
dtrain = xgb.DMatrix(Xtrain,Ytrain) #特征矩阵和标签都进行一个传入
dtest = xgb.DMatrix(Xtest,Ytest)

参数需要用一个字典来存储

#写明参数
param = {'silent':True #默认为False,通常要手动把它关闭掉
         ,'objective':'reg:linear'
         ,"eta":0.1}
num_round = 180 #n_estimators

注意num_round参数可以直接传入XGB,其它参数还是需要字典传入。

#类train,可以直接导入的参数是训练数据,树的数量,其他参数都需要通过params来导入
bst = xgb.train(param, dtrain, num_round)

然后就可以预测了

#接口predict
preds = bst.predict(dtest)

参数化决策树XGBRegressor哪些参数需要调参_复杂度_04:参数alpha,lambda

XGB的目标函数可以转换为只与当前次的迭代相关的形式:
XGBRegressor哪些参数需要调参_损失函数_05
其中XGBRegressor哪些参数需要调参_复杂度_06XGBRegressor哪些参数需要调参_二分类_07只与传统损失函数相关。
对XGB来说,预测值是需要单独计算的分数,即叶子权重,用XGBRegressor哪些参数需要调参_损失函数_08XGBRegressor哪些参数需要调参_损失函数_09表示。XGBRegressor哪些参数需要调参_损失函数_08表示将样本XGBRegressor哪些参数需要调参_二分类_11放入到树XGBRegressor哪些参数需要调参_复杂度_12中获得的叶子权重。
当有多棵树时,集成模型的回归结果是所有树的预测分数之和:
XGBRegressor哪些参数需要调参_二分类_13
在树结构中,使用XGBRegressor哪些参数需要调参_损失函数_14表示样本XGBRegressor哪些参数需要调参_二分类_11所在的叶子结点,用XGBRegressor哪些参数需要调参_损失函数_16表示样本落到第XGBRegressor哪些参数需要调参_复杂度_17棵树上的第XGBRegressor哪些参数需要调参_损失函数_14个叶子结点中获得的分数,于是:
XGBRegressor哪些参数需要调参_二分类_19
这是对于每一个样本而言的叶子权重,然而在一个叶子节点上所有的样本所对应的叶子权重是相同的。
设总共有T个叶子结点,可以表示XGBRegressor哪些参数需要调参_损失函数_20:
XGBRegressor哪些参数需要调参_二分类_21
若使用XGBRegressor哪些参数需要调参_损失函数_22正则项:
XGBRegressor哪些参数需要调参_二分类_23
若使用XGBRegressor哪些参数需要调参_二分类_24正则项:
XGBRegressor哪些参数需要调参_复杂度_25
也可以两个一起用:
XGBRegressor哪些参数需要调参_损失函数_26
由于在梯度提升树中都是二叉树,所以知道叶子结点的数目XGBRegressor哪些参数需要调参_复杂度_27的话就可以知道树的深度,也知道树的复杂程度。
在剪枝前,XGB就有正则项参数可以调节以防止过拟合。

参数含义

xgb.train()

xgb.XGBRegressor()

L1正则项参数

alpha,默认0,取值范围

reg_alpha,默认0,取值范围

L2正则项参数XGBRegressor哪些参数需要调参_损失函数_31

lambda,默认1,取值范围XGBRegressor哪些参数需要调参_损失函数_31

reg_lambda,默认1,取值范围XGBRegressor哪些参数需要调参_损失函数_31

通常在回归中才用得到。
可以使用网格搜索来找正则化参数

寻找最佳树结构:求解XGBRegressor哪些参数需要调参_损失函数_31XGBRegressor哪些参数需要调参_复杂度_27

在XGB中,一个核心的思想是把目标函数变为叶子节点数的函数,所以目标函数又可以称为“结构分数”。
前文已经得到XGB的目标函数可以表示为:
XGBRegressor哪些参数需要调参_损失函数_36
前半部分仍然为关于样本的求和,可以通过数学转换为
XGBRegressor哪些参数需要调参_二分类_37
XGBRegressor哪些参数需要调参_复杂度_38,可以表示最终的目标函数
XGBRegressor哪些参数需要调参_复杂度_39
可以通过对每一个XGBRegressor哪些参数需要调参_复杂度_40对应下的XGBRegressor哪些参数需要调参_损失函数_41求导并带入解,最终可以得到
XGBRegressor哪些参数需要调参_损失函数_42
即转化为只与叶子节点有关的函数了。

寻找最佳分枝:结构分数之差

在XGB中,是通过使每一次分枝前后的结构分数之差最大的贪心算法来实现分支的。
分枝后的结构分数之差为
XGBRegressor哪些参数需要调参_复杂度_43

让树停止生长:重要参数gamma

从上面的XGBRegressor哪些参数需要调参_复杂度_44的计算式可以看到,XGBRegressor哪些参数需要调参_二分类_45可以看作每进行一次分枝都要计算的一个惩罚项(因为我们希望XGBRegressor哪些参数需要调参_复杂度_44越大越好),也叫“复杂性控制(complexity control)”,是用来防止过拟合的重要参数。
在XGB中,只要XGBRegressor哪些参数需要调参_复杂度_44是大于0的,就可以继续分枝,由上面的式子可以知道,XGBRegressor哪些参数需要调参_二分类_45可以看作是在树的叶子结点上进行进一步分枝所需要的最小目标函数减少量,其值越小,模型越复杂。

参数含义

xgb.train()

xgb.XGBRegressor()

复杂度的惩罚项

gamma,默认0,取值范围

gamma,默认0,取值范围

XGB的调参可以使用xgb.cv()工具进行

import xgboost as xgb
#为了便捷,使用全数据
dfull = xgb.DMatrix(X,y) #设定参数
param1 = {'silent':True,'obj':'reg:linear',"gamma":0}
num_round = 180
n_fold=5 #使用类xgb.cv
time0 = time()
cvresult1 = xgb.cv(param1, dfull, num_round,n_fold)
print(datetime.datetime.fromtimestamp(time()-time0).strftime("%M:%S:%f"))
#看看类xgb.cv生成了什么结果?
cvresult1
plt.figure(figsize=(20,5))
plt.grid()
plt.plot(range(1,181),cvresult1.iloc[:,0],c="red",label="train,gamma=0")
plt.plot(range(1,181),cvresult1.iloc[:,2],c="orange",label="test,gamma=0")
plt.legend()
plt.show()

通过xgb.cv()绘制的曲线可以看到调整gamma之后训练集和测试集分数之间的差异,需要调整到一个使测试集分数最高且训练集和测试集差异较小的状态。