XGBoost C++ API 指南:头文件导出、稳定性边界与插件系统实战
XGBoost C API 指南头文件导出、稳定性边界与插件系统实战【免费下载链接】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导读本文以 doc/c.rst 为核心系统讲解 XGBoost C 接口的定位与使用方式从 1.0 版本起 CMake 构建会生成安装规则、导出全部 C 头文件同时官方明确警告该接口比其它语言绑定更接近 XGBoost 内部、变更频繁、不承诺稳定性因此访问内部能力的主流途径是插件系统。读完本文你将掌握C 头文件如何随构建安装与消费、如何生成 C 接口的 Doxygen 文档、插件系统的注册宏清单以及从零编写一个可被objectivemylogistic直接调用的自定义目标函数插件的完整三步流程。C API 的定位靠近内部而非稳定契约与 Python、R、Java 等语言绑定不同XGBoost 的 C 接口直接暴露训练引擎内部结构。原文档明确给出三条关键事实自1.0 release起CMake 会生成安装规则将全部 C 头文件导出到系统C 接口比其他语言绑定更贴近 XGBoost 内部实现因此它变更频繁官方不维护其稳定性we dont maintain its stability。从源码结构看这一不稳定的接口由 include/xgboost 目录承载包含base.h、data.h、learner.h、gbm.h、objective.h、metric.h、tree_model.h、linalg.h、json.h、parameter.h等 30 余个公开头文件。它们构成内部各模块互相依赖的骨架是插件开发者与训练内核打交道的主要入口。与之相对include/xgboost/c_api.h提供的 C API 才是对外稳定层——C 头文件更像是内部组件说明书。从 1.0 起CMake 导出全部 C 头文件安装规则做了什么CMakeLists.txt 中与头文件安装相关的核心逻辑如下# Install all headers. Please note that currently the C headers does not form an API. install(DIRECTORY ${xgboost_SOURCE_DIR}/include/xgboost DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})这段注释再次印证了官方态度C 头文件当前并不构成一份API。除头文件外安装规则还会导出动态库libxgboost或开启BUILD_STATIC_LIBON时的静态库此时额外导出objxgboost与dmlcXGBoostTargets.cmake以xgboost::命名空间导出安装到${libdir}/cmake/xgboostxgboost-config.cmake与xgboost-config-version.cmake由 cmake/xgboost-config.cmake.in 模板生成xgboost.pcpkg-config 文件由 cmake/xgboost.pc.in 模板生成默认开启可用ADD_PKGCONFIGOFF关闭。注意当构建 Python wheel 时会设置__XGBOOST_FOR_PYTHON_WHEEL跳过上述系统级安装规则见 CMakeLists.txt普通开发者构建不受影响。在 CMake 工程中消费安装完成后下游工程可通过标准的find_package方式链接find_package(xgboost REQUIRED) target_link_libraries(your_app PRIVATE xgboost::xgboost)如果目标是静态库XGBOOST_BUILD_STATIC_LIBONcmake/xgboost-config.cmake.in 会自动帮你补齐传递依赖Threads、OpenMP若USE_OPENMPON、CUDAToolkit与CCCL若USE_CUDAON、Nccl若USE_NCCLON从而保证链接期符号完整。编译器版本前提C 接口依赖较新的标准库特性构建时对编译器有硬性要求CMakeLists.txtGCC ≥ 8.1、Clang ≥ 9.0、AppleClang ≥ 11.0Xcode 11.0、MSVC ≥ 2019。GCC 8.x 还会额外链接stdcfs以提供std::filesystem。如何获取 C 接口的 Doxygen 文档原文档提供的dev/files.html链接指向的是 Doxygen 生成的在线 API 参考。该页面不随仓库源码存在而是由构建系统产出你可以在本地复现cmake -DBUILD_C_DOCON -DCMAKE_BUILD_TYPERelease ..开启后cmake/Doc.cmake 会查找 Doxygen 与 graphvizdot并通过add_custom_target(doc_doxygen ALL)生成文档。关键配置在 doc/Doxyfile.in 中INPUT PROJECT_SOURCE_DIR/include仅扫描include目录FILE_PATTERNS *.h且RECURSIVE YES递归收录全部头文件EXCLUDE_PATTERNS */test/*与logging.h排除测试与日志实现细节EXAMPLE_PATH PROJECT_SOURCE_DIR/demo/c-api/C API 示例代码可被文档内嵌引用EXTRACT_ALL YES即使无注释也会提取实体方便浏览内部符号。生成产物位于${PROJECT_BINARY_DIR}/doc_doxygen其中即包含files.html全量文件列表页。插件系统接触内部的标准途径正是因为 C 接口不稳定官方推荐配合插件系统使用已有的 C 头文件来获取更多内部访问能力。插件机制允许你在不修改主仓库代码的前提下向 XGBoost 注入新功能适合实验性特性与私有定制。可用的注册宏根据 plugin/README.md插件必须通过注册宏把新功能登记进 XGBoost 才能被使用宏注册对象对应头文件XGBOOST_REGISTER_METRIC评估指标metricinclude/xgboost/metric.hXGBOOST_REGISTER_GBM梯度提升器boosterinclude/xgboost/gbm.hXGBOOST_REGISTER_OBJECTIVE目标函数objectiveinclude/xgboost/objective.hXGBOOST_REGISTER_TREE_UPDATER树更新器tree updaterinclude/xgboost/tree_updater.hDMLC_REGISTER_PARAMETER参数集合来自 dmlc-coredmlc-core 的parameter.h例如XGBOOST_REGISTER_OBJECTIVE的宏定义位于 include/xgboost/objective.h用法为XGBOOST_REGISTER_OBJECTIVE(UniqueId, Name)配合.describe(...)与.set_body(...)完成类工厂注册。仓库内已有的插件形态plugin/example最简单的插件示例注册了一个自定义目标函数详见下一节plugin/sycl基于 SYCL 的后端插件通过 plugin/CMakeLists.txt 的PLUGIN_SYCL选项接入覆盖common/、data/、predictor/、tree/多个模块plugin/updater_gpuGPU 树更新器插件另有 plugin/updater_gpu/README.md 说明。实战三步注册一个自定义目标函数以 plugin/example/custom_obj.cc 为蓝本它实现了一个可缩放负样本权重的 logistic 回归目标函数mylogistic。官方 plugin/example/README.md 给出三步流程第一步编写源文件实现扩展在xgboost::obj命名空间内定义一个继承ObjFunction的类并实现以下核心接口#include xgboost/base.h #include xgboost/json.h #include xgboost/linalg.h // for Vector #include xgboost/objective.h #include xgboost/parameter.h namespace xgboost::obj { struct MyLogisticParam : public XGBoostParameterMyLogisticParam { float scale_neg_weight; DMLC_DECLARE_PARAMETER(MyLogisticParam) { DMLC_DECLARE_FIELD(scale_neg_weight) .set_default(1.0f) .set_lower_bound(0.0f) .describe(Scale the weight of negative examples by this factor); } }; DMLC_REGISTER_PARAMETER(MyLogisticParam); class MyLogistic : public ObjFunction { public: std::setstd::string Configure(const Args args) override { return UpdateAndGetUsedParameters(param_, args); } [[nodiscard]] ObjInfo Task() const override { return ObjInfo::kRegression; } void GetGradient(const HostDeviceVectorfloat preds, MetaInfo const info, std::int32_t /*iter*/, linalg::MatrixGradientPair* out_gpair) override { out_gpair-Reshape(info.num_row_, 1); const std::vectorfloat preds_h preds.HostVector(); auto out_gpair_h out_gpair-HostView(); auto const labels_h info.labels.HostView(); for (size_t i 0; i preds_h.size(); i) { float w info.GetWeight(i); if (labels_h(i) 0.0f) w * param_.scale_neg_weight; // 缩放负样本权重 float p 1.0f / (1.0f std::exp(-preds_h[i])); // sigmoid 变换 float grad (p - labels_h(i)) * w; // 一阶梯度 float hess p * (1.0f - p) * w; // 二阶梯度 out_gpair_h(i) GradientPair(grad, hess); } } [[nodiscard]] const char* DefaultEvalMetric() const override { return logloss; } void PredTransform(HostDeviceVectorfloat* io_preds) const override { // 将 margin 值变换为概率 std::vectorfloat preds io_preds-HostVector(); for (auto pred : preds) pred 1.0f / (1.0f std::exp(-pred)); } void ProbToMargin(linalg::Vectorfloat* base_score) const override { // 将概率 base_score 变换回 margin 值 auto h_intercept base_score-HostView(); for (std::size_t i 0, n h_intercept.Size(); i n; i) { h_intercept(i) -std::log(1.0f / h_intercept(i) - 1.0f); } } void SaveConfig(Json* p_out) const override { auto out *p_out; out[name] String(mylogistic); out[my_logistic_param] ToJson(param_); } void LoadConfig(Json const in) override { FromJson(in[my_logistic_param], param_); } private: MyLogisticParam param_; }; } // namespace xgboost::obj值得注意的工程细节参数模块来自 dmlc-coreDMLC_DECLARE_FIELD(scale_neg_weight)声明了字段及其默认值1.0f、下界0.0f从而自动获得参数校验与序列化能力GetGradient中labels_h(i) 0.0f时放大权重正是缩放负样本权重的业务逻辑所在SaveConfig/LoadConfig使用 include/xgboost/json.h 提供的Json结构完成配置持久化保证模型文件可保存、可加载Task()返回ObjInfo::kRegression向训练引擎声明本目标的求解任务类型。第二步用注册宏登记扩展在文件末尾通过宏把类注册为名字mylogistic的目标函数custom_obj.ccXGBOOST_REGISTER_OBJECTIVE(MyLogistic, mylogistic) .describe(User defined logistic regression plugin) .set_body([]() { return new MyLogistic(); });第三步把源文件加入构建在 plugin/CMakeLists.txt 中追加一行把源文件编入objxgboost目标target_sources(objxgboost PRIVATE ${xgboost_SOURCE_DIR}/plugin/example/custom_obj.cc)然后重新用 CMake 构建 XGBoost。注意插件源文件必须与主仓库一起编译链接因此本仓库的plugin/example是只读示范——在你自己的工程中应将这份.cc文件放到你自己维护的插件目录并接入你自己的工作流。验证直接用参数调用构建完成后在 Python / R / CLI 中把目标函数切换为新注册的名字即可import xgboost as xgb model xgb.train( {objective: mylogistic, scale_neg_weight: 2.0}, dtrain, )scale_neg_weight即插件自定义参数会被Configure中的UpdateAndGetUsedParameters识别并解析。稳定层与不稳定层如何选择从仓库结构可以清晰看到分层策略对外稳定契约include/xgboost/c_api.h对应的 C API另有 src/c_api 实现以及 Python/R/Java 各绑定内部 C 接口include/xgboost 下的头文件被插件系统用于访问内核插件扩展点metric / gbm / objective / tree_updater 四大注册宏是接入训练流程的官方缝隙。因此实践上的建议是普通调用优先使用语言绑定或 C API只有需要深入定制自定义目标函数、评估指标、树更新器或后端时才编写 C 插件并做好随版本迭代适配头文件的心理准备——这正是 doc/c.rst 反复强调不维护稳定性的现实含义。若想系统查阅全部可用头文件与符号可先阅读 doc/index.rst 中 C 接口条目对应的 doc/c.rst再按上文BUILD_C_DOCON方式本地生成完整 Doxygen 文档。【免费下载链接】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),仅供参考