[机器学习]xgboost二分类实战

6,168 阅读5分钟

0/前言

xgboost有两大类接口:
    <1>XGBoost原生接口,及陈天奇开源的xgboost项目,import xgboost as xgb
    <2>scikit-learn api接口,及python的sklearn库
    
并且xgboost能够实现 分类 和 回归 两种任务。
并且对于分类任务,xgboost可以实现 二分类 和 多分类

“reg:linear” —— 线性回归。 
“reg:logistic”—— 逻辑回归。 

“binary:logistic”—— 二分类的逻辑回归问题,输出为概率。 
“binary:logitraw”—— 二分类的逻辑回归问题,输出的结果为wTx。
“count:poisson”—— 计数问题的poisson回归,输出结果为poisson分布。在poisson回归中,max_delta_step的缺省值为0.7。(used to safeguard optimization) 


“multi:softmax” –让XGBoost采用softmax目标函数处理多分类问题,
                 同时需要设置参数num_class(类别个数) 
                 
“multi:softprob” –和softmax一样,但是输出的是ndata * nclass结构的向量,
                  可以将该向量reshape(映射)成ndata行nclass列的矩阵。
                  每一行数据表示被预测样本所属于每个类别的概率。 

“rank:pairwise” –set XGBoost to do ranking task by minimizing the pairwise loss

1/demo1(原生接口)

二分类,特征是连续型的数据
label01
# demo2
# 使用鸢尾花的数据来说明二分类的问题

import xgboost as xgb
from sklearn import metrics
from sklearn.cross_validation import train_test_split
from sklearn import datasets
iris = datasets.load_iris()

# 特征数据,100行,一共有4个特征
data = iris.data[:100] 
print(data)
print(data.shape) 

# 标签数据
label = iris.target[:100]
print(label)

# 划分训练数据集,测试数据集
train_x, test_x, train_y, test_y = train_test_split(data, label, random_state=0)

# 调用xgb中的DMatrix()函数,把数据格式转换为xgb需要的模式
dtrain = xgb.DMatrix(train_x, label=train_y)
dtest = xgb.DMatrix(test_x)

# 参数准备
params={'booster':'gbtree',  # 弱学习器的类型,默认就是gbtree,及cart决策树
        'objective': 'binary:logistic',   # 目标函数,二分类:逻辑回归,输出的是概率
        'eval_metric': 'auc',
        'max_depth':4,  # 最大深度
        'lambda':10,
        'subsample':0.75,
        'colsample_bytree':0.75,
        'min_child_weight':2,
        'eta': 0.025,  # 步长
        'seed':0,
        'nthread':8,
        'silent':1}


watchlist = [(dtrain,'train')]

# 开始训练模型
# params是传入模型的各个参数,以字典的形式传入
model = xgb.train(params,
                  dtrain,
                  num_boost_round= 100,  # 迭代的次数,及弱学习器的个数
                  evals= watchlist)

# 对测试集合预测
ypred = model.predict( dtest )

# 设置阈值, 输出一些评价指标,选择概率大于0.5的为1,其他为0类
y_pred = (ypred >= 0.5)*1


# 输出各种指标,评价模型的优劣
# 比如auc曲线,准确率,精确率,召回率等
print('AUC: %.4f' % metrics.roc_auc_score(test_y, ypred))
print('ACC: %.4f' % metrics.accuracy_score(test_y, y_pred))        # 准确率
print('Precesion: %.4f' % metrics.precision_score(test_y, y_pred)) # 精确率
print('Recall: %.4f' % metrics.recall_score(test_y, y_pred))       # 召回率
print('F1-score: %.4f' % metrics.f1_score(test_y, y_pred))         # 二者的结合
print(metrics.confusion_matrix(test_y, y_pred))  # 混淆矩阵

2/demo2(sklearn的接口)

# 目的是判断病人是否会在 5 年内患糖尿病,给出的数据为csv文件。
# 一共9列数据,前 8 列是特征,最后一列是标签label,为 0 或 1。

from xgboost.sklearn import XGBClassifier
from numpy import loadtxt

from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score  

from xgboost import plot_importance
from matplotlib import pyplot

# 加载数据,分出特征和标签
data = loadtxt('dataset_001.csv', delimiter=",") 
X = data[:,0:8]  # 前8列是特征
Y = data[:,8]    # 最后一列是标签

# 把数据集分为训练集和测试集
# 训练集用来训练模型,测试集用来测试模型的效果
X_train, X_test, y_train, y_test = train_test_split(X, Y,
                                                    test_size=0.33, 
                                                    random_state=90)

# 直接使用xgboost开源项目中封装好的分类器和回归器,可以直接使用XGBClassifier建立模型
# 不可视化数据集loss
#model = XGBClassifier()
#model.fit(X_train, y_train)

# 可视化测试集的loss
# 改为True就能可视化loss
xgboost_model = XGBClassifier()
eval_set = [(X_test, y_test)]
xgboost_model.fit(X_train, 
                  y_train, 
                  early_stopping_rounds=10, 
                  eval_metric="logloss",  # 损失函数的类型,分类一般都是用对数作为损失函数
                  eval_set=eval_set,
                  verbose=False)

# xgboost的结果是每一个样本属于第一类的概率,要使用round将其转换为0 1值
y_pred = xgboost_model.predict( X_test )
predictions = [round(i) for i in y_pred] 

# 计算准确率,也就是把准确率作为衡量模型好坏的指标
# 当正负类样本分布不均匀的时候(比如之前做的判断一架飞机上的恐怖分子),用准确率是不合适的
accuracy = accuracy_score(y_test, predictions)
print("Accuracy: %.2f%%" % (accuracy * 100.0))
##Accuracy: 77.56%


xgboost_model.fit(X, Y)
plot_importance( xgboost_model )
pyplot.show()

image.png

网格搜索

如何确定最佳的参数组合呢
下面是三个超参数的一般实践最佳值,可以先将它们设定为这个范围,然后画出 learning curves,再调解参数找到最佳模型:

learning_rate = 0.1 或更小,越小就需要多加入弱学习器; 
tree_depth = 28;
subsample = 训练集的 30%~80%;

接下来我们用 GridSearchCV 来进行调参会更方便一些: 可以调的超参数组合有:
树的个数和大小 (n_estimators and max_depth).
学习率和树的个数 (learning_rate and n_estimators).
行列的 subsampling rates (subsample, colsample_bytree and colsample_bylevel).

# 下面以学习率 learning rate 为例
# 通过遍历的方式,在不同的学习率的情况下,看哪个学习率的情况下,模型最优
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import StratifiedKFold

# 设定要调节的 learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3] 

# 和原代码相比就是在 model 后面加上 grid search 这几行:
model = XGBClassifier()

learning_rate = [0.0001, 0.001, 0.01, 0.1, 0.2, 0.3]
param_grid = dict(learning_rate=learning_rate)
kfold = StratifiedKFold(n_splits=10, shuffle=True, random_state=7)

grid_search = GridSearchCV(model, 
                           param_grid, 
                           scoring="neg_log_loss", 
                           n_jobs=-1, cv=kfold)
grid_result = grid_search.fit(X, Y)

# 输出最佳学习率和其对应的分数
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))
#Best: -0.483013 using {'learning_rate': 0.1}

# 打印出每一个学习率对应的分数
means = grid_result.cv_results_['mean_test_score']
stds = grid_result.cv_results_['std_test_score']
params = grid_result.cv_results_['params']
for mean, stdev, param in zip(means, stds, params):
    print("%f (%f) with: %r" % (mean, stdev, param))

# 结果如下:
-0.689650 (0.000242) with: {‘learning_rate’: 0.0001}
-0.661274 (0.001954) with: {‘learning_rate’: 0.001}
-0.530747 (0.022961) with: {‘learning_rate’: 0.01}
-0.483013 (0.060755) with: {‘learning_rate’: 0.1}
-0.515440 (0.068974) with: {‘learning_rate’: 0.2}
-0.557315 (0.081738) with: {‘learning_rate’: 0.3}