XGBoost模型训练及可视化

本文介绍xgboost模型的训练以及模型的导出和可视化。

本文在显示树图像时遇到了下面问题:

dot: graph is too large for cairo-renderer bitmaps. Scaling by 0.498668 to fit

然后一通操作解决了这个问题。

一、数据格式

xgboost支持多种数据输入格式,DMatrix()的文档显示xgboost支持

string/numpy array/scipy.sparse/pd.DataFrame/DataTable等几种方式的输入,其实python二维数组也可以作为输入

我曾经尝试过用python list或python list转为numpy array的方式生成训练数据,但这两种方式在数据量级很大时并不适用,其转换过程会导致内存暴涨

后来采取libSVM格式的数据格式之后,单机可训练样本数目可以翻几倍,并且加载速度很快。搭配spark生成libsvm格式数据,整个数据处理、模型训练的过程会变得很流畅。

二、模型训练

# loading dataset.
dtrain = xgb.DMatrix('train.lib', missing=-999.0)
print(dtrain.num_row(), dtrain.num_col())
# output: (4206926L, 187L)
dtest = xgb.DMatrix('test.lib', missing=-999.0)
print(dtest.num_row(), dtest.num_col())
# output: (421846L, 187L)

# training and save model.
evallist = [(dtest, 'eval'), (dtrain, 'train')]
bst = xgb.train(params, dtrain, 100, evallist, early_stopping_rounds=10)
bst.save_model('xgb.model')

# evaluate.
y_test = dtest.get_label()
y_pred = bst.predict(dtest)
auc = roc_auc_score(y_test, y_pred)
print(auc)

以上,完成了xgboost模型的训练、保存和评估。

为表尊重,将xgboost的参数单独拎出来:

params = {'verbose': False,
          'booster': 'gbtree',
          'n_estimators': 200,
          'max_depth': 9,  # max_depth [缺省值=6]
          'eta': 0.08,  # learning_rate
          'silent': 1,  # 为0打印运行信息;设置为1静默模式,不打印
          'nthread': 20,  # 运行时占用cpu数
          'gamma': 0.0,  # min_split_loss](分裂最小loss)参数的值越大,算法越保守
          'min_child_weight': 5,  # 决定最小叶子节点样本权重和,缺省值=1,避免过拟合. 值过高,会导致欠拟合
          'max_delta_step': 0,
          'subsample': 1,  #参数控制对于每棵树,随机采样的比例 减小避免过拟合,  典型值:0.5-1,0.5代表平均采样,防止过拟合.
          'colsample_bytree': 0.8,  #树级列采样
          'colsample_bylevel': 1,  #层级列采样
          'lambda': 0.1,  # L2正则化项, 减少过拟合
          'alpha': 0.1,  # 权重的L1正则化项
          'objective': 'binary:logistic',
          'scale_pos_weight': 1,  # 通常可以将其设置为负样本的数目与正样本数目的比值
          'eval_metric': 'auc',
          'base_score': 0.5,
          }

Xgboost 参数很多,通过调参数大致能够将auc提高一个百分点。

常见的调参方法有Grid Search,佛系循环调参,随机调参等。

要使用grid search就要用XGBClassifier评估器,其是对xgboost原始API的封装,能够和sklearn中的评估器一样使用fit()函数进行训练呢。

三、模型可视化

import xgboost as xgb
from xgboost import plot_tree
import matplotlib.pyplot as plt
# load model.
bst = xgb.Booster()
bst.load_model('xgb.model')
# plot
plot_tree(bstfmap='', num_trees=0, rankdir='UT', ax=None)
plt.show()

以上是显示树结构最简单的实现。

但是我在运行以上代码时遇到dot: graph is too large for cairo-renderer bitmaps的问题,是由于我训练的树模型深度有9层,图像过大而无法转化为png格式。

查看plot_tree 源码可以发现,该函数调用to_graphviz函数生成有向图Digraph对象,然后将其format为png格式显示出来。

def plot_tree(booster, ...):
    g = to_graphviz(booster, )
    s = BytesIO()
    s.write(g.pipe(format='png'))
    s.seek(0)
    img = image.imread(s)

解决方法是,直接调用to_graphviz生成有向图对象,并将其保存为文件,之后通过命令将其转换为svg格式。

graph = xgb.to_graphviz(bst, num_trees=0, **{'size': str(10)})
graph.render(filename='xgb.dot')

生成svg命令:

dot -Tsvg xgb.dot -o xgb.svg

效果图如下:

发布于 2019-07-25

文章被以下专栏收录