C API 教程

在本教程中,我们将安装 XGBoost 库,并配置我们的 C/C++ 应用程序的 CMakeLists.txt 文件,以便将 XGBoost 库与我们的应用程序链接。之后,我们将看到一些使用 C API 的有用提示,并提供代码片段作为示例,以使用 C API 中可用的各种函数来执行加载、训练模型和在测试数据集上进行预测等基本任务。有关 API 参考,请访问 XGBoost C 包

要求

安装 CMake - 请按照 CMake 安装文档 的说明进行操作。安装 Conda - 请按照 Conda 安装文档 的说明进行操作。

在 conda 环境中安装 XGBoost

在你的终端上运行以下命令。下面的命令将在你克隆的仓库中的XGBoost文件夹内安装XGBoost。

# clone the XGBoost repository & its submodules
git clone --recursive https://github.com/dmlc/xgboost
cd xgboost
mkdir build
cd build
# Activate the Conda environment, into which we'll install XGBoost
conda activate [env_name]
# Build the compiled version of XGBoost inside the build folder
cmake .. -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
# install XGBoost in your conda environment (usually under [your home directory]/miniconda3)
make install

需要记住的有用提示

以下是使用C API时的一些有用提示:

  1. 错误处理:始终检查C API函数的返回值。

  1. 在C应用程序中:使用以下宏来保护所有对XGBoost的C API函数的调用。该宏会打印所有发生的错误/异常:

1#define safe_xgboost(call) {  \
2  int err = (call); \
3  if (err != 0) { \
4    fprintf(stderr, "%s:%d: error in %s: %s\n", __FILE__, __LINE__, #call, XGBGetLastError());  \
5    exit(1); \
6  } \
7}

在你的应用程序中,将所有 C API 函数调用用以下宏包裹:

DMatrixHandle train;
safe_xgboost(XGDMatrixCreateFromFile("/path/to/training/dataset/", silent, &train));
  1. 在C++应用程序中:修改宏 safe_xgboost 以在发生错误时抛出异常。

1#define safe_xgboost(call) {  \
2  int err = (call); \
3  if (err != 0) { \
4    throw std::runtime_error(std::string(__FILE__) + ":" + std::to_string(__LINE__) + \
5                        ": error in " + #call + ":" + XGBGetLastError());  \
6  } \
7}
  1. 断言技术:它在 C/C++ 中都有效。如果表达式计算结果为 0(假),则表达式、源代码文件名和行号将被发送到标准错误,然后调用 abort() 函数。它可用于测试代码中你做出的假设。

DMatrixHandle dmat;
assert( XGDMatrixCreateFromFile("training_data.libsvm", 0, &dmat) == 0);
  1. 始终记得通过 BoosterHandle 和 DMatrixHandle 适当地释放分配的空间:

 1#include <assert.h>
 2#include <stdio.h>
 3#include <stdlib.h>
 4#include <xgboost/c_api.h>
 5
 6int main(int argc, char** argv) {
 7  int silent = 0;
 8
 9  BoosterHandle booster;
10
11  // do something with booster
12
13  //free the memory
14  XGBoosterFree(booster);
15
16  DMatrixHandle DMatrixHandle_param;
17
18  // do something with DMatrixHandle_param
19
20  // free the memory
21  XGDMatrixFree(DMatrixHandle_param);
22
23  return 0;
24}
  1. 对于树模型,在训练和评分/预测过程中使用一致的数据格式非常重要,否则会导致错误的输出。例如,如果我们的训练数据是 dense matrix 格式,那么您的预测数据集也应该是 dense matrix 格式;如果在 libsvm 格式中进行训练,那么预测的数据集也应该是 libsvm 格式。

  2. 在booster handle对象中设置参数值时,始终使用字符串。参数值可以是任何数据类型(例如int、char、float、double等),但它们应始终编码为字符串。

BoosterHandle booster;
XGBoosterSetParam(booster, "parameter_name", "0.1");

使用C API函数的示例代码

  1. 如果数据集以文件形式存在,可以使用 XGDMatrixCreateFromFile() 将其加载到 DMatrix 对象中。

DMatrixHandle data; // handle to DMatrix
// Load the data from file & store it in data variable of DMatrixHandle datatype
safe_xgboost(XGDMatrixCreateFromFile("/path/to/file/filename", silent, &data));
  1. 你也可以使用 XGDMatrixCreateFromMat() 从二维矩阵创建一个 DMatrix 对象。

 1// 1D matrix
 2const int data1[] = { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
 3
 4// 2D matrix
 5const int ROWS = 5, COLS = 3;
 6const int data2[ROWS][COLS] = { {1, 2, 3}, {2, 4, 6}, {3, -1, 9}, {4, 8, -1}, {2, 5, 1}, {0, 1, 5} };
 7DMatrixHandle dmatrix1, dmatrix2;
 8// Pass the matrix, no of rows & columns contained in the matrix variable
 9// here '0' represents the missing value in the matrix dataset
10// dmatrix variable will contain the created DMatrix using it
11safe_xgboost(XGDMatrixCreateFromMat(data1, 1, 50, 0, &dmatrix));
12// here -1 represents the missing value in the matrix dataset
13safe_xgboost(XGDMatrixCreateFromMat(data2, ROWS, COLS, -1, &dmatrix2));
  1. 使用 XGBoosterCreate() 创建一个用于训练和测试数据集的 Booster 对象

1BoosterHandle booster;
2const int eval_dmats_size;
3// We assume that training and test data have been loaded into 'train' and 'test'
4DMatrixHandle eval_dmats[eval_dmats_size] = {train, test};
5safe_xgboost(XGBoosterCreate(eval_dmats, eval_dmats_size, &booster));
  1. 对于每个 DMatrix 对象,使用 XGDMatrixSetFloatInfo() 设置标签。之后,您可以使用 XGDMatrixGetFloatInfo() 访问标签。

 1const int ROWS=5, COLS=3;
 2const int data[ROWS][COLS] = { {1, 2, 3}, {2, 4, 6}, {3, -1, 9}, {4, 8, -1}, {2, 5, 1}, {0, 1, 5} };
 3DMatrixHandle dmatrix;
 4
 5safe_xgboost(XGDMatrixCreateFromMat(data, ROWS, COLS, -1, &dmatrix));
 6
 7// variable to store labels for the dataset created from above matrix
 8float labels[ROWS];
 9
10for (int i = 0; i < ROWS; i++) {
11  labels[i] = i;
12}
13
14// Loading the labels
15safe_xgboost(XGDMatrixSetFloatInfo(dmatrix, "label", labels, ROWS));
16
17// reading the labels and store the length of the result
18bst_ulong result_len;
19
20// labels result
21const float *result;
22
23safe_xgboost(XGDMatrixGetFloatInfo(dmatrix, "label", &result_len, &result));
24
25for(unsigned int i = 0; i < result_len; i++) {
26  printf("label[%i] = %f\n", i, result[i]);
27}
  1. 根据需求使用 XGBoosterSetParam() 设置 Booster 对象的参数。查看完整的参数列表 这里

1BoosterHandle booster;
2safe_xgboost(XGBoosterSetParam(booster, "booster", "gblinear"));
3// default max_depth =6
4safe_xgboost(XGBoosterSetParam(booster, "max_depth", "3"));
5// default eta  = 0.3
6safe_xgboost(XGBoosterSetParam(booster, "eta", "0.1"));
  1. 分别使用 XGBoosterUpdateOneIter()XGBoosterEvalOneIter() 来训练和评估模型。

 1int num_of_iterations = 20;
 2const char* eval_names[eval_dmats_size] = {"train", "test"};
 3const char* eval_result = NULL;
 4
 5for (int i = 0; i < num_of_iterations; ++i) {
 6  // Update the model performance for each iteration
 7  safe_xgboost(XGBoosterUpdateOneIter(booster, i, train));
 8
 9  // Give the statistics for the learner for training & testing dataset in terms of error after each iteration
10  safe_xgboost(XGBoosterEvalOneIter(booster, i, eval_dmats, eval_names, eval_dmats_size, &eval_result));
11  printf("%s\n", eval_result);
12}

备注

对于自定义损失函数,请使用 XGBoosterBoostOneIter() 并手动指定梯度和二阶梯度。

  1. 使用 XGBoosterPredictFromDMatrix() 预测测试集的结果

 1char const config[] =
 2    "{\"training\": false, \"type\": 0, "
 3    "\"iteration_begin\": 0, \"iteration_end\": 0, \"strict_shape\": false}";
 4/* Shape of output prediction */
 5uint64_t const* out_shape;
 6/* Dimension of output prediction */
 7uint64_t out_dim;
 8/* Pointer to a thread local contiguous array, assigned in prediction function. */
 9float const* out_result = NULL;
10safe_xgboost(
11    XGBoosterPredictFromDMatrix(booster, dmatrix, config, &out_shape, &out_dim, &out_result));
12
13for (unsigned int i = 0; i < output_length; i++){
14  printf("prediction[%i] = %f \n", i, output_result[i]);
15}
  1. 使用 XGBoosterGetNumFeature() 获取数据集中特征的数量。

1bst_ulong num_of_features = 0;
2
3// Assuming booster variable of type BoosterHandle is already declared
4// and dataset is loaded and trained on booster
5// storing the results in num_of_features variable
6safe_xgboost(XGBoosterGetNumFeature(booster, &num_of_features));
7
8// Printing number of features by type conversion of num_of_features variable from bst_ulong to unsigned long
9printf("num_feature: %lu\n", (unsigned long)(num_of_features));
  1. 使用 XGBoosterSaveModel() 保存模型

BoosterHandle booster;
const char *model_path = "/path/of/model.json";
safe_xgboost(XGBoosterSaveModel(booster, model_path));
  1. 使用 XGBoosterLoadModel() 加载模型

 1BoosterHandle booster;
 2const char *model_path = "/path/of/model.json";
 3
 4// create booster handle first
 5safe_xgboost(XGBoosterCreate(NULL, 0, &booster));
 6
 7// set the model parameters here
 8
 9// load model
10safe_xgboost(XGBoosterLoadModel(booster, model_path));
11
12// predict the model here
  1. 使用 XGDMatrixFree()XGBoosterFree() 释放代码中使用的所有内部结构。这一步对于防止内存泄漏非常重要。

safe_xgboost(XGDMatrixFree(dmatrix));
safe_xgboost(XGBoosterFree(booster));