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
# 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 -B build -S . -DCMAKE_INSTALL_PREFIX=$CONDA_PREFIX
# install XGBoost in your conda environment (usually under [your home directory]/miniconda3)
cmake --build build --target 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 (false),则将表达式、源代码文件名和行号发送到标准错误,然后调用 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. 对于树模型,在训练和评分/预测期间使用一致的数据格式非常重要,否则会导致错误的输出。例如,如果我们的训练数据采用 密集矩阵 格式,则预测数据集也应该采用 密集矩阵 格式;如果训练采用 libsvm 格式,则预测数据集也应该采用 libsvm 格式。

  2. 在为助推器句柄对象的参数设置值时,始终使用字符串。参数值可以是任何数据类型(例如 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 = 6, 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));