XGBoost:二分类问题

二分类问题

本文介绍XGBoost的命令行使用方法。Python和R的使用方法见https://github.com/dmlc/xgboost/blob/master/doc/README.md 。
下面将介绍如何利用XGBoost解决二分类问题。以下使用的数据集见mushroom dataset

简介

产生输入数据

XGBoost的输入数据格式和LibSVM一样。下面是XGBoost使用的输入数据格式:

1 101:1.2 102:0.03
0 1:2.1 10001:300 10002:400 
...

每行表示一个样本,第一列的数字表示类别标签,表示样本所属于的类别,‘101’和‘102’表示特征索引,’1.2‘和‘0.03’是特征所对应的值。在二分类中‘1’表示正类,‘0’表示负类。同时类别标签支持概率标签,取值服务i为[0,1],表示样本属于某个类别的可能性。

第一步需要将数据集转化成libSVM形式,执行如下脚本

python mapfeat.py
python mknfold.py agaricus.txt 1

mapfeat.py和mknfold.py分别如下

#!/usr/bin/python
def loadfmap( fname ):
    fmap = {}
    nmap = {}
    for l in open( fname ):
        arr = l.split()
        if arr[0].find('.') != -1:
            idx = int( arr[0].strip('.') )
            assert idx not in fmap
            fmap[ idx ] = {}
            ftype = arr[1].strip(':')
            content = arr[2]
        else:
            content = arr[0]
        for it in content.split(','):
            if it.strip() == '':
                continue
            k , v = it.split('=')
            fmap[ idx ][ v ] = len(nmap)
            nmap[ len(nmap) ] = ftype+'='+k
    return fmap, nmap

def write_nmap( fo, nmap ):
    for i in range( len(nmap) ):
        fo.write('%d\t%s\ti\n' % (i, nmap[i]) )
# start here
fmap, nmap = loadfmap( 'agaricus-lepiota.fmap' )
fo = open( 'featmap.txt', 'w' )
write_nmap( fo, nmap )
fo.close()
fo = open( 'agaricus.txt', 'w' )
for l in open( 'agaricus-lepiota.data' ):
    arr = l.split(',')
    if arr[0] == 'p':
        fo.write('1')
    else:
        assert arr[0] == 'e'
        fo.write('0')
    for i in range( 1,len(arr) ):
        fo.write( ' %d:1' % fmap[i][arr[i].strip()] )
    fo.write('\n')
fo.close()
#!/usr/bin/python
import sys
import random
if len(sys.argv) < 2:
    print ('Usage:<filename> <k> [nfold = 5]')
    exit(0)
random.seed( 10 )
k = int( sys.argv[2] )
if len(sys.argv) > 3:
    nfold = int( sys.argv[3] )
else:
    nfold = 5
fi = open( sys.argv[1], 'r' )
ftr = open( sys.argv[1]+'.train', 'w' )
fte = open( sys.argv[1]+'.test', 'w' )
for l in fi:
    if random.randint( 1 , nfold ) == k:
        fte.write( l )
    else:
        ftr.write( l )
fi.close()
ftr.close()
fte.close()

运行完以上两个Python脚本将会产生训练数据集:’agaricus.txt.train’ 和测试数据集: ‘agaricus.txt.test’

训练

执行如下命令行完成模型训练:

xgboost mushroom.conf

mushroom.conf文件用于配置训练模型和测试模型时需要的信息。每行的配置信息格式为:[attribute]=[value]:

# General Parameters, see comment for each definition
# can be gbtree or gblinear
booster = gbtree 
# choose logistic regression loss function for binary classification
objective = binary:logistic

# Tree Booster Parameters
# step size shrinkage
eta = 1.0 
# minimum loss reduction required to make a further partition
gamma = 1.0 
# minimum sum of instance weight(hessian) needed in a child
min_child_weight = 1 
# maximum depth of a tree
max_depth = 3 

# Task Parameters
# the number of round to do boosting
num_round = 2
# 0 means do not save any model except the final round model
save_period = 0 
# The path of training data
data = "agaricus.txt.train" 
# The path of validation data, used to monitor training process, here [test] sets name of the validation set
eval[test] = "agaricus.txt.test" 
# The path of test data 
test:data = "agaricus.txt.test"      

这里的booster采用gbtree,目标函数采用logistic regression。这意味着可以采用经典的梯度提升回归树进行计算(GBRT)。这种方法能够很好的处理二分类问题

以上的配置文件中给出了最常用的配置参数。如果想了解更多的参数,详见https://github.com/dmlc/xgboost/blob/master/doc/parameter.md。如果不想在配置文件中配置算法参数,可以通过命令行配置,如下

xgboost mushroom.conf max_depth=6

这表示max_depth参数将被设置为6而不是配置文件中的3。当使用命令行参数时确保max_depth=6为一个参数,即参数之间不要含有间隔。如果既使用配置又使用命令行参数,则命令行参数会覆盖配置文件参数,即优先使用命令行参数

在以上的例子中使用tree booster计算梯度提升。如果想使用linear booster进行回归计算,可以修改booster参数为gblinear,配置文件中的其它参数都不需要修改,配置文件信息如下

# General Parameters
# choose the linear booster
booster = gblinear
...

# Change Tree Booster Parameters into Linear Booster Parameters
# L2 regularization term on weights, default 0
lambda = 0.01
# L1 regularization term on weights, default 0
f ```agaricus.txt.test.buffer``` exists, and automatically loads from binary buffer if possible, this can speedup training process when you do training many times. You can disable it by setting ```use_buffer=0```.
  - Buffer file can also be used as standalone input, i.e if buffer file exists, but original agaricus.txt.test was removed, xgboost will still run
* Deviation from LibSVM input format: xgboost is compatible with LibSVM format, with the following minor differences:
  - xgboost allows feature index starts from 0
  - for binary classification, the label is 1 for positive, 0 for negative, instead of +1,-1
  - the feature indices in each line *do not* need to be sorted
alpha = 0.01 
# L2 regularization term on bias, default 0
lambda_bias = 0.01 

# Regression Parameters
...

预测

在训练好模型之后,可以对测试数据进行预测,执行如下脚本

xgboost mushroom.conf task=pred model_in=0003.model

对于二分类问题预测的输出结果为[0,1]之间的概率值,表示样本属于正类的概率。

模型展示

目前这还是个基本功能,只支持树模型的展示。XGBoost可以用文本的显示展示树模型,执行以下脚本

../../xgboost mushroom.conf task=dump model_in=0003.model name_dump=dump.raw.txt 
../../xgboost mushroom.conf task=dump model_in=0003.model fmap=featmap.txt name_dump=dump.nice.txt

0003.model将会输出到dump.raw.txt和dump.nice.txt中。dump.nice.txt中的结果更容易理解,因为其中使用了特征映射文件featmap.txt

featmap.txt的格式为 featmap.txt: <featureid> <featurename> <q or i or int>\n:

  • Feature id从0开始直到特征的个数为止,从小到大排列。
  • i表示是二分类特征
  • q表示数值变量,如年龄,时间等。q可以缺省
  • int表示特征为整数(when int is hinted, the decision boundary will be integer)

计算过程监测

当运行程序时,会输出如下运行信息

tree train end, 1 roots, 12 extra nodes, 0 pruned nodes ,max_depth=3
[0]  test-error:0.016139
boosting round 1, 0 sec elapsed

tree train end, 1 roots, 10 extra nodes, 0 pruned nodes ,max_depth=3
[1]  test-error:0.000000

计算过程中模型评价信息输出到错误输出流stderr中,如果希望记录计算过程中的模型评价信息,可以执行如下脚本

xgboost mushroom.conf 2>log.txt

在log.txt文件中记录如下信息

[0]     test-error:0.016139
[1]     test-error:0.000000

也可以同时监测训练过程和测试过程中的统计信息,可以通过如下方式进行配置

eval[test] = "agaricus.txt.test" 
eval[trainname] = "agaricus.txt.train" 

运行以上的脚本后得到的信息如下

[0]     test-error:0.016139     trainname-error:0.014433
[1]     test-error:0.000000     trainname-error:0.001228

运行规则是[name-printed-in-log] = filename, filename文件将会被加入检测进程并在每个迭代过程中对模型进行评价。

XGBoost同时支持多种统计量的监测,假设希望监测在训练过程每次预测的平均log-likelihood,只需要在配置文件中添加配置信息 eval_metric=logloss。再次运行log文件中将会有如下信息

[0]     test-error:0.016139     test-negllik:0.029795   trainname-error:0.014433        trainname-negllik:0.027023
[1]     test-error:0.000000     test-negllik:0.000000   trainname-error:0.001228        trainname-negllik:0.002457

保存运行过程中的模型

如果现在运行过程中每两步保存一个模型,则可以设置参数set save_period=2.。在当前文件夹将会看到模型0002.model。如果想修改模型输出的路径,则可以通过参数dir=foldername修改。缺省情况下XGBoost将会保持上次迭代的结果模型。

从已有模型继续计算

如果想从已有的模型继续训练,例如从0002.model继续计算,则用如下命令行

xgboost mushroom.conf model_in=0002.model num_round=2 model_out=continue.model

XGBoost将加载0002.model并进行两次迭代计算,并将输出明显保存在continue.model。需要注意的是 在mushroom.conf中定义的训练数据和评价数据信息不能发生变化。

使用多线程

当计算大数据集时,可能需要并行计算。如果编译器支持OpenMP,XGBoost原生是支持多线程的,通过一下参数nthread=10设置线程数为10。

其它需要注意的点

  • agaricus.txt.test.bufferagaricus.txt.train.buffer是什么文件
    • 默认情况下XGBoost将会产生二进制的缓存文件,文件后缀为 buffer。当下次再次运行XGBoost时将加载缓存文件而不是原始的文件。

你可能感兴趣的:(xgboost)