一、XGBoost的介绍
1.什么是XGBoost?
XGBoost(eXtreme Gradient Boosting)是一种基于梯度提升树的机器学习算法,它在解决分类和回归问题上表现出色。它是由陈天奇在2014年开发的,如今已成为机器学习领域中最流行和强大的算法之一。
XGBoost结合了梯度提升框架和决策树模型,通过迭代地训练一系列的决策树来逐步改进预测性能。它的目标是优化损失函数,使得预测值与实际值之间的误差最小化。
2.XGBoost的主要特点
- 梯度提升树:XGBoost使用梯度提升框架,通过迭代地训练多个决策树来不断改进模型的预测能力。
- 正则化:XGBoost引入了正则化技术,包括L1和L2正则化,以控制模型的复杂度并减少过拟合的风险。
- 特征重要性:XGBoost能够评估特征的重要性,并根据特征的贡献度进行特征选择。
- 并行计算:XGBoost支持并行计算,可以有效地利用多个CPU核心加速训练过程。
- 缺失值处理:XGBoost能够自动处理缺失值,无需对缺失值进行预处理。
- 可扩展性:XGBoost可以处理大规模数据集和高维特征,具有很好的可扩展性。
- 多种语言支持:XGBoost提供了多种编程语言的接口,包括Python、R、Java等。
由于XGBoost在准确性、灵活性和效率方面的优势,它在各种机器学习任务中被广泛应用,包括分类、回归、排序、推荐系统等。它在许多机器学习竞赛和实际应用中取得了显著的成绩,成为了许多数据科学家和机器学习从业者的首选算法之一。
3.XGBoost的算法原理
XGBoost(eXtreme Gradient Boosting)是一种梯度提升树(Gradient Boosting Tree)算法,它是一种集成学习方法,通过将多个弱学习器(通常是决策树)进行集成来构建一个更强大的预测模型。下面是XGBoost的算法原理:
- 损失函数:XGBoost的目标是最小化一个定义在预测值和实际值之间的损失函数。常用的损失函数包括平方损失函数(回归问题)和对数损失函数(二分类和多分类问题)。
- 基础模型:XGBoost使用回归树作为基础模型,每个回归树由一系列决策节点和叶节点组成。初始时,XGBoost使用一个简单的基础模型(如一个叶节点)作为起点。
- 残差计算:在每轮迭代中,XGBoost通过计算当前模型的预测值与实际值之间的残差来进行训练。这里的残差表示当前模型对样本的预测结果与真实值之间的差异。
- 损失函数近似:为了优化损失函数,XGBoost使用泰勒展开(Taylor expansion)来近似损失函数。将损失函数进行二阶泰勒展开后,可以得到一个简化的目标函数,其中包括关于残差的一阶导数和二阶导数。
- 弱学习器训练:XGBoost以梯度下降的方式训练每个回归树。根据目标函数的一阶导数和二阶导数,XGBoost计算每个样本在当前模型下的梯度和二阶梯度。然后,通过拟合一个新的回归树来近似梯度和二阶梯度,使得模型能够更好地预测这些样本的残差。
- 加权组合:XGBoost使用一定的步长(学习率)将新构建的回归树与当前模型进行加权组合。这样,每轮迭代都会得到一个更新的模型,它在之前模型的基础上进一步提高了预测能力。
- 正则化:为了控制模型的复杂度和防止过拟合,XGBoost引入了正则化项。正则化项包括树的复杂度和叶节点权重的惩罚项,可以限制树的深度和叶节点的权重。
- 迭代训练:通过多轮迭代,XGBoost不断优化模型的预测能力,直到达到停止条件(如达到指定的迭代次数、模型在验证集上的性能不再提升等)。
- 预测:训练完成后,可以使用XGBoost模型进行预测。对于回归问题,预测值为多个回归树的加权求和;对于分类问题,预测值可以通过使用softmax函数将多个回归树的输出转化为概率。
总之,XGBoost通过迭代训练多个回归树,以梯度下降的方式优化损失函数,通过加权组合多个回归树的预测结果来得到最终的预测值。它通过特定的损失函数近似和正则化技术,提供了一种高效而强大的机器学习算法,适用于回归问题和分类问题。
4.XGBoost的回归树构建流程
XGBoost使用回归树作为基础模型,下面是XGBoost构建回归树的方法:
- 划分候选特征:对于每个节点,在训练数据中选择一部分特征作为候选特征。常用的特征选择方法有随机选择、按照特征重要性排序等。
- 特征分割点搜索:对于每个候选特征,通过遍历特征的所有可能取值或使用一些启发式算法(如贪婪算法)来搜索最佳的特征分割点。分割点的选择通常基于某种准则(如最小化平方损失、最大化信息增益等)来衡量分割的质量。
- 分割节点:根据选定的特征和分割点,将当前节点的训练样本分成左子节点和右子节点。左子节点包含满足分割条件的样本,右子节点包含不满足分割条件的样本。
- 终止条件:对每个节点,可以设置一些终止条件来判断是否停止分割节点。常见的终止条件包括树的最大深度、节点包含的最小样本数等。
- 递归构建:根据上述步骤,递归地构建子节点,直到满足终止条件为止。这样就得到了一棵完整的回归树。
- 正则化:为了控制树的复杂度和防止过拟合,XGBoost引入了正则化项。正则化项包括树的复杂度和叶节点权重的惩罚项,可以限制树的深度和叶节点的权重。
- 加权叶节点输出:对于回归问题,XGBoost为每个叶节点分配一个权重,表示该叶节点的输出。这些权重可以通过优化损失函数得到。
- 预测:对于新的样本,通过遍历回归树的节点,并根据节点的分割条件判断样本应该进入左子树还是右子树,最终得到叶节点的输出值。预测值可以通过加权叶节点输出的加和来得到。
XGBoost的回归树构建方法与传统的决策树构建方法类似,但引入了正则化和加权叶节点输出的技术来提高模型的泛化能力和预测准确性。通过迭代地构建多个回归树,并使用梯度提升的方式优化模型的预测能力,XGBoost能够在回归问题中取得较好的性能。
5.XGBoost与GBDT的区别
XGBoost(eXtreme Gradient Boosting)与GBDT(Gradient Boosting Decision Tree)都是基于梯度提升树(Gradient Boosting Tree)的算法,它们在原理上有一些相似之处,但也存在一些区别。以下是XGBoost与GBDT的几个主要区别:
- 正则化技术:XGBoost引入了正则化项来控制模型的复杂度,包括树的复杂度和叶节点权重的惩罚项。这些正则化项可以通过控制树的深度、叶节点权重等来限制模型的复杂度,防止过拟合。而GBDT通常只使用树的剪枝来进行正则化。
- 损失函数的优化:XGBoost使用了二阶泰勒展开来逼近目标函数,并使用近似的方式优化损失函数,提高了模型的拟合能力和训练效率。相比之下,GBDT通常使用一阶泰勒展开来逼近目标函数,并采用贪婪算法进行优化。
- 特征分裂策略:XGBoost采用了一种近似的贪婪算法来选择最佳的特征分裂点,同时结合了精确的分位数方法来处理连续特征。这种分裂策略可以提高模型的训练速度。而GBDT通常采用精确的枚举方式来选择最佳的特征分裂点,计算量较大。
- 并行计算:XGBoost在训练过程中支持并行计算,可以有效地利用多核CPU进行加速,提高训练速度。而GBDT的训练过程通常是串行的,无法充分利用多核CPU。
- 缺失值处理:XGBoost能够自动处理缺失值,无需对缺失值进行特殊处理。而GBDT通常需要对缺失值进行额外处理,如特殊编码或填充。
总体而言,XGBoost在算法设计和实现上对GBDT进行了一系列的改进和优化,包括正则化、近似优化、特征分裂策略、并行计算等方面。这些改进使得XGBoost在训练速度、模型的准确性和泛化能力上都具有一定的优势。
二、XGBoost算法API介绍
1.XGBoost的安装
pip3 install xgboost
2.XGBoost参数介绍
xgboost中封装了很多参数,主要由三种类型构成:通用参数(general parameters),Booster参数(booster parameters)和学习目标参数(task parameters)
- 通用参数:主要是宏观函数控制;
- Booster参数:取决于选择的Booster类型,用于控制每一步的booster(tree,regression);
- 学习目标参数:控制训练目标的表现。
通用参数:
- booster:决定使用哪个booster,可以是gbtree,gblinear或者dart,默认值是gbtree。
- gbtree和dart使用基于树的模型(dart主要多了Dropout),而gblinear使用线性函数。
- silent:设置为0打印运行信;设置为1静默模式,不打印,默认值是0
- nthread:并行运行xgboost的线程数,输入的参数要小于等于系统的CPU核心数。默认值是最大可能的线程数。
- num_pbuffer[xgboost自动设置,不需要用户设置]:预测结果缓存大小,通常设置为训练实例的个数。
- num_feature[xgboost自动设置,不需要用户设置]:在boosting中使用特征的维度,设置为特征的最大维度
Booster参数:
- Tree Booster 的参数:
- eta(别名 learning_rate):
- 更新中减少的步长来防止过拟合。
- 在每次boosting之后,可以直接获得新的特征权值,这样可以使得boosting更加鲁棒。
- 范围是[0,1],这个参数的默认值为0.3
- gamma(别名 min_split_loss(分裂最小loss)):
- 在节点分裂时,只有分裂后损失函数的值下降了,才会分裂这个节点。
- gamma指定了节点分裂所需的最小损失函数下降值。这个参数的值越大,算法越保守。这个参数的值和损失函数息息相关,所以是需要调整的。
- 范围是[0,∞],这个参数的默认值为0
- max_depth:
- 这个值为树的最大深度。这个值也是避免过拟合的。max_depth越大,模型会学到更具体更局部的样本。该参数设置为0表示没有最大深度限制。
- 范围是[0,∞],这个参数的默认值为6
- min_child_weight:
- 决定最小叶子节点样本权重和。XGBoost的这个参数是最小样本权重的和。
- 当它的值较大时,可以避免模型学习到局部的特殊样本。但是这个值过高,很导致欠拟合。通常这个参数的值要通过CV来调整。
- 范围是[0,∞],这个参数的默认值为1
- subsample:
- 这个参数控制对于每棵树,随机采样的比例。
- 减小这个参数的值,算法会更加保守,避免过拟合。但是,如果这个值设置的过小,它可能会导致欠拟合。
- 典型值:[0.5-1],0.5代表平均采样,防止过拟合。
- 范围是[0,1],这个参数的默认值为1
- colsample_bylevel:
- 用来控制树的每一级的每一次分裂,对列数的采样的占比。
- 范围是[0,1],这个参数的默认值为1
- lambda(别名 reg_lambda):
- 权重的L2正则化项(和Ridge regression类似)
- 这个参数是用来控制XGBoost的正则化部分的。这个参数在减少过拟合上有挺多作用。
- 默认值为1
- alpha:
- 权重的L1正则化项。(和Lasso regression类似)。可以应用在很高维度的情况下,使得算法的速度更快。
- 默认值为0
- scale_pos_weight:
- 在各类别样本十分不平衡时,把这个参数设定为一个正值,可以使算法更快收敛。通常可以将其设置为负样本数目与正样本数目的比值。
- 默认值为1
- eta(别名 learning_rate):
- Linear Booster的参数:
- lambda:
- L2正则化惩罚系数,增加该值会使得模型更加保守。
- 默认值为0
- alpha:
- L1正则化惩罚系数,增加该值会使得模型更加保守。
- 默认值为0
- lambda_bias:
- 偏置上的L2正则化(没有在L1上加偏置,因为不重要)
- 默认值为0
- lambda:
学习目标参数:
- objective:
- “reg:linear”:线性回归
- “reg:logistic”:逻辑回归
- “binary:logistic”:二分类逻辑回归,输出为概率
- “multi:softmax”:使用softmax的多分类器,返回预测的类别。在这种情况下,还需要多设一个参数:num_class(类别数目)
- “multi:softprob”:和"multi:softmax"参数一样,但是返回的是每个数据属于各个类别的概率
- 默认值为:reg:linear
- eval_metric:
- “rmse”:均方根误差
- “mae”:平均绝对值误差
- “logloss”:负对数似然函数值
- “error”:二分类错误率
- 其值通过错误分类数目与全部分类数目比值得到。对于预测,预测值大于0.5被认为是正类,其他归为负类。
- “error@t”:不同的划分阈值可以通过t进行设置
- “merror”:多分类错误率
- “mlogloss”:多分类log损失
- “auc”:曲线下的面积
- 默认值是根据目标函数自己选择
- seed:
- 随机数的种子
- 设置它可以复现随机数据的结果,也可以用于调整参数
- 默认值为0
三、XGBoost的实现案例
1.案例背景
泰坦尼克号沉没是历史上最臭名昭著的沉船事件之一。这场耸人听闻的悲剧震惊了国际社会,并为船舶制定了更好的安全规定。造成海难失事的原因之一是乘客和机组人员没有足够的救生艇。尽管幸存下去有一些运气因素,但有些人比其他人更容易幸存。例如妇女,儿童和上流社会。在这个案例中,要求完成对哪些人可能存活的分析。特别是,要求运用机器学习工具来预测哪些乘客幸免于悲剧。
我们提到的数据集中的特征包括票的类别,是否存活,乘坐班次,年龄,登陆home.dest,房间船和性别等。
数据:https://hbiostat.org/data/repo/titanic.txt
经过观察数据得到:
- 乘坐班是指乘客班(1,2,3),是社会经济阶层的代表
- 其中age数据存在缺失
2.步骤分析
-
获取数据
-
数据基本处理
2.1 确定特征值目标值
2.2 缺失值处理
2.3 数据集划分
-
特征工程(字典特征抽取)
-
机器学习(xgboost)
-
模型评估
3.代码实现
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from xgboost import XGBClassifier
import matplotlib.pyplot as plt
# 1.获取数据
titan = pd.read_csv("https://hbiostat.org/data/repo/titanic.txt")
titan.head()
# 2.数据基本处理
# 2.1确定特征值,目标值
x = titan[["pclass","age","sex"]]
y = titan["survived"]
# 2.2缺失值处理
x["age"].fillna(value=titan["age"].mean(),inplace= True)
# 2.3数据集划分
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.2,random_state=22)
# 3.特征工程--字典类型提取
x_train = x_train.to_dict(orient="records")
x_test = x_test.to_dict(orient="records")
transfer = DictVectorizer(sparse=False)
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.模型训练(XGBoost)以及模型评估
# 模型初步训练
estimator = XGBClassifier()
estimator.fit(x_train,y_train)
score1 = estimator.score(x_test,y_test)
print("模型初步训练的准确率为:\n",score1)
# 针对max_depth进行模型调优
depth_range = range(10)
score = []
for i in depth_range:
estimator = XGBClassifier(eta=0.3,gamma=0,max_depth=i)
estimator.fit(x_train,y_train)
s = estimator.score(x_test,y_test)
print(s)
score.append(s)
# 结果可视化
plt.plot(depth_range,score,"r")
plt.show()