1. 集成算法总结
1.1 Bagging
- 随机森林:多个基模型的构建是基于不同数据来构建的,各个模型是独立,不提提高准确度,但是可以降低过拟合;
1.2 Boosting
- 通过迭代的形式,基于之前构建好的模型,对样本数据做一定的修正【或者改变权重/标签值】然后影响之后模型的构建。不断迭代构建的目的是:让预测更加准确,提升准确度,降低偏差;
- Adaboost
- 通过修正样本的权重
- GBDT
- 通过修正样本的预测值label标签值;
2. XGBoost的基本概述
- XGBoost是GBDT算法的一种变种优化,是一种有监督的集成学习算法;是一种伸缩性强、便捷的可并行构建模型的Gradient Boosting算法;
- XGBoost的官网:http://xgboost.readthedocs.io
- XGBoost的Github源码位置:
- XGBoost支持的开发语言:Python、R、Java、Scala、C++等。
3. XGBoost的原理
3.1 CART、GBDT

3.2 模型
- 目标函数
- Obj(θ)=L(θ)+Ω(θ)Obj(\theta)=L(\theta) + \Omega(\theta)Obj(θ)=L(θ)+Ω(θ)
- L(θ)L(\theta)L(θ)是误差函数,体现的是模型有多拟合数据;
- Ω(θ)\Omega(\theta)Ω(θ)正则化项:惩罚复杂模型的参数用于解决过拟合;
3.3 GBDT的目标函数
- obj=∑i=1nl(yi,yi−(t))obj=\sum_{i=1}^nl(y_i, y_i^-(t))obj=∑i=1nl(yi,yi−(t))
- 逐步迭代
- yi−(0)=0y_i^-(0)=0yi−(0)=0
- yi−(1)=yi−(0)+f1(xi)y_i^-(1)=y_i^-(0)+f_1(x_i)yi−(1)=yi−(0)+f1(xi)
- yi−(2)=yi−(1)+f2(xi)y_i^-(2)=y_i^-(1)+f_2(x_i)yi−(2)=yi−(1)+f2(xi)
- …
- yi−(t)=yi−(t−1)+ft(xi)y_i^-(t)=y_i^-(t-1)+f_t(x_i)yi−(t)=yi−(t−1)+ft(xi)
- 并没有考虑模型的复杂程度
3.4 XGBoost的目标函数
- 在GBDT的目标函数上增加正则化项[主要考虑基函数的复杂度]
- obj=∑i=1nl(yi,yi−(t))+∑i=1tΩ(fi)obj=\sum_{i=1}^nl(y_i, y_i^-(t))+\sum_{i=1}^t\Omega(f_i)obj=∑i=1nl(yi,yi−(t))+∑i=1tΩ(fi)
- 逐步迭代
- yi−(0)=0y_i^-(0)=0yi−(0)=0
- yi−(1)=yi−(0)+f1(xi)y_i^-(1)=y_i^-(0)+f_1(x_i)yi−(1)=yi−(0)+f1(xi)
- yi−(2)=yi−(1)+f2(xi)y_i^-(2)=y_i^-(1)+f_2(x_i)yi−(2)=yi−(1)+f2(xi)
- …
- yi−(t)=yi−(t−1)+ft(xi)y_i^-(t)=y_i^-(t-1)+f_t(x_i)yi−(t)=yi−(t−1)+ft(xi)
- 假设ft(x)=ωq(x)f_t(x)=\omega_q(x)ft(x)=ωq(x),ωq(x)\omega_q(x)ωq(x)表示第q个叶子节点的预测值
- $\Omega(f)=\gamma T+\frac{1}{2}\lambda \sum_{j=1}^T \omega_j^2 $,T表示当前这棵树的叶子节点数,后面表示叶子节点的预测值不能太大【相当于模型的复杂度有两部分组成:叶子节点数(分的太细)和叶子节点的预测值不能太大】
3.5 XGBoost公式的推导
- 第t次迭代之后,模型的预测等于前t-1次的模型加上第t棵树的预测结果:yi−(t)=yi−(t−1)+ft(xi)y_i^-(t)=y_i^-(t-1)+f_t(x_i)yi−(t)=yi−(t−1)+ft(xi)
- 目标函数可以写成:loss=∑i=1nl(yi,yit−1+ft(xi))+∑t=1t−1Ω(fi)+Ω(ft)loss=\sum_{i=1}^nl(y_i, y_i^{t-1}+f_t(x_i))+\sum_{t=1}^{t-1}\Omega(f_i)+\Omega(f_t)loss=∑i=1nl(yi,yit−1+ft(xi))+∑t=1t−1Ω(fi)+Ω(ft)
- 将误差函数中的yit−1+ft(xi)y_i^{t-1}+f_t(x_i)yit−1+ft(xi)当成一个整体在yit−1y_i^{t-1}yit−1初进行二阶泰勒展开
- loss≈∑in[l(yi,yit−1)+gift(xi)+12hift2(xi)]+∑i=1t−1Ω(fi)+Ω(ft)loss\approx \sum_i^n [l(y_i,y_i^{t-1})+g_i f_t(x_i)+\frac{1}{2}h_i f_t^2(x_i)]+\sum_{i=1}^{t-1}\Omega(f_i)+\Omega(f_t)loss≈∑in[l(yi,yit−1)+gift(xi)+21hift2(xi)]+∑i=1t−1Ω(fi)+Ω(ft)
- gi=∂yit−1l(yi,yit−1)g_i=\partial_{y_i^{t-1}}l(y_i, y_i^{t-1})gi=∂yit−1l(yi,yit−1)
- hi=∂yit−12l(yi,yit−1)h_i=\partial_{y_i^{t-1}}^2l(y_i, y_i^{t-1})hi=∂yit−12l(yi,yit−1)
- t=yi+ft(x),t0=ft−1(x)t=y_i+f_t(x), t_0=f_{t-1}(x)t=yi+ft(x),t0=ft−1(x)
5.



3.6 GBDT和XGBoost的比较
- XGBoost在GBDT的基础上加入了正则化项,防止模型过拟合;
- XGBoost在构建的过程中,考虑了二阶导函数;而GBDT只考虑了一阶导函数;
- XGBoost中决策树的构建是基于损失函数的;而GBDT内的决策树(CART)是基于MSE/MAE/Gini
系数 - XGBoost支持列采样(类似随机森林的方式),可以降低过拟合的情况;
- XGBoost是并行计算的,此处的并行指的是:划分特征选择过程中是并行计算的;
- GBDT底层只支持CART,XGBoost底层不仅支持CART,还支持线性回归、逻辑回归;
- 一般很少用xgboost来获取特征的重要性权重
3.7 XGBoost的学习策略
- 当树的结构确定的时候,我们就可以得到最优的叶子节点分数以及对应的最小损失值,问题在于如何确定树结构:
- 暴力穷举法:暴力穷举所有可能的树结构,选择损失最小的树【难度较大】;
- 贪心算法:每次尝试选择一个分裂节点进行分裂,计算操作前后的增益,选择增益最大的方式进行分裂;
- 决策树相关的算法计算指标
- ID3算法:信息增益
- C4.5算法:信息增益率
- CART算法:Gini系数






3.8 XGBoost的其他特性
- 列采样(column subsampling):借鉴随机森林的做法,支持列采样,不仅可以降低过拟合,而且还可以提高计算量;
- 支持对缺失值的自动处理:对于某个特征有缺失的样本,XGBoost可以自动学习分裂方向;
- SGBoost支持并行算法;XGBoost的并行实在特征粒度上进行的,在计算特征的Gain的时候是并行计算的,但是在树的构建过程中,还是串行构建的;
- XGBoost算法中加入正则项,用于控制模型的复杂度,最终模型更加不容易过拟合;
- XGBoost基学习器支持CART、线性回归、逻辑回归;
- XGBoost支持自定义损失函数(要求损失函数二阶可导)
3.9XGBoost API相关参数
| 参数 | XGBClassifier | XGBRegressor |
|---|
| max_depth | 给定树的深度,默认是3 | |
| learning_rate | 每个迭代产生额模型的权重/学习率,默认为0.1 | |
| n_estimators | 子模型的数量,默认为100 | |
| objective | 给定损失函数,默认为“binary:logistics” | 给定损失函数,默认为“reg:linear” |
| booster | 给定模型的求解方式,默认为:gbtree,可选参数:gbtree、gblinear、dart | |
| n_jobs | 使用多少个线程并行构建XGBoost模型,默认为1 | |
| reg_alpha | L1正则的权重,默认为0 | |
| reg_lambda | L2正则的权重,默认为1 | |
## demos
import pandas as pd
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import xgboost as xgb
# load data
X, Y = load_boston(return_X_y=True)
# train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, Y,
test_size=0.15,
random_state=0)
print('Train Set Size:', x_train.shape)
print('Test Set Size:', x_test.shape)
# 构建模型对象,使用XGBoost的相关API
# 1. 直接使用相关的API
# 1.1 数据转换
d_train = xgb.DMatrix(data=x_train, label=y_train, )
d_test = xgb.DMatrix(data=x_test, label=y_test)
# 1.2 模型参数构建
params = {
'max_depth': 50, # 训练数据集
'eta': 0.1, # 迭代次数
'n_estimators': 50,
'objective': 'reg:squarederror',
'booster': 'gbtree'
}
# 1.3 模型训练
model = xgb.train(params=params, # booster 中的参数
dtrain=d_train, # 训练数据集
num_boost_round=50, # 迭代次数
evals=(), # 评价函数
obj=None, # 损失函数
xgb_model=None,)
# 1.4 模型保存
model.save_model('xgb.model')
# 加载模型来预测
model2 = xgb.Booster()
model2.load_model('xgb.model')
pred = model2.predict(d_test)
print('MSE on Test:', mean_squared_error(y_test, pred))
print('r2_score on Test', r2_score(y_test, pred))
from xgboost import plot_importance
from matplotlib import pyplot as plt
plot_importance(model2, importance_type='cover')
plt.show()
