XGBoost C API 完全指南:从环境搭建、CMake 链接到训练与推理实战
XGBoost C API 完全指南从环境搭建、CMake 链接到训练与推理实战【免费下载链接】xgboostScalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow项目地址: https://gitcode.com/gh_mirrors/xg/xgboostXGBoost 为多种编程语言绑定Python、R、Java、Scala、C 等提供了一套稳定且被长期维护的 C API本文以 doc/c.rst 与 doc/tutorials/c_api_tutorial.rst 为主线结合仓库中的 include/xgboost/c_api.h 源码与 demo/c-api/ 示例系统讲解 C API 的构建安装、CMake 链接方式、错误处理与内存管理要点并给出从数据加载、Booster 创建、参数配置、迭代训练、评估到推理保存的完整可运行代码。读完本文你将能够在自己的 C/C 项目中独立完成 XGBoost 的接入、训练、预测与模型序列化。一、XGBoost C Package 概览XGBoost 实现了一套专为各种语言绑定设计的 C API官方明确承诺维护其稳定性以及对应的CMake/make 构建接口见 doc/c.rst。这套 API 的权威定义集中在 include/xgboost/c_api.h 中文件顶部注明了其定位C API of XGBoost, used to interface with other high-level languages第 4 行。在文档体系中C API 参考文档通过 doxygen 分组defgroup组织与 doc/c.rst 中列出的章节一一对应分组定义位置include/xgboost/c_api.h职责Library第 40 行获取版本、构建信息与全局配置等通用信息DMatrix第 123 行DMatrix 数据对象的创建、查询与操作Streaming第 311 行外部内存/流式数据迭代callback 方式Booster第 968 行Booster 模型的创建与参数设置Prediction第 1134 行基于 DMatrix 或稠密/稀疏数据的预测Serialization第 1338 行模型的保存、加载与序列化Collective第 1633 行分布式集体通信相关接口两种查阅参考的方式源码注释直接阅读 include/xgboost/c_api.h 中每个函数的注释这也是最原始、最准确的参考来源。自动生成文档在 CMake 构建时传入-DBUILD_C_DOCON生成 doxygen 文档例如cmake -B build -S . -DBUILD_C_DOCON cmake --build build --target doc # 具体 target 名称以构建配置为准此外参考文档还会通过 breathe 插件导出到 sphinx 页面即doc/c.rst本身便于在文档站点内阅读。入门导读请见 doc/tutorials/c_api_tutorial.rst完整的可编译示例位于 demo/c-api/ 目录其中包括 basic基础训练与预测、external-memory外部内存数据迭代和 inference推理三个子示例。二、环境准备与构建安装2.1 前置依赖CMake用于构建 XGBoost 库并链接到你的应用参考官方安装文档安装版本需满足cmake_minimum_required(VERSION 3.18)见下文示例。Conda用于创建和管理安装 XGBoost 的虚拟环境也可以使用系统环境但教程默认基于 Conda。2.2 克隆仓库并安装到 Conda 环境# clone the XGBoost repository its submodules git clone --recursive https://github.com/dmlc/xgboost cd xgboost # Activate the Conda environment, into which well 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要点说明--recursive用于拉取仓库的 git 子模块包括 dmlc-core 等依赖这一点非常关键缺失子模块会导致构建失败。-DCMAKE_INSTALL_PREFIX$CONDA_PREFIX指定安装前缀为当前 Conda 环境目录这样安装后即可在激活该环境时直接使用。cmake --build build --target install完成编译并安装头文件与库文件libxgboost。三、在 C/C 应用中链接 XGBoost假设你的应用使用 CMake 构建通过find_package()与target_link_libraries()即可链接 XGBoostcmake_minimum_required(VERSION 3.18) project(your_project_name LANGUAGES C CXX VERSION your_project_version) find_package(xgboost REQUIRED) add_executable(your_project_name /path/to/project_file.c) target_link_libraries(your_project_name xgboost::xgboost)为了让 CMake 能找到 XGBoost 库调用 CMake 时需要传入-DCMAKE_PREFIX_PATH$CONDA_PREFIX告知 CMake 在 Conda 环境目录中查找# Activate the Conda environment where we previously installed XGBoost conda activate [env_name] # Invoke CMake with CMAKE_PREFIX_PATH cmake -B build -S . -DCMAKE_PREFIX_PATH$CONDA_PREFIX # Build your application cmake --build build仓库内的真实示例 demo/c-api/basic/CMakeLists.txt 展示了更完整的写法并处理了一个关键细节——XGBoost 以静态库构建时其 C 依赖也需要一并链接进可执行文件project(api-demo LANGUAGES C VERSION 0.0.1) find_package(xgboost REQUIRED) # xgboost is built as static libraries, all cxx dependencies need to be linked into the # executable. if(XGBOOST_BUILD_STATIC_LIB) enable_language(CXX) # find again for those cxx libraries. find_package(xgboost REQUIRED) endif() add_executable(api-demo c-api-demo.c) target_link_libraries(api-demo PRIVATE xgboost::xgboost)两种链接方式对比除了find_package()如果 XGBoost 以 git submodule 形式放在你的项目源码树内也可以直接用add_subdirectory()add_subdirectory(xgboost) add_executable(api-demo c-api-demo.c) target_link_libraries(api-demo xgboost) # 注意此时目标名不带命名空间前缀以上两种方式在 demo/c-api/basic/README.md 中均有说明。若不用 CMakedemo/c-api/basic/Makefile 给出了 make 方式SRCc-api-demo.c TGTc-api-demo XGBOOST_ROOT ?../.. INCLUDE_DIR-I$(XGBOOST_ROOT)/include -I$(XGBOOST_ROOT)/dmlc-core/include LIB_DIR-L$(XGBOOST_ROOT)/lib $(TGT): $(SRC) Makefile $(cc) $(CFLAGS) $(INCLUDE_DIR) $(LIB_DIR) -o $(TGT) $(SRC) -lxgboost run: $(TGT) LD_LIBRARY_PATH$(XGBOOST_ROOT)/lib ./$(TGT)四、C API 使用要点官方建议4.1 始终检查返回值C API 的绝大多数函数都返回int错误码0 表示成功。官方建议用宏统一包装所有调用。C 应用版本出错时打印文件、行号与错误信息并退出#define safe_xgboost(call) { \ int err (call); \ if (err ! 0) { \ fprintf(stderr, %s:%d: error in %s: %s\n, __FILE__, __LINE__, #call, XGBGetLastError()); \ exit(1); \ } \ }C 应用版本把错误转换为异常抛出#define safe_xgboost(call) { \ int err (call); \ if (err ! 0) { \ throw std::runtime_error(std::string(__FILE__) : std::to_string(__LINE__) \ : error in #call : XGBGetLastError()); \ } \ }注意其中使用的XGBGetLastError()用于获取最近一次错误的具体描述字符串。断言方式当表达式求值为 0false时会把表达式、源文件名和行号输出到标准错误并调用abort()适合在代码中测试假设DMatrixHandle dmat; char const *config {\uri\: \training_data.libsvm?formatlibsvm\, \silent\: 0}; assert(XGDMatrixCreateFromURI(config, dmat) 0);assert在 C/C 中均可使用但注意在NDEBUG宏开启的 release 构建下断言会被编译器移除正式代码中仍以safe_xgboost风格的显式检查为主。4.2 及时释放句柄防止内存泄漏BoosterHandle与DMatrixHandle都是不透明指针opaque handle其底层内存在 include/xgboost/c_api.h 中定义为typedef void *DMatrixHandle;和typedef void *BoosterHandle;第 49-51 行。所有通过 API 创建的对象使用完毕后必须用对应的*Free函数释放#include assert.h #include stdio.h #include stdlib.h #include xgboost/c_api.h int main(int argc, char** argv) { int silent 0; BoosterHandle booster; // do something with booster //free the memory XGBoosterFree(booster); DMatrixHandle DMatrixHandle_param; // do something with DMatrixHandle_param // free the memory XGDMatrixFree(DMatrixHandle_param); return 0; }4.3 训练与推理的数据格式必须一致对于树模型训练与预测时必须使用一致的稀疏/稠密格式例如训练数据用稠密矩阵则预测数据也应该是稠密矩阵训练用 libsvm 格式则预测也应提供 libsvm 格式。格式混用会导致错误的预测输出。这一点在 doc/tutorials/c_api_tutorial.rst 中明确强调。4.4 参数值一律使用字符串通过XGBoosterSetParam设置 Booster 参数时无论参数本身的类型是 int、char、float 还是 double都必须编码为字符串传入BoosterHandle booster; XGBoosterSetParam(booster, parameter_name, 0.1);这是因为参数最终会经字符串解析进入统一的配置解析流程相关实现见 src/learner.cc 等核心模块字符串编码可以规避不同语言绑定之间的类型差异。五、完整实战从数据加载到模型训练下面按官方教程的顺序串起一个完整的训练-评估-预测流程。所有片段都可直接组装进main()源码级参考见 demo/c-api/basic/c-api-demo.c。5.1 从文件加载 DMatrix若数据集在文件中可用XGDMatrixCreateFromURI加载。配置以 JSON 字符串形式传入支持通过?formatlibsvm指定格式silent控制是否静默DMatrixHandle data; // handle to DMatrix // Load the data from file store it in data variable of DMatrixHandle datatype char const *config {\uri\: \/path/to/file/filename?formatlibsvm\, \silent\: 0}; safe_xgboost(XGDMatrixCreateFromURI(config, data));示例程序 demo/c-api/basic/c-api-demo.c 中用一个辅助函数动态拼接该 JSON 配置并同时加载训练集与测试集第 51-58 行DMatrixHandle dtrain, dtest; char dmat_config[256]; MakeDMatrixConfig(../../data/agaricus.txt.train?formatlibsvm, silent, sizeof(dmat_config), dmat_config); safe_xgboost(XGDMatrixCreateFromURI(dmat_config, dtrain));5.2 从内存矩阵创建 DMatrix也可以用XGDMatrixCreateFromMat直接从二维数组创建 DMatrix。该函数的关键参数是缺失值标记数值等于该标记的条目会被当作缺失值处理// 1D matrix const int data1[] { 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, /* ... 共 50 个元素 ... */ }; // 2D matrix const int ROWS 6, COLS 3; const int data2[ROWS][COLS] { {1, 2, 3}, {2, 4, 6}, {3, -1, 9}, {4, 8, -1}, {2, 5, 1}, {0, 1, 5} }; DMatrixHandle dmatrix1, dmatrix2; // Pass the matrix, no of rows columns contained in the matrix variable // here 0 represents the missing value in the matrix dataset // dmatrix variable will contain the created DMatrix using it safe_xgboost(XGDMatrixCreateFromMat(data1, 1, 50, 0, dmatrix1)); // here -1 represents the missing value in the matrix dataset safe_xgboost(XGDMatrixCreateFromMat(data2, ROWS, COLS, -1, dmatrix2));更贴近现代的用法是借助 NumPy 风格的 array interfaceJSON 字符串调用XGDMatrixCreateFromDense示例见 demo/c-api/inference/inference.c 第 122-128 行这种方式可以直接把 C 数组封装成 DMatrix无需复制数据char const *X_interface Matrix_ArrayInterface(X); // 形如 {data: [addr, true], shape: [n, m], typestr: f4, version: 3} char config[] {\nthread\: 16, \missing\: NaN}; DMatrix Xy; safe_xgboost(XGDMatrixCreateFromDense(X_interface, config, Xy)); safe_xgboost(XGDMatrixSetDenseInfo(Xy, label, y-data, y-shape[0], 1));5.3 创建 BoosterXGBoosterCreate接受一个 DMatrix 句柄数组作为缓存便于训练过程中复用这些数据做评估BoosterHandle booster; const int eval_dmats_size 2; // We assume that training and test data have been loaded into train and test DMatrixHandle eval_dmats[eval_dmats_size] {train, test}; safe_xgboost(XGBoosterCreate(eval_dmats, eval_dmats_size, booster));5.4 设置标签与读取标签每个 DMatrix 都要用XGDMatrixSetFloatInfo设置label之后用XGDMatrixGetFloatInfo读取const int ROWS 6, COLS 3; const int data[ROWS][COLS] { {1, 2, 3}, {2, 4, 6}, {3, -1, 9}, {4, 8, -1}, {2, 5, 1}, {0, 1, 5} }; DMatrixHandle dmatrix; safe_xgboost(XGDMatrixCreateFromMat(data, ROWS, COLS, -1, dmatrix)); // variable to store labels for the dataset created from above matrix float labels[ROWS]; for (int i 0; i ROWS; i) { labels[i] i; } // Loading the labels safe_xgboost(XGDMatrixSetFloatInfo(dmatrix, label, labels, ROWS)); // reading the labels and store the length of the result bst_ulong result_len; const float *result; safe_xgboost(XGDMatrixGetFloatInfo(dmatrix, label, result_len, result)); for(unsigned int i 0; i result_len; i) { printf(label[%i] %f\n, i, result[i]); }注意bst_ulong类型在 include/xgboost/c_api.h 中被定义为uint64_t第 28 行打印时通常需要显式转换。5.5 设置训练参数参数全部通过XGBoosterSetParam以字符串设置完整的参数清单见 doc/parameter.rstBoosterHandle booster; safe_xgboost(XGBoosterSetParam(booster, booster, gblinear)); // default max_depth 6 safe_xgboost(XGBoosterSetParam(booster, max_depth, 3)); // default eta 0.3 safe_xgboost(XGBoosterSetParam(booster, eta, 0.1));示例程序中的一组典型配置demo/c-api/basic/c-api-demo.c 第 68-74 行还演示了设备选择与二分类目标safe_xgboost(XGBoosterSetParam(booster, device, use_gpu ? cuda : cpu)); safe_xgboost(XGBoosterSetParam(booster, objective, binary:logistic)); safe_xgboost(XGBoosterSetParam(booster, min_child_weight, 1)); safe_xgboost(XGBoosterSetParam(booster, gamma, 0.1)); safe_xgboost(XGBoosterSetParam(booster, max_depth, 3)); safe_xgboost(XGBoosterSetParam(booster, verbosity, silent ? 0 : 1));其中device为cuda时表示使用 GPU 训练需构建支持 CUDA 的版本cpu为默认 CPU 训练。5.6 迭代训练与评估XGBoosterUpdateOneIter执行一轮提升迭代XGBoosterEvalOneIter在每轮之后给出各评估数据集的指标输出int num_of_iterations 20; const char* eval_names[eval_dmats_size] {train, test}; const char* eval_result NULL; for (int i 0; i num_of_iterations; i) { // Update the model performance for each iteration safe_xgboost(XGBoosterUpdateOneIter(booster, i, train)); // Give the statistics for the learner for training testing dataset in terms of error after each iteration safe_xgboost(XGBoosterEvalOneIter(booster, i, eval_dmats, eval_names, eval_dmats_size, eval_result)); printf(%s\n, eval_result); }注意如需自定义损失函数应改用XGBoosterBoostOneIter自行指定一阶梯度和二阶梯度。5.7 获取特征数用XGBoosterGetNumFeature获取数据集的特征数量bst_ulong num_of_features 0; // Assuming booster variable of type BoosterHandle is already declared // and dataset is loaded and trained on booster safe_xgboost(XGBoosterGetNumFeature(booster, num_of_features)); // Printing number of features by type conversion of num_of_features variable from bst_ulong to unsigned long printf(num_feature: %lu\n, (unsigned long)(num_of_features));六、推理预测配置详解6.1 基于 DMatrix 的预测新版 API 使用XGBoosterPredictFromDMatrix预测配置同样以 JSON 字符串传入。配置中的字段含义如下training是否为训练模式推理时置falsetype预测类型0 表示普通输出value1 表示 margin2 表示 leaf index 等具体枚举见 include/xgboost/c_api.h 中XGBoosterPredictType相关注释iteration_begin/iteration_end预测时使用的迭代树范围均为 0 表示使用全部strict_shape是否强制输出固定的多维形状。char const config[] {\training\: false, \type\: 0, \iteration_begin\: 0, \iteration_end\: 0, \strict_shape\: false}; /* Shape of output prediction */ uint64_t const* out_shape; /* Dimension of output prediction */ uint64_t out_dim; /* Pointer to a thread local contiguous array, assigned in prediction function. */ float const* out_result NULL; safe_xgboost( XGBoosterPredictFromDMatrix(booster, dmatrix, config, out_shape, out_dim, out_result)); for (unsigned int i 0; i output_length; i){ printf(prediction[%i] %f \n, i, output_result[i]); }关于输出缓冲有一个重要约定demo/c-api/inference/inference.c 第 168 行有明确注释out_result指向线程局部thread-local的连续数组该指针在下次调用 API 前有效因此如需长期使用必须先拷贝/* Always copy output from XGBoost before calling next API function. */ Matrix_Create(predt, out_results, out_shape[0], out_shape[1]);6.2 就地预测Inplace PredictionXGBoosterPredictFromDense支持直接对内存中的稠密数组做预测跳过 DMatrix 创建的开销速度更快、内存效率更高但只支持基础推理类型。配置中多了一个cache_idDMatrix 缓存槽位和missing缺失值标记char const config[] {\type\: 0, \iteration_begin\: 0, \iteration_end\: 0, \strict_shape\: true, \cache_id\: 0, \missing\: NaN}; uint64_t const *out_shape; uint64_t out_dim; float const *out_results; char const *X_interface Matrix_ArrayInterface(X); safe_xgboost(XGBoosterPredictFromDense(booster, X_interface, config, NULL, out_shape, out_dim, out_results));七、模型保存与加载7.1 保存模型XGBoosterSaveModel按路径保存模型文件名后缀决定格式.json为 JSON 格式旧版二进制格式则不带后缀BoosterHandle booster; const char *model_path /path/of/model.json; safe_xgboost(XGBoosterSaveModel(booster, model_path));7.2 加载模型XGBoosterLoadModel要求先创建 Booster 句柄再加载BoosterHandle booster; const char *model_path /path/of/model.json; // create booster handle first safe_xgboost(XGBoosterCreate(NULL, 0, booster)); // set the model parameters here // load model safe_xgboost(XGBoosterLoadModel(booster, model_path)); // predict the model here推理示例 demo/c-api/inference/inference.c 第 141-147 行演示了完整的训练-保存-加载-推理闭环先用XGBoosterSaveModel(booster, model.json)保存再用XGBoosterCreate(NULL, 0, booster)创建空 Booster 后XGBoosterLoadModel(booster, model.json)加载。7.3 收尾清理程序结束前释放所有句柄防止内存泄漏safe_xgboost(XGDMatrixFree(dmatrix)); safe_xgboost(XGBoosterFree(booster));八、进阶Streaming 外部内存数据Custom Data Iterator当数据规模超过内存或需要分批读取时可以使用 Streaming 分组include/xgboost/c_api.h 第 311 行起提供的回调式数据迭代接口。官方在 demo/c-api/external-memory/ 中给出了完整示例其 README 明确指出该功能目前仍处于experimental阶段尚不适合生产环境。8.1 迭代器协议自定义迭代器需要实现两个回调next(DataIterHandle handle)把一批数据传给 XGBoost返回 0 表示迭代结束返回 1 表示继续reset(DataIterHandle handle)重置迭代状态使数据可以再次从头读取。示例 demo/c-api/external-memory/external_memory.c 定义了一个DataIter结构体第 26-41 行内部保存每批的data、labels、lengths、批次总数n与当前迭代位置cur_it同时包含一个用于数据传输的代理 DMatrix 句柄_proxy。8.2 向 XGBoost 传递数据next回调中把当前批次通过 array interface JSON 写入代理 DMatrix并设置标签int DataIterator_Next(DataIterHandle handle) { DataIter *self (DataIter *)(handle); if (self-cur_it self-n) { self-cur_it 0; return 0; /* At end */ } /* A JSON string encoding array interface (standard from numpy). */ char array[] {\data\: [%lu, false], \shape\:[%lu, 1], \typestr\: \f4\, \version\: 3}; memset(self-_array, \0, sizeof(self-_array)); sprintf(self-_array, array, (size_t)self-data[self-cur_it], self-lengths[self-cur_it]); safe_xgboost(XGProxyDMatrixSetDataDense(self-_proxy, self-_array)); /* The data passed in the iterator must remain valid (not being freed until the next * iteration or reset) */ safe_xgboost(XGDMatrixSetDenseInfo(self-_proxy, label, self-labels[self-cur_it], self-lengths[self-cur_it], 1)); self-cur_it; return 1; /* Continue. */ }8.3 关键内存约定注释中特别强调传入next回调的数据必须保持有效不能被释放直到下一次迭代或调用reset为止。外部内存 DMatrix 不仅限于训练也适用于预测等其他功能。8.4 创建外部内存 DMatrix 并训练XGDMatrixCreateFromCallback把迭代器包装成 DMatrix配置中可通过cache_prefix指定缓存文件前缀训练过程中会在当前目录生成cache-前缀的缓存文件/* Create DMatrix from iterator. During training, some cache files with the * prefix cache- will be generated in current directory */ char config[] {\missing\: NaN, \cache_prefix\: \cache\}; DMatrix Xy; safe_xgboost(XGDMatrixCreateFromCallback( iter, iter._proxy, DataIterator_Reset, DataIterator_Next, config, Xy)); TrainModel(Xy);训练时官方建议使用tree_methodhist示例第 143 行外部内存训练支持approx或hist方法。九、测试与更多资源官方测试C API 的行为由 tests/cpp/ 下的测试用例保障其中针对 Prediction 的测试还会验证复用 ProxyDMatrix 降低 DMatrix 创建延迟等细节demo/c-api/inference/inference.c 文件头注释提及test_c_api.cc。入门示例demo/c-api/basic/c-api-demo.c 是完整可编译的最小示例覆盖文件加载、内存矩阵、CSR/CSC 稀疏矩阵、训练、评估、预测与释放全过程是学习 C API 的最佳起点。外部内存demo/c-api/external-memory/external_memory.c 演示自定义数据迭代器。推理demo/c-api/inference/inference.c 演示 DMatrix 预测与就地inplace预测两种方式。参数参考所有 Booster 参数的取值与默认值见 doc/parameter.rst。构建入口仓库根目录的 CMakeLists.txt 定义了BUILD_C_DOC等构建选项JVM 等语言绑定的 C 接口生成脚本位于 jvm-packages/create_jni.py可帮助你理解 C API 如何支撑上层语言绑定。总结XGBoost 的 C API 是所有语言绑定的基石接口稳定且文档完备。核心实践可归纳为五条一是通过 CMakefind_package/add_subdirectory接入工程并正确传递CMAKE_PREFIX_PATH二是用safe_xgboost宏统一做错误检查、用XGDMatrixFree/XGBoosterFree保证资源释放三是牢记训练与推理的数据格式必须一致、参数值一律用字符串四是掌握XGBoosterPredictFromDMatrix预测配置中type、iteration_begin/end、strict_shape等字段的语义并注意输出结果在使用前先拷贝五是对超大数据集可以借助 experimental 的 Streaming 回调迭代接口按批喂入数据。把上述要点与 demo/c-api/ 中的三个示例结合起来即可在自己的 C/C 项目中快速落地从训练到推理的完整链路。【免费下载链接】xgboostScalable, Portable and Distributed Gradient Boosting (GBDT, GBRT or GBM) Library, for Python, R, Java, Scala, C and more. Runs on single machine, Hadoop, Spark, Dask, Flink and DataFlow项目地址: https://gitcode.com/gh_mirrors/xg/xgboost创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考