一. 前言
在XGBoost基本原理博文中我们介绍了XGBoost的基本原理,本篇博文我们将介绍XGBoost的基本使用方法,作为新手的学习参考。
本文使用kaggle上的泰坦尼克数据集,只是对XGBoost的使用做一个简单的描述,若想知道Kaggle的整个竞赛流程以及在竞赛中如何使用XGBoost进行预测的话,关注本博客,以后会陆续推出与竞赛内容相关的博客及代码。kaggle的泰坦尼克的数据集分为训练数据和测试数据,测试数据与训练数据的区别在于测试数据缺少‘survival’列,即为我们需要预测的列,数据集中的每列描述如下:
- survival------表示乘客是否存活;0=No,1=Yes
- pclass------表示票的等级;1=1st,2=2nd,3=3rd
- sex------表示乘客性别;
- Age------表示乘客年龄
- sibsp------表示在船上的兄弟姐妹加上配偶的数量
- parch------表示在船上的父母加上子女的数量
- ticket------表示票的编号
- fare------表示票价
- cabin------表示船舱编号
- embarked------表示乘客登录的港口;C = Cherbourg, Q = Queenstown, S = Southampton
接下来就是如何进行简单的特征处理,以及如何用XGBoost对测试集进行预测,同时也会使用其他的模型与XGBoost进行比较。
二. 数据的特征处理
-
import pandas as pd
-
import numpy as np
-
import matplotlib.pyplot as plt
-
import seaborn as sns
-
import xgboost as xgb
-
from sklearn.model_selection import train_test_split
-
from sklearn import preprocessing
-
from sklearn.model_selection import GridSearchCV
-
from sklearn.linear_model import LogisticRegression
-
from sklearn.ensemble import RandomForestClassifier
-
from sklearn.ensemble import GradientBoostingClassifier
-
from sklearn import cross_validation
-
from sklearn.preprocessing import LabelEncoder
-
import warnings
-
warnings.filterwarnings('ignore')
-
train = pd.read_csv('data/train.csv')
-
test = pd.read_csv('data/test.csv')
-
train.info() # 打印训练数据的信息
-
<class 'pandas.core.frame.DataFrame'>
-
RangeIndex: 891 entries, 0 to 890
-
Data columns (total 12 columns):
-
PassengerId 891 non-null int64
-
Survived 891 non-null int64
-
Pclass 891 non-null int64
-
Name 891 non-null object
-
Sex 891 non-null object
-
Age 714 non-null float64
-
SibSp 891 non-null int64
-
Parch 891 non-null int64
-
Ticket 891 non-null object
-
Fare 891 non-null float64
-
Cabin 204 non-null object
-
Embarked 889 non-null object
-
dtypes: float64(2), int64(5), object(5)
-
memory usage: 83.6+ KB
从输出信息中可以看出训练集一共有891个样本,12个特征,所有数据所占的内存大小为83.6K;所有的特征中有两个特征缺失情况较为严重,一个是Age,一个是Cabin;一个缺失不严重Embarked;数据一共有三种类型,float64(2), int64(5), object(5)。
接下来就是对数据的缺失值进行处理,这里采用的方法是对连续值用该列的平均值进行填充,非连续值用该列的众数进行填充,还可以使用机器学习的模型对缺失值进行预测,用预测的值来填充缺失值,该方法这里不做介绍:
-
def handle_na(train, test): # 将Cabin特征删除
-
fare_mean = train['Fare'].mean() # 测试集的fare特征有缺失值,用训练数据的均值填充
-
test.loc[pd.isnull(test.Fare), 'Fare'] = fare_mean
-
embarked_mode = train['Embarked'].mode() # 用众数填充
-
train.loc[pd.isnull(train.Embarked), 'Embarked'] = embarked_mode[0]
-
train.loc[pd.isnull(train.Age), 'Age'] = train['Age'].mean() # 用均值填充年龄
-
test.loc[pd.isnull(test.Age), 'Age'] = train['Age'].mean()
-
return train, test
-
new_train, new_test = handle_na(train, test) # 填充缺失值
由于Embarked,Sex,Pclass特征是离散特征,所以对其进行one-hot/get_dummies编码
-
# 对Embarked和male特征进行one-hot/get_dummies编码
-
new_train = pd.get_dummies(new_train, columns=['Embarked', 'Sex', 'Pclass'])
-
new_test = pd.get_dummies(new_test, columns=['Embarked', 'Sex', 'Pclass'])
然后再去除掉PassengerId,Name,Ticket,Cabin, Survived列,这里不使用这些特征做预测
-
target = new_train['Survived'].values
-
# 删除PassengerId,Name,Ticket,Cabin, Survived列
-
df_train = new_train.drop(['PassengerId','Name','Ticket','Cabin','Survived'], axis=1).values
-
df_test = new_test.drop(['PassengerId','Name','Ticket','Cabin'], axis=1).values
三. XGBoost模型
在用XGBoost模型进行预测之前先对XGBoost进行简单的介绍
XGBoost模型有两种使用方式,一种是原生版本,一种是实现了sklearn接口的版本。
3.1 XGBoost的原生版本参数介绍
这里介绍一些重要的参数,具体的根据实际的应用情况再来查看API。
3.1.1 General Parameters
- booster [default=gbtree]:可选项为gbtree,gblinear或dart;其中gbtree和dart是使用基于树模型的,而gblinear是使用基于线性模型的;
- silent [default=0]:0表示输出运行信息,1表示不输出;
- nthread [如果不进行设置,默认是最大线程数量]:表示XGBoost运行时的并行线程数量;
- disable_default_eval_metric [default=0]:标记以禁用默认度量标准。设置 >0 表示禁用;
- num_pbuffer [通过XGBoost自动设置,不需要用户来设置]:预测缓冲区的大小,通常设置为训练实例的数量;
- num_feature [通过XGBoost自动设置,不需要用户来设置]:被使用在boosting中的特征维度,设置为最大化的特征维度;
3.1.2 Parameters for Tree Booster:
- eta (default=0.3, 别名: learning_rate) :eta表示学习率:range:[0, 1] ,作用:防止过拟合;
- gamma [default=0, 别名: min_split_loss]: 在树的叶节点上进一步分区所需的最小化损失减少,gamma越大算法越保守 range:[0, ∞];
- max_depth [default=6]:表示树的深度,值越大模型越复杂,越容易过拟合。0表示不限制;
- min_child_weight [default=1]:子节点所需要的最小样本权重之和。如果一个叶子节点的样本权重和小于min_child_weight结束节点进一步的切分。在线性回归模型中,这个参数是指建立每个模型所需要的最小样本数。该值越大,算法越保守;
- max_delta_step [default=0]:我们允许每个叶子输出的最大的delta step,该值为0,表示不限制。该值为正数,可以帮助使更新步骤更加保守。通常该参数不需要设置,但是在logistic回归中,分类类别极度不平衡的时候,将该值设置在1_10之间可以帮助控制更新步骤;
- subsample [default=1]:训练数据的子样本,subsample=n,表示在训练数据中随机采样n%的样本,可以防止过拟合。 range:(0, 1] ;
- lambda [default=1, 别名: reg_lambda]: L2正则化项系数;
- alpha [default=0, 别名: reg_alpha]: L1正则化项系数;
- tree_method string [default= auto]:在分布式和外存的版本中,仅支持 tree_method=approx;可选项为:auto, exact, approx, hist, gpu_exact, gpu_hist
- auto:表示使用启发式的方法来选择使运行速度最快的算法,如下:
- 对于小到中等的数据集,Exact Greedy Algorithm将被使用;
- 对于大数据集,Approximate Algorithm将被使用;
- 因为以前的行为总是在单个机器中使用Exact Greedy Algorithm,所以当选择Approximate Algorithm来通知该选择时,用户将得到消息。
- exact:Exact Greedy Algorithm
- approx:Approximate Algorithm
- hist:快速直方图优化近似贪心算法。它使用了一些可以改善性能的方法,例如bins caching;
- gpu_exact:在GPU上执行Exact Greedy Algorithm;
- gpu_hist:在GPU上执行hist算法;
- auto:表示使用启发式的方法来选择使运行速度最快的算法,如下:
- max_leaves [default=0]:设置叶节点的最大数量,仅仅和当row_policy=lossguide才需要被设置;
- max_bin, [default=256]:仅仅tree_method=hist时,该方法需要去设置。bucket连续特征的最大离散bins数量;
3.1.3 学习任务参数(Learning Task Parameters)
- objective [default=reg:linear]
- reg:linear:线性回归;
- reg:logistic:逻辑回归;
- binary:logistic: 二分类逻辑回归,输出概率;
- binary:logitraw: 二分类逻辑回归,在logistic transformation之前输出score;
- binary:hinge: 二分类的hinge损失,让预测为0或1,而不是概率;
- multi:softmax:多分类的使用softmax目标函数,使用此含参数时需要指定多分类分为几类,设置num_class=n;
- multi:softprob: 和softmax相同,但是输出的是每个样本点属于哪个类的预测概率值;
- rank:pairwise:使用XGBoost做排序任务使用的。
- base_score [default=0.5]:所有实例的初始预测分数,全局偏差。对于有足够的迭代数目,改变该值将不会太多的影响;
- eval_metric [default according to objective] :默认:根据objective参数(回归:rmse, 分类:error)。还有许多可以自己查官方API。
3.2 使用XGBoost原生版本模型
-
X_train,X_test,y_train,y_test = train_test_split(df_train,target,test_size = 0.3,random_state = 1)
-
data_train = xgb.DMatrix(X_train, y_train) # 使用XGBoost的原生版本需要对数据进行转化
-
data_test = xgb.DMatrix(X_test, y_test)
-
param = {'max_depth': 5, 'eta': 1, 'objective': 'binary:logistic'}
-
watchlist = [(data_test, 'test'), (data_train, 'train')]
-
n_round = 3
-
booster = xgb.train(param, data_train, num_boost_round=n_round, evals=watchlist)
-
# 计算错误率
-
y_predicted = booster.predict(data_test)
-
y = data_test.get_label()
-
accuracy = sum(y == (y_predicted > 0.5))
-
accuracy_rate = float(accuracy) / len(y_predicted)
-
print ('样本总数:{0}'.format(len(y_predicted)))
-
print ('正确数目:{0}'.format(accuracy) )
-
print ('正确率:{0:.3f}'.format((accuracy_rate)))
下面是XGBoost原生版本对数据进行预测的结果:
3.3 XGBoost的sklearn接口版本参数介绍
因为XGBoost是使用的是一堆CART树进行集成的,而CART(Classification And Regression Tree)树即可用作分类也可用作回归,这里仅仅介绍XGBoost的分类,回归问题类似,有需要请访问XGBoost API的官网进行查看。
class xgboost.XGBClassifier(max_depth=3, learning_rate=0.1, n_estimators=100, silent=True, objective='binary:logistic', booster='gbtree', n_jobs=1, nthread=None, gamma=0, min_child_weight=1, max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, base_score=0.5, random_state=0, seed=None, missing=None, **kwargs)
- max_depth : int 表示基学习器的最大深度;
- learning_rate : float 表示学习率,相当于原生版本的 "eta";
- n_estimators: int 表示去拟合的boosted tree数量;
- silent:boolean 表示是否在运行boosting期间打印信息;
- objective:string or callable 指定学习任务和相应的学习目标或者一个自定义的函数被使用,具体看原生版本的objective;
- booster:string 指定要使用的booster,可选项为:gbtree,gblinear 或 dart;
- n_jobs:int 在运行XGBoost时并行的线程数量。
- gamma:float 在树的叶节点上进行进一步分区所需的最小损失的减少值,即加入新节点进入的复杂度的代价;
- min_child_weight : int 在子节点中实例权重的最小的和;
- max_delta_step : int 我们允许的每棵树的权重估计最大的delta步骤;
- subsample :float 训练样本的子采样率;
- colsample_bytree :float 构造每个树时列的子采样率。
- colsample_bylevel :float 在每一层中的每次切分节点时的列采样率;
- reg_alpha :float 相当于原生版本的alpha,表示L1正则化项的权重系数;
- reg_lambda: float 相当于原生版本的lambda,表示L2正则化项的权重系数;
- scale_pos_weight:float 用来平衡正负权重;
- base_score: 所有实例的初始预测分数,全局偏差;
- random_state:int 随机种子;
- missing:float,optional 需要作为缺失值存在的数据中的值。 如果为None,则默认为np.nan。
XGBoost的sklearn的接口版本用法与sklearn中的模型的用法相同,这里简单的进行使用
-
X_train,X_test,y_train,y_test = train_test_split(df_train,target,test_size = 0.3,random_state = 1)
-
model = xgb.XGBClassifier(max_depth=3, n_estimators=200, learn_rate=0.01)
-
model.fit(X_train, y_train)
-
test_score = model.score(X_test, y_test)
-
print('test_score: {0}'.format(test_score))
下面是XGBoost的sklearn接口版本对数据进行预测的结果:
四. 使用其他模型于XGBoost进行对比
-
# 应用模型进行预测
-
model_lr = LogisticRegression()
-
model_rf = RandomForestClassifier(n_estimators=200)
-
model_xgb = xgb.XGBClassifier(max_depth=5, n_estimators=200, learn_rate=0.01)
-
models = [model_lr, model_rf, model_xgb]
-
model_name = ['LogisticRegression', '随机森林', 'XGBoost']
-
cv = ShuffleSplit(len(df_train), n_iter=3, test_size=0.3, random_state=1)
-
for i in range(3):
-
print(model_name[i] + ":")
-
model = models[i]
-
for train, test in cv:
-
model.fit(df_train[train], target[train])
-
train_score = model.score(df_train[train], target[train])
-
test_score = model.score(df_train[test], target[test])
-
print('train score: {0:.5f} \t test score: {0:.5f}'.format(train_score, test_score))
各个模型的运行结果如下:
从上面的结果可以看出,XGBoost的预测结果略好于LogisticRegression和随机森林分类,但是这都是可以继续调参的,调出好的参数会有更好的预测结果。
五. 总结
本文首先对Titanic数据集进行了简单的特征处理,然后介绍了XGBoost模型的原生版本和sklearn接口版本的一些重要参数,接着对数据集使用XGBoost模型,最后用LogisticRegression和随进森林算法与XGBoost进行了比较。到这里,XGBoost的简单实战已经介绍完毕,欢迎交流。