上手机器学习系列-第5篇(上)-XGBoost

本文介绍了XGBoost的优势及在Python中的使用,通过对官方DEMO的解剖,详细讲解了如何读取和理解数据集,特别是DMatrix数据结构与目标变量的关系。此外,还探讨了XGBoost与sklearn接口的区别,并提供了sklearn版本的使用示例。
摘要由CSDN通过智能技术生成

引言

在第4篇中我们简要介绍了GBDT的使用方法,本篇来聊一种进阶的GBDT-XGBoost,这是一款极其优秀的算法解决方案,项目官方网站:https://xgboost.readthedocs.io/en/latest/。

XGBoost本身最大的优势就在于它在工程上做了大量的工作,使得该算法可以广泛应用到不同的生态中(python、spark、C++等)。

Python + XGBoost

对官方DEMO的解剖

以下是XGBoost官网上给出来的一个DEMO代码:

import xgboost as xgb
# read in data
dtrain = xgb.DMatrix('demo/data/agaricus.txt.train')
dtest = xgb.DMatrix('demo/data/agaricus.txt.test')
# specify parameters via map
param = {
   'max_depth':2, 'eta':1, 'objective':'binary:logistic' }
num_round = 2
bst = xgb.train(param, dtrain, num_round)
# make prediction
preds = bst.predict(dtest)

这里的数据集显然是需要从xgboost软件附带的文件去下载,可以按照官网上说的那样把整个xgboost都git clone到本地(但这个有时候会因为网速的原因,不一定能顺利下载到),也可以到github上(https://github.com/dmlc/xgboost/tree/master/demo/data)去找到对应的目录下的数据,直接复制粘贴到本地文件中,反正怎么高效怎么来。

首先关注一下数据集的格式:
在这里插入图片描述
显然,这是已经预处理好的很干净的数据。第一列是目标变量(这一点跟很多数据集不同,一般情况下目标变量是在最后一列,不过没关系,核心还是要看读取数据时是怎么操作的,只要能正确解析就行,一会我们再去看它的代码实现细节)。其次,我们看到这里特征变量是用k:v这样的格式来表达,其实这是非常常用的一种格式,称为dense向量,与之相对的称为sparse向量,我们可以通过下图的示意来理解:
在这里插入图片描述
那上面这些120多个特征变量,分别是啥呢?我们可通过github上xgboost/demo/data/featmap.txt 这个文件来了解:
在这里插入图片描述
从这个文件的内容,我们可以推测出来它是对特征进行了one-hot-encoding。很多机器学习算法都不支持具有枚举值的变量,所以需要做这样的一个特征工程处理,原理如下图所示:
在这里插入图片描述
这样我们就对数据有了初步了解。接着去看代码操作。

在上面的代码中是用.Dmatrix读入数据,我们自己用 type(dtrain) 查看一下,发现返回的是xgboost.core.DMatrix这样一种数据类型,看来是xgboost自己定义的数据格式了。那么问题来了,
dtrain = xgb.DMatrix(‘demo/data/agaricus.txt.train’)
这一步操作之后,是把特征变量与目标变量保持到了一个数据集中,这与我们以往使用的sklearn接口是不同的,还记得吗,我们通常是把数据集拆成X_train, y_train 这样,有特征集与目标变量之分,之后再调用.fit(X_train, y_train)这样的接口来拟合数据。而这里我们看到是这样用的:
bst = xgb.train(param, dtrain, num_round)
train 我们可以认为等同于sklearn里面算法包接口的fit方法,但这里只传了一个dtrain数据集,并没有拆分开哪一列是目标变量,train这个方法是怎么知道用哪一列来拟合呢?我们猜想train这个方法一定与DMatrix数据结构有约定好的格式。为了解这里究竟是怎么处理的(没错,就是要多保留一些好奇心,这样写代码才有趣),我们去翻翻github上xgboost的源代码。

找啊找,我们在文件dmlc/xgboost/blob/master/python-package/xgboost/core.py中看到了DMatrix这个类的定义:
在这里插入图片描述
可见这里其实是支持传入目标向量的,但可以默认为空,那么猜想如果传入为空,它一定默认从前面的data中去提取这个目标向量了。

--------------以下过程不感兴趣的可以跳过————————
继续往下看,发现这样一个线索:

if label is not None:
            self.set_label(label)

看来,当传入的label不为空时,通过set_label 这个方法就直接获取到了label, 那么label未传入呢?但是我们居然没有找到 if label is None 这个逻辑的处理!呃,一定是在某个地方隐式处理了,继续找线索:

  def get_label(self):
        """Get the label of the DMatrix.
        Returns
        -------
        label : array
        """
        return self.get_float_info('label')

....

    def get_float_info(self, field):
        """Get float property from the DMatrix.
        Parameters
        ----------
        field: str
            The field name of the information
        Returns
        -------
        info : array
            a numpy array of float information of the data
        """
        length = c_bst_ulong()
        ret = ctypes.POINTER(ctypes.c_float)()
        _check_call(_LIB.XGDMatrixGetFloatInfo(self.handle,
                                               c_str
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值