步骤(booststrap sampling):
目标函数: o b j ( t ) = ∑ i = 1 n L ( y i , y ^ i ( t − 1 ) + f t x i ) + Ω f ( t ) + C obj^{(t)}=\sum_{i=1}^nL(y_i,\widehat y_i^{(t-1)}+f_t^{x_i})+\Omega f(t)+C obj(t)=∑i=1nL(yi,y i(t−1)+ftxi)+Ωf(t)+C
Taylor展开: f ( x + Δ x ) ≈ f ( x ) + f ′ ( x ) Δ x + 1 2 f ′ ′ ( x ) ( Δ x ) 2 f(x+\Delta x)\approx f(x)+f'(x)\Delta x+\frac{1}{2}f''(x)(\Delta x)^2 f(x+Δx)≈f(x)+f′(x)Δx+21f′′(x)(Δx)2
加法训练优化步骤:
{ y ^ i ( 0 ) = 0 y ^ i ( 1 ) = f 1 ( x i ) = y ^ i ( 0 ) + f 1 ( x i ) . . . . . . y ^ i ( t ) = ∑ k = 1 t f k ( x i ) = y ^ i ( t − 1 ) + f t ( x i ) \begin{cases} \widehat y_i^{(0)}=0\\ \widehat y_i^{(1)}=f_1(x_i)=\widehat y_i^{(0)}+f_1(x_i)\\ ......\\ \widehat y_i^{(t)}=\sum_{k=1}^tf_k(x_i)=\widehat y_i^{(t-1)}+f_t(x_i) \end{cases} ⎩⎪⎪⎪⎨⎪⎪⎪⎧y i(0)=0y i(1)=f1(xi)=y i(0)+f1(xi)......y i(t)=∑k=1tfk(xi)=y i(t−1)+ft(xi)
目标函数进一步可表示为:
o b j ( t ) = ∑ i = 1 n l ( y i , y ^ i ( t ) ) + ∑ i = 1 t Ω f ( t ) obj^{(t)}=\sum_{i=1}^nl(y_i,\widehat y_i^{(t)})+\sum_{i=1}^t\Omega f(t) obj(t)=∑i=1nl(yi,y i(t))+∑i=1tΩf(t)
∑ i = 1 t Ω f ( t ) = Ω f ( t ) + ∑ i = 1 t − 1 Ω f ( t − 1 ) = Ω f ( t ) + c o n s t a t n t \sum_{i=1}^t\Omega f(t)=\Omega f(t)+\sum_{i=1}^{t-1}\Omega f(t-1)=\Omega f(t)+constatnt ∑i=1tΩf(t)=Ωf(t)+∑i=1t−1Ωf(t−1)=Ωf(t)+constatnt 其中 ∑ i = 1 t − 1 Ω f ( t − 1 ) / c o n s t a n t \sum_{i=1}^{t-1}\Omega f(t-1)/constant ∑i=1t−1Ωf(t−1)/constant表示前t-1棵树的复杂度
o b j ( t ) = ∑ i = 1 n l ( y i , y ^ i ( t − 1 ) + f ( t ) ( x i ) ) + Ω f ( t ) + c o n s t a n t obj^{(t)}=\sum_{i=1}^nl(y_i,\widehat y_i^{(t-1)}+f_{(t)}(x_i))+\Omega f(t)+constant obj(t)=∑i=1nl(yi,y i(t−1)+f(t)(xi))+Ωf(t)+constant
y ^ i ( t ) = y ^ i ( t − 1 ) + f ( t ) ( x i ) \widehat y_i^{(t)}=\widehat y_i^{(t-1)}+f_{(t)}(x_i) y i(t)=y i(t−1)+f(t)(xi) 其中 f ( t ) ( x i ) f_{(t)}(x_i) f(t)(xi)是第t课树,是唯一一个需要学习的变量,其余都为已知量。 Ω f ( t ) \Omega f(t) Ωf(t)是第t棵树的复杂度。 c o n s t a n t constant constant前 t − 1 t-1 t−1棵树的复杂度
o b j ( t ) = ∑ i = 1 n [ l ( y i , y ^ i ( t − 1 ) ) + g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω f ( t ) + c o n s t a n t obj^{(t)}=\sum_{i=1}^n[l(y_i,\widehat y_i^{(t-1)})+g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+\Omega f(t)+constant obj(t)=∑i=1n[l(yi,y i(t−1))+gift(xi)+21hift2(xi)]+Ωf(t)+constant
其中 g i g_i gi和 h i h_i hi定义如下:
{ g i = ∂ y ^ ( t − 1 ) l ( y i , y ^ ( t − 1 ) ) h i = ∂ 2 y ^ ( t − 1 ) l ( y i , y ^ ( t − 1 ) ) \begin{cases} g_i=\partial\widehat y^{(t-1)}l(y_i,\widehat y^{(t-1)})\\ h_i=\partial^2\widehat y^{(t-1)}l(y_i,\widehat y^{(t-1)}) \end{cases} {gi=∂y (t−1)l(yi,y (t−1))hi=∂2y (t−1)l(yi,y (t−1))
1、定义树的复杂度 Ω f ( t ) = γ T + 1 2 λ ∑ j = 1 T w j 2 \Omega f(t)=\gamma T+\frac{1}{2}\lambda\sum_{j=1}^{T}w_j^2 Ωf(t)=γT+21λ∑j=1Twj2 其中 T T T为叶子节点数量; λ \lambda λ为一个叶子带来的复杂度; w j 2 w_j^2 wj2为叶子节点 L 2 L_2 L2的范数; j j j为叶子节点数量
2、定义一棵树: f t ( x ) = W q ( x ) ( w ∈ R T , q : R d → { 1 、 2..... T } ) f_t(x)=W_{q(x)}(w \in R^T,q:R^d\rightarrow\{1、2.....T\}) ft(x)=Wq(x)(w∈RT,q:Rd→{1、2.....T}) 其中 w w w为一维向量,代表树 q q q各个叶子节点权重; q q q代表一棵树的结构
去常数项 :
o b j ( t ) = ∑ i = 1 n [ g i f t ( x i ) + 1 2 h i f t 2 ( x i ) ] + Ω f ( t ) = ∑ i = 1 n [ g i w q ( x i ) + 1 2 h i w q ( x i ) 2 ] + γ T + 1 2 λ ∑ j = 1 T w j 2 = ∑ j = 1 T [ ( ∑ i ∈ I j g i ) w j + 1 2 ( ∑ i ∈ I j h i + λ ) w j 2 ] + γ T \begin{aligned} obj^{(t)}&=\sum_{i=1}^n[g_if_t(x_i)+\frac{1}{2}h_if_t^2(x_i)]+\Omega f(t)\\ &=\sum_{i=1}^n[g_iw_{q(x_i)}+\frac{1}{2}h_iw_{q(x_i)}^2]+\gamma T+\frac{1}{2}\lambda\sum_{j=1}^{T}w_j^2\\ &=\sum_{j=1}^T[(\sum_{i \in I_j}g_i)w_j+\frac{1}{2}(\sum_{i \in I_j}h_i+\lambda)w_j^2]+\gamma T \end{aligned} obj(t)=i=1∑n[gift(xi)+21hift2(xi)]+Ωf(t)=i=1∑n[giwq(xi)+21hiwq(xi)2]+γT+21λj=1∑Twj2=j=1∑T[(i∈Ij∑gi)wj+21(i∈Ij∑hi+λ)wj2]+γT
∑ j = 1 T \sum_{j=1}^T ∑j=1T将所有训练样本,按叶子节点进行了分组。其中 I j = { i ∣ q ( x i ) = j } 将 属 于 第 I_j=\{i|q(x_i)=j\}将属于第 Ij={i∣q(xi)=j}将属于第j 个 叶 子 节 点 所 有 样 本 个叶子节点所有样本 个叶子节点所有样本x_i$,划入到一个叶子节点样本集中
o b j ( t ) = ∑ j = 1 T [ G j w j + 1 2 ( H j + λ ) w j 2 ] + γ T obj^{(t)}=\sum_{j=1}^T[G_jw_j+\frac{1}{2}(H_j+\lambda)w_j^2]+\gamma T obj(t)=∑j=1T[Gjwj+21(Hj+λ)wj2]+γT
G j = ∑ i ∈ I j g i G_j=\sum_{i \in I_j}g_i Gj=∑i∈Ijgi:叶子节点 j j j所包含样本一阶偏导数累加之和(常量); H j = ∑ i ∈ I j h i H_j=\sum_{i \in I_j}h_i Hj=∑i∈Ijhi:叶子节点 j j j所包含样本二阶偏导数累加之和(常量)
求解:
{ w j ∗ = − G j H j + λ ( 每 个 叶 子 节 点 权 重 s c o r e ) o b j = − 1 2 ∑ j = 1 T G j 2 H j + λ + γ T ( 第 t 棵 树 带 来 的 最 小 损 失 ) \begin{cases} w_j^*=-\frac{G_j}{H_j+\lambda} (每个叶子节点权重score)\\ obj=-\frac{1}{2}\sum_{j=1}^T\frac{G_j^2}{H_j+\lambda}+\gamma T(第t棵树带来的最小损失) \end{cases} {wj∗=−Hj+λGj(每个叶子节点权重score)obj=−21∑j=1THj+λGj2+γT(第t棵树带来的最小损失)
分裂指标(分割点在Gain最大且大于0):
G a i n = o b j L + R − ( o b j L + o b j R ) = [ − 1 2 ( G L + G R ) 2 H L + H R + λ + γ ] − [ − 1 2 ( G L ) 2 H L + λ + ( G R ) 2 H R + λ + 2 λ ] \begin{aligned} Gain&=obj_{L+R}-(obj_{L}+obj_{R})\\ &=[-\frac{1}{2}\frac{(G_L+G_R)^2}{H_L+H_R+\lambda}+\gamma]-[-\frac{1}{2}\frac{(G_L)^2}{H_L+\lambda}+\frac{(G_R)^2}{H_R+\lambda}+2\lambda] \end{aligned} Gain=objL+R−(objL+objR)=[−21HL+HR+λ(GL+GR)2+γ]−[−21HL+λ(GL)2+HR+λ(GR)2+2λ]
Gain>0则obj下降了;Gain<0分裂失败
不需要归一化,能自动处理缺失值
一、优点:
二、缺点:
XGB与GBDT的不同之处
1、XGB在目标函数中加了正则化项(相当于预剪枝,不易过拟合)
2、XGB不仅用了一阶导数而且还使用了二阶导数
3、支持并行化
4、XGB的基分类器除了CART还可以是线性分类器
5、缺失值处理,自动学习出他的默认分裂方向
6、支持列抽样
XGB为什么使用泰勒二阶展开
1、精准性:更为精准的逼近真实的损失函数
2、可扩展性:损失函数支持自定义,只需要新的损失函数二阶可导
XGB为什么可以并行训练
特征维度并行:在训练之前,每个特征按特征值进行预排序,并存储Block结构,在后面查找分割点重复使用(并行查找)
XGB为什么快
1、分块并行:训练前每个特征值排序并存储Block结构,后面查找分割点重复使用,支持并行查找每个特征分割点
2、候选分割点:每个特征采用常数个分位点作为候选分割点
3、CPU cache命中优化:使用缓存预取的方法,对每个线性分配一个连续buffer,读取每个Block中样本的梯度信息并存入连续buffer中
4、Block处理优化:Block预先放入内存,Block按列进行解压缩,将Block划分到不同硬盘来提高吞吐
XGB防止过拟合的方法
1、目标函数添加了正则项(叶子节点数+叶子节点权重 L 2 L_2 L2正则化)
2、列抽样(训练的时候只用一部分特征)
3、子采样(每轮计算可以不使用全部样本)
4、Shrinkage(学习率|步长,为了给后面训练流出更多的学习空间)
XGB如何处理缺失值
1、在特征上寻找分割点时不考虑缺失值,只考虑non—missing值
2、训练时缺失值自定义划分方向放到右子结点
3、预测时分别划分到左叶子节点与右叶子节点各计算一遍,选择分裂后增益最大的方向
XGB一棵树停止生长的条件
1、Gain<0停止分裂
2、达到树的最大深度
3、最小样本权重和(引入一次分裂后,重新计算生成左右2个叶子结点的样本权重和,如果任意一个叶子节点的样本权重低于某一个阈值,放弃本次分裂)
4、最小样本数量(叶子)
XGB如何处理不平衡数据
1、采用AUC评估模型性能,可以通过scale_pos_weight来平衡正、负样本权重(关注AUC)
2、通过上采样与下采样
3、如果在意正确率,不能平衡数据(破坏真实分布),应该设置max_delta_step为一个有限数字帮助收敛(基模型为LR时有效)
GBDT与LR
1、LR可解释性强,可并行化,需要大量特征工程
2、GBDT非线性,特征表达能力强,无法并行,易过拟合
3、高维稀疏场景下,LR比GBDT好
XGB如何剪枝
1、正则化
2、Gain的阈值
3、最小样本权重和
4、最大深度
XGB如何评价特征重要性
1、weight:该特征在所有树中被用作分割样本特征的总次数
2、gain:该特征在其出现过的所有树中产生平均增益
3、cover:在其出现过的所有树中平均覆盖范围(一个特征作为分割点,影响的样本数量。即有多少个样本经过该特征分割到2个子节点)
XGB过拟合如何解决
1、控制模型复杂度(max_depth、min_child_weight等参数)
2、增加随机性(subsample和colsample_bytree)
3、减少学习率,同时增加迭代次数(estimator)
RF与GBDT的区别
1、集成学习:RF属于baggig,GBDT属于boosting
2、偏差-方差:RF降低方差,GBDT降低偏差
3、训练样本:RF抽样,GBDT全部样本
4、并行:RF可并行,GBDT不可并行
5、泛化能力:RF不易过拟合,GBDT易过拟合
6、异常值:RF对异常值不敏感,GBDT对异常值敏感
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder#分类变量编码包
from sklearn.metrics import roc_auc_score,roc_curve,auc,precision_score,f1_score,accuracy_score,classification_report,recall_score
from sklearn.model_selection import train_test_split
from xgboost.sklearn import XGBClassifier
import matplotlib.pylab as plt
import xgboost as xgb
import os
os.chdir('E:/wyz/Desktop/XGB/')
data = pd.read_excel('ceshi.xlsx',sheet_name = 'Sheet2')
#分类变量编码
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
str_variable = list(data.dtypes[data.dtypes.values == object].index)
for col in str_variable:
data[col] = le.fit_transform(data[col].astype(str))
#划分数据集
y = data_model['target']
x = data_model.drop('target', axis=1)
x_train, x_test, y_train, y_test = train_test_split(x, y,random_state=0,train_size=0.7)
#通过交叉验证的方法来获取最优的迭代次数(树的数量)
def modelfit1(alg,train_x,train_y,test_x,test_y,useTrainCV=True,cv_folds=5,early_stopping_rounds=20):
if useTrainCV:
xgb_param = alg.get_xgb_params()#获取xgb参数
xgtrain = xgb.DMatrix(train_x.values,label=train_y.values)#传入x和y
cvresult = xgb.cv(xgb_param,
xgtrain,#训练数据
num_boost_round=alg.get_params()['n_estimators'],#树的数量
nfold=cv_folds,#交叉验证
metrics='auc',#评价指标
early_stopping_rounds=early_stopping_rounds,#连续迭代多少次auc不在下降
# verbose_eval=10,#每隔1轮打印一次评价指标
show_stdv=False )#不打印标准差
alg.set_params(n_estimators=cvresult.shape[0])#得到最优的树的数量
#训练集上的拟合
alg.fit(train_x,train_y,eval_metric='auc')#传入x和y
#训练集上的预测
train_class = alg.predict(train_x)#输出0和1
train_prob = alg.predict_proba(train_x)[:,1]#输出1的概率
#测试集上的预测
test_class = alg.predict(test_x)#输出0和1
test_prob = alg.predict_proba(test_x)[:,1]#输出1的概率
#准确率与auc
print('训练集准确率: %.4f'%accuracy_score(train_y,train_class))##准确率,预测为类别(normalize=False返回预测正确的个数)
print('测试集准确率: %.4f'%accuracy_score(test_y,test_class))#准确率,预测为类别(normalize=False返回预测正确的个数)
print('训练集AUC: %.4f'%roc_auc_score(train_y,train_prob))#AUC,预测为概率
print('测试集AUC: %.4f'%roc_auc_score(test_y,test_prob))#AUC,预测为概率
#print(alg.feature_importances_)#变量重要性
return alg
#预测结果
from sklearn.model_selection import cross_val_score
from bayes_opt import BayesianOptimization
#定义贝叶斯优化的f
def model_target(learning_rate,n_estimators,max_depth,min_child_weight,subsample,colsample_bytree,reg_alpha,gamma):
val = cross_val_score(
XGBClassifier(
learning_rate =learning_rate,#学习率
n_estimators=int(n_estimators),#最多的树的数量
max_depth=int(max_depth),#每棵树的最大深度
min_child_weight=min_child_weight,#叶子节点最小的样本权重和
subsample=subsample,#行抽样
colsample_bytree=colsample_bytree,#列抽样
objective= 'binary:logistic',
reg_alpha=reg_alpha,#正则化
gamma=gamma,#当损失函数减少时才会分裂
scale_pos_weight=1,#数值大于0,在样本的类非常不均衡时使用有助于快速收敛
seed=27),x_train,y_train,scoring='roc_auc',cv=5).mean()
return val
model_bo = BayesianOptimization(
model_target,
{'learning_rate':(0.01,0.01),
'n_estimators': (100, 1000),
'max_depth': (2, 4),
'min_child_weight': (0,1),
'subsample': (0.6, 1),
'colsample_bytree':(0.6,1),
'reg_alpha': (0.001, 10),
'gamma':(0.0,0.0)})
model_bo.maximize()
贝叶斯进阶优化
#预测结果
from sklearn.model_selection import cross_val_score
from bayes_opt import BayesianOptimization
#定义贝叶斯优化的f
def model_target(learning_rate,n_estimators,max_depth,min_child_weight,subsample,colsample_bytree,reg_alpha,gamma):
val = cross_val_score(
XGBClassifier(
learning_rate =learning_rate,#学习率
n_estimators=int(n_estimators),#最多的树的数量
max_depth=int(max_depth),#每棵树的最大深度
min_child_weight=min_child_weight,#叶子节点最小的样本权重和
subsample=subsample,#行抽样
colsample_bytree=colsample_bytree,#列抽样
objective= 'binary:logistic',
reg_alpha=reg_alpha,#正则化
gamma=gamma,#当损失函数减少时才会分裂
scale_pos_weight=1,#数值大于0,在样本的类非常不均衡时使用有助于快速收敛
seed=27),x_train,y_train,scoring='roc_auc',cv=5).mean()
return val
model_bo = BayesianOptimization(
model_target,
{'learning_rate':(0.01,0.01),
'n_estimators': (100, 1000),
'max_depth': (2, 4),
'min_child_weight': (0,1),
'subsample': (0.6, 1),
'colsample_bytree':(0.6,1),
'reg_alpha': (0.001, 10),
'gamma':(0.0,0.0)})
model_bo.maximize()
XGB参数详解
参数 | 默认值及输入类型 | 介绍 |
---|---|---|
booster | 默认值:gbtree 输入:gbtree、gblinear |
在每次迭代中选择模型的类型,有2个选项:gbtree:基于树的模型gblinear:基于回归的模型 |
silent | 默认值:0 输入:0、1 |
激活Silent mode就设置为1,即正在运行的消息不会被打印。默认为0,好处就是帮助我们理解模型运行状况 |
nthread | 默认值:使用所有的核 | 这个参数用于并行处理,系统中的核的数量如果想运行所有的核,就不用再输入nthread的值,因为默认情况就是使用所有核。还有另外两个参数是由XGBoost自动设置的,下面继续探索Booster参数 |
eta | 默认值:0.3 | 与GBM中的eta类似。在每一步中收缩权重使得模型更加稳健。通常设置值为:0.01−0.2 |
min_child_weight | 默认值:1 | 孩子节点中最小的样本权重和。如果一个叶子节点的样本权重和小于min_child_weight则拆分过程结束。在现行回归模型中,这个参数是指建立每个模型所需要的最小样本数。该成熟越大算法越conservative这与GBM中的min_child_leaf类似,但不完全相同,XGBoost指 min “sum of weights” of observations 而 GBM 为 min “number of observations”。可用于控制过拟合。太高的值可能导致欠拟合,应使用CV进行调参 |
max_depth | 默认值:6 | 与GBM一样,定义了一棵树的最大深度。用于控制过拟合,因为较高的深度会使模型对一些样本学习到特定关系,而这种关系又不是泛化的。适合用CV进行调整值的大小。通常设置值为:3−10 |
max_leaf_nodes | 树中节点或树叶的最大数量。有时可以代替max_depth。 如:二叉树,深度“n”将产生最大2 ^ n个叶。如果这样,GBM可以忽略max_depth | |
gamma | 默认值:0 | 只有当损失函数以正值减少时,节点才会分割。 Gamma指定了进行分割时所需的最小损失的减少量。使算法比较保守。 Gamma值可以根据损失函数调整大小 |
max_delta_step | 默认值:0 | 如果max_delta_step设置为0,表示没有约束。 可以取正值。这个参数不是必须要设定的。在逻辑回归中,当类别比例非常不平衡时,这个参数很有用 |
subsample | 默认值:1 | 与GBM取子样本一样,都是对总体进行随机采样出子样本占总体的比例。较低的值使算法比较保守,可以防止过度拟合,但太小的值可能会导致欠拟合。通常设置值为:0.5−1 |
colsample_bytree | 默认值:1 | 类似于GBM中的max_features。 表示随机抽取的列数占总列数的比例。通常设置值为:0.5−1 |
colsample_bylevel | 默认值:1 | 表示每个层中用于拆分时的列数占比(相当于选出的列数的再比例)。这个参数不常用,因为subsample和 colsample_bytree可以替代这个参数的作用 |
lambda | 默认值:1 | L2对权重正则化(Ridge回归也是L2)这用于XGBoost的正则化部分。 虽然许多数据科学家一般不用它,但是减少过拟合的时候还是要用一下的 |
alpha | 默认值:0 | L1对权重正则化(类似于Lasso回归的L1)维度较高时使用,可以运行得更快 |
scale_pos_weight | 默认值:1 | 数值大于0,在样本的类非常不均衡时使用有助于快速收敛 |
seed | 默认值:0 | 种子随机数。使采样的结果与之前相同以及参数调整 |
objective | 默认值:reg:linear | 这个参数定义了要最小化的损失函数。 有如下选择: objective [default=reg:linear] 这个参数定义了要最小化的损失函数。 有如下选择: binary:logistic:用于二分类的逻辑回归,返回值为概率,非类别。 multi:softmax:使用softmax目标的多类分类返回预测类(不是概率)。 还需设置一个num_class(number of classes)参数来定义类的数量。 multi:softprob: 与softmax相同,但返回的是每个样本属于每个类的预测概率而不是类别。 eval_metric [ default according to objective ] 默认值为rmse用于回归,错误率用于分类。可选值有: 1、rmse – root mean square error 2、mae – mean absolute error 3、logloss– negative log-likelihood 4、error – Binary classification error rate (0.5 threshold) 5、merror – Multiclass classification error rate 6、mlogloss – Multiclass logloss 7、auc: Area under the curve |