XGBoost
- 1. 原理改进及特点
- 1.1 遵循Boosting算法的基本建模流程
- 1.2 平衡精确性与复杂度
- 1.3 降低模型复杂度、提升运行效率
- 1.4 保留部份GBDT属性
- 2. sklearn接口(回归)
- 2.1 导库 & 数据
- 2.2 sklearn api普通训练
- 2.3 sklearn api交叉验证
- 2.4 查看属性接口
- 3. xgboost原生代码(回归)
- 3.1 导包
- 3.2 DMatrix数据 xgboost.DMatrix()
- 3.3 params参数 params={}
- 3.4 不交叉验证 xgboost.train()
- 3.4.1 参数 & 代码
- 3.4.2 评估指标
- 3.5 交叉验证 xgboost.cv()
- 4. xgboost实现分类
- 4.1 sklearn接口
- 4.2 xgboost原生代码
1. 原理改进及特点
1.1 遵循Boosting算法的基本建模流程
依据上一个弱评估器f(x)k-1的结果,计算损失函数L;
并使用L自适应地影响下一个弱评估器f(x)k的构建。
集成模型输出的结果,受所有弱评估器f(x)0~f(x)K的影响.
1.2 平衡精确性与复杂度
树模型的学习能力和过拟合风险需要平衡,即预测精确性与模型复杂度之间的平衡,经验风险与结构风险之间的平衡。
一般建立模型后手动剪枝调节复杂度,XGBoost在迭代过程中实现平衡。
- XGBoost为损失函数加入结构风险项
AdaBoost、GBDT追求损失函数L(y,y^)
最小化;
XGBoost追求目标函数O(y,y^) = L(y,y^) + 结构风险项
最小化。
XGBoost利用结构风险项控制过拟合,其他树模型依赖树结构max_depth
,min_impurity_decrease
等。 - XGBoost使用新不纯度衡量指标
一般算法建CART树,分类使用信息增益,回归使用MSE或弗里德曼MSE;
XGBoost设定分支指标结构分数,基于结构分数的结构分数增益,向整体结构简单的方向建树。
1.3 降低模型复杂度、提升运行效率
决策树建树,需要对每一个特征上所有潜在的分支节点进行不纯度计算。XGBoost多种优化技巧优化提升效率:
- 全新建树流程
使用估计贪婪算法、平行学习、分位数草图算法等,适用于大数据。 - 提升硬件运算性能
使用感知缓存访问技术、核外计算技术。 - 建树增加随机性
引入Dropout技术。
1.4 保留部份GBDT属性
- 弱评估器是回归器,借助sigmoid或softmax实现分类。
- 拟合负梯度
GBDT中每次用于建立评估器的是样本X,以及当下集成输出H(xi)与真是标签y之间的伪残差(负梯度)。
当损失函数是1/2 MSE时,负梯度等同于残差。
XGBoost同样依赖于拟合残差来影响后续弱评估器建立。 - 抽样思想
对样本和特征进行抽样增大弱评估器之间的独立性。
2. sklearn接口(回归)
2.1 导库 & 数据
from sklearn.model_selection import KFold, cross_validate
from sklearn.model_selection import train_test_split
from xgboost import XGBRegressor
'''
xgboost提供的sklearn api
XGBRegressor() 实现xgboost回归
XGBClassifier() 实现xgboost分类
XGBRanker() 实现xgboost排序
XGBRFClassifier() 基于xgboost库实现随机森林分类
XGBRFRegressor() 基于xgboost库实现随机森林回归
'''
from sklearn.datasets import load_digits
data = load_digits()
X = data.data
y = data.target
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=1412)
print(Xtrain.shape, Xtest.shape)
'''
(1257, 64) (540, 64)
'''
2.2 sklearn api普通训练
# sklearn普通训练:实例化,fit,score
# booster 使用弱评估器建树,可选gbtree,gbliner,dart
xgb_sk = XGBRegressor(random_state=1412)
xgb_sk.fit(Xtrain, Ytrain)
xgb_sk.score(Xtest, Ytest) # 默认评估指标R^2
'''
0.831818417176343
'''
2.3 sklearn api交叉验证
# sklearn交叉验证:实例化,交叉验证,结果求平均
xgb_sk = XGBRegressor(random_state=1412)
cv = KFold(n_splits=5, shuffle=True, random_state=1412)
result_xgb_sk = cross_validate(xgb_sk
,X,y
,scoring='neg_root_mean_squared_error' #-RMSE
,return_train_score=True
,verbose=True
,n_jobs=-1
)
result_xgb_sk
'''
{'fit_time': array([1.49709201, 1.51305127, 1.5214994 , 1.52006483, 1.49009109]),
'score_time': array([0.00797772, 0.0069809 , 0.02449441, 0.00797725, 0.01301908]),
'test_score': array([-1.3107202 , -1.3926962 , -1.34945876, -1.18663263, -1.49893354]),
'train_score': array([-0.0196779 , -0.02156499, -0.0167526 , -0.01670659, -0.02254371])}
'''
def RMSE(result, name):
return abs(result[name].mean())
RMSE(result_xgb_sk, 'train_score')
'''
0.019449156665978885
'''
RMSE(result_xgb_sk, 'test_score')
'''
1.347688263452443
'''
2.4 查看属性接口
# sklearn查看属性接口
xgb_sk = XGBRegressor(max_depth=5).fit(X,y)
xgb_sk.feature_importances_ # 特征重要性
'''
array([0. , 0.00225333, 0.00230321, 0.00326973, 0.00863725,
0.00895859, 0.00746422, 0.00157759, 0. , 0.00096148,
0.00569782, 0.00173326, 0.02128937, 0.00525403, 0.00283347,
0.00028462, 0.00450659, 0.00130977, 0.01772124, 0.00536137,
0.04007934, 0.06141694, 0.00869896, 0.00226618, 0. ,
0.00413993, 0.01785861, 0.03045771, 0.0369929 , 0.03439412,
0.04346734, 0.00481802, 0. , 0.04838382, 0.01810016,
0.03241276, 0.06217332, 0.00609181, 0.00342981, 0. ,
0. , 0.00546112, 0.04138443, 0.00643031, 0.00676051,
0.00443247, 0.00591809, 0. , 0. , 0.00230393,
0.00367385, 0.02346367, 0.0843313 , 0.01382598, 0.00216754,
0.00023067, 0. , 0.00051113, 0.01587264, 0.00686751,
0.01672259, 0.01588235, 0.00281848, 0.18434276], dtype=float32)
'''
# 调出单独的树
xgb_sk.get_booster()[1]
'''
<xgboost.core.Booster at 0x1f23889a550>
'''
# 一共建立树数量,n_estimators取值
xgb_sk.get_num_boosting_rounds()
'''
100
'''
# 获取参数取值
xgb_sk.get_params()
'''
{'objective': 'reg:squarederror',
'base_score': 0.5,
'booster': 'gbtree',
'callbacks': None,
'colsample_bylevel': 1,
'colsample_bynode': 1,
'colsample_bytree': 1,
'early_stopping_rounds': None,
'enable_categorical': False,
'eval_metric': None,
'gamma': 0,
'gpu_id': -1,
'grow_policy': 'depthwise',
'importance_type': None,
'interaction_constraints': '',
'learning_rate': 0.300000012,
'max_bin': 256,
'max_cat_to_onehot': 4,
'max_delta_step': 0,
'max_depth': 5,
'max_leaves': 0,
'min_child_weight': 1,
'missing': nan,
'monotone_constraints': '()',
'n_estimators': 100,
'n_jobs': 0,
'num_parallel_tree': 1,
'predictor': 'auto',
'random_state': 0,
'reg_alpha': 0,
'reg_lambda': 1,
'sampling_method': 'uniform',
'scale_pos_weight': 1,
'subsample': 1,
'tree_method': 'exact',
'validate_parameters': 1,
'verbosity': None}
'''
3. xgboost原生代码(回归)
3.1 导包
from sklearn.datasets import load_digits
import xgboost # 原生代码只需导入xgboost
data = load_digits()
X = data.data
y = data.target
print(X.shape,y.shape)
'''
(1797, 64) (1797,)
'''
3.2 DMatrix数据 xgboost.DMatrix()
- 必须使用xgboost自定义的数据结构DMatrix
'''
返回专用的DMatrix对象
不能索引和循环读取, 即不可查看和修改
不分X,y,特征和标签同时打包,训练时作为dtrain的输入
'''
data_xgb = xgboost.DMatrix(X,y)
print(data_xgb)
'''
若需划分训练测试集,需提前划分再转换类型
'''
from sklearn.model_selection import train_test_split
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y,test_size=0.3,random_state=1412)
dtrain = xgboost.DMatrix(Xtrain, Ytrain)
dtest = xgboost.DMatrix(Xtest, Ytest)
print(dtrain, dtest)
'''
<xgboost.core.DMatrix object at 0x000001F237D29DC0>
<xgboost.core.DMatrix object at 0x000001F237D293A0> <xgboost.core.DMatrix object at 0x000001F237E36370>
'''
3.3 params参数 params={}
'''
定义参数
参数名称会与sklearn有区别,seed随机数种子
这里的seed是boosting过程的随机数种子
'''
params = {'max_depth':5, 'seed':1412}
3.4 不交叉验证 xgboost.train()
3.4.1 参数 & 代码
'''
xgboost.train()
包含了实例化和训练过程,返回实例
训练时没区分回归分类,默认执行回归算法
.train()中,params外
num_boost_round 控制建树数量(迭代次数)
提前停止
一般来说除了上述两个参数,其余参数设置在params中
params中
xgb_model 指定弱评估器,可选gbtree,gbliner,dart评估器有不同的params列表
eta boosting算法中的学习率
objective 用于优化的损失函数,分类使用
base_score 初始化预测结果H0的值
max_delta_step 一次迭代中允许的最大迭代值
目标函数参数 https://www.bilibili.com/video/BV1Au411B7bC
gamma,lambda,alpha 放大可控制过拟合
'''
reg = xgboost.train(params, data_xgb, num_boost_round=100)
y_pred = reg.predict(data_xgb)
y_pred
'''
array([-0.10801424, 0.84069467, 2.083782 , ..., 8.143546 ,
8.9779825 , 8.03064 ], dtype=float32)
'''
3.4.2 评估指标
# 评估指标
# 借用sklearn.metrics
from sklearn.metrics import mean_squared_error as MSE
# squared=False 使用RMSE
MSE(y, y_pred, squared=False)
'''
0.10822869258896699
'''
# 特征重要性
from xgboost import plot_importance
plot_importance(reg)
'''
<AxesSubplot:title={'center':'Feature importance'}, xlabel='F score', ylabel='Features'>
'''
3.5 交叉验证 xgboost.cv()
'''
不会返回模型,train()可以返回模型
返回评估指标和数值
'''
result = xgboost.cv(params, data_xgb, num_boost_round=100
,nfold=5 # 5折
# 交叉验证的随机数种子
# params中seed是建树的随机数种子
,seed=1412
)
'''
返回DataFrame
100行代表num_boost_round定义迭代100次
每一次迭代都会进行5折交叉验证,显示结果为5次的平均
4列,训练集/测试集 上的 均值/标准差
很适合用来绘制图像
'''
result
train-rmse-mean | train-rmse-std | test-rmse-mean | test-rmse-std | |
---|---|---|---|---|
0 | 3.638185 | 0.039632 | 3.677730 | 0.202608 |
1 | 2.763450 | 0.028739 | 2.878112 | 0.173517 |
2 | 2.128277 | 0.020819 | 2.303325 | 0.152110 |
3 | 1.677589 | 0.027772 | 1.911049 | 0.117346 |
4 | 1.373573 | 0.034642 | 1.657949 | 0.097172 |
... | ... | ... | ... | ... |
95 | 0.094639 | 0.004466 | 1.076697 | 0.055437 |
96 | 0.092524 | 0.004142 | 1.076498 | 0.055798 |
97 | 0.091061 | 0.003936 | 1.076479 | 0.055860 |
98 | 0.089755 | 0.003874 | 1.076414 | 0.055971 |
99 | 0.088533 | 0.003673 | 1.076586 | 0.056002 |
100 rows × 4 columns
import matplotlib.pyplot as plt
# dpi=300分辨率,figsize=[,]画布大小
plt.figure()
plt.plot(result['train-rmse-mean'])
plt.plot(result['test-rmse-mean'])
plt.legend(['train', 'test'])
plt.title('xgboost 5fold cv')
4. xgboost实现分类
4.1 sklearn接口
from xgboost import XGBClassifier
4.2 xgboost原生代码
'''
objective:
“reg:linear” 线性回归.
“reg:logistic" 逻辑回归.
“binary:logistic” 二分类的逻辑回归问题,输出为概率.
“binary:logitraw” 二分类的逻辑回归问题,输出的为wTx.
“count:poisson” 计数问题的poisson回归,输出结果为poisson分布.max_delta_step默认为0.7.(used to safeguard optimization)
“multi:softmax” softmax处理多分类问题,同时需要设置参数num_class(类别个数).
“multi:softprob” 输出各个分类概率,ndata*nclass向量,表示样本所属于每个类别的概率.
“rank:pairwise” set XGBoost to do ranking task by minimizing the pairwise loss.
'''
params = {'learning_rate':0.1
,'max_depth':5
,'objective':'multi:softmax'
# ,'objective':'multi:softprob'
,'num_class':10
,'random_state':1412
, 'eta':0.8 # boosting算法中的学学习率
}
model = xgboost.train(params, data_xgb, num_boost_round=10)
y_pred = model.predict(data_xgb)
y_pred
'''
array([0., 1., 2., ..., 8., 9., 8.], dtype=float32)
'''