在C++中使用XGBOOST

23

你有阅读安装指南吗? - kometen
是的,我已经阅读了安装指南,但是我找不到使用C++和xgboost的示例。 - V. Gai
2
尝试使用此链接: https://stackoverflow.com/questions/49744351/xgboost-prediction-is-different-for-c-and-python-for-the-same-model - user10772619
6个回答

32

我最终使用了C API,以下是一个示例:

// create the train data
int cols=3,rows=5;
float train[rows][cols];
for (int i=0;i<rows;i++)
    for (int j=0;j<cols;j++)
        train[i][j] = (i+1) * (j+1);

float train_labels[rows];
for (int i=0;i<rows;i++)
    train_labels[i] = 1+i*i*i;


// convert to DMatrix
DMatrixHandle h_train[1];
XGDMatrixCreateFromMat((float *) train, rows, cols, -1, &h_train[0]);

// load the labels
XGDMatrixSetFloatInfo(h_train[0], "label", train_labels, rows);

// read back the labels, just a sanity check
bst_ulong bst_result;
const float *out_floats;
XGDMatrixGetFloatInfo(h_train[0], "label" , &bst_result, &out_floats);
for (unsigned int i=0;i<bst_result;i++)
    std::cout << "label[" << i << "]=" << out_floats[i] << std::endl;

// create the booster and load some parameters
BoosterHandle h_booster;
XGBoosterCreate(h_train, 1, &h_booster);
XGBoosterSetParam(h_booster, "booster", "gbtree");
XGBoosterSetParam(h_booster, "objective", "reg:linear");
XGBoosterSetParam(h_booster, "max_depth", "5");
XGBoosterSetParam(h_booster, "eta", "0.1");
XGBoosterSetParam(h_booster, "min_child_weight", "1");
XGBoosterSetParam(h_booster, "subsample", "0.5");
XGBoosterSetParam(h_booster, "colsample_bytree", "1");
XGBoosterSetParam(h_booster, "num_parallel_tree", "1");

// perform 200 learning iterations
for (int iter=0; iter<200; iter++)
    XGBoosterUpdateOneIter(h_booster, iter, h_train[0]);

// predict
const int sample_rows = 5;
float test[sample_rows][cols];
for (int i=0;i<sample_rows;i++)
    for (int j=0;j<cols;j++)
        test[i][j] = (i+1) * (j+1);
DMatrixHandle h_test;
XGDMatrixCreateFromMat((float *) test, sample_rows, cols, -1, &h_test);
bst_ulong out_len;
const float *f;
XGBoosterPredict(h_booster, h_test, 0,0,&out_len,&f);

for (unsigned int i=0;i<out_len;i++)
    std::cout << "prediction[" << i << "]=" << f[i] << std::endl;


// free xgboost internal structures
XGDMatrixFree(h_train[0]);
XGDMatrixFree(h_test);
XGBoosterFree(h_booster);

你知道如何释放 const float *f; 吗?当我预测大量数据时,似乎内存没有被释放。我查看了代码 XGDMatrixFree(h_test) 应该能够释放内存,但是随着 h_test 的大小,内存泄漏仍在增加! - Khaledvic
1
显然 XGBoosterPredict 不是线程安全的,我正在从大量线程中调用它,https://github.com/dmlc/xgboost/issues/311 - Khaledvic
你是怎么安装C++库的?另外,你在使用哪些#include?@Tomer @Khaledvic - Meet Taraviya
请使用#include <xgboost/c_api.h>,并在您的makefile中链接已构建的xgboost库LDLIBSOPTIONS=../xgboost/lib/libxgboost.a ../xgboost/rabit/lib/librabit.a ../xgboost/dmlc-core/libdmlc.a。当然,还要将xgboost和rabit添加到包含路径中(gcc命令)-I../xgboost/include -I../xgboost/rabit/include - Khaledvic
顺便说一下,我正在使用Linux。 - Meet Taraviya
显示剩余3条评论

6
使用XGBoost C API。
  BoosterHandle booster;
  const char *model_path = "/path/of/model";

  // create booster handle first
  XGBoosterCreate(NULL, 0, &booster);

  // by default, the seed will be set 0
  XGBoosterSetParam(booster, "seed", "0");

  // load model
  XGBoosterLoadModel(booster, model_path);

  const int feat_size = 100;
  const int num_row = 1;
  float feat[num_row][feat_size];

  // create some fake data for predicting
  for (int i = 0; i < num_row; ++i) {
    for(int j = 0; j < feat_size; ++j) {
      feat[i][j] = (i + 1) * (j + 1)
    }
  }

  // convert 2d array to DMatrix
  DMatrixHandle dtest;
  XGDMatrixCreateFromMat(reinterpret_cast<float*>(feat),
                         num_row, feat_size, NAN, &dtest);

  // predict
  bst_ulong out_len;
  const float *f;
  XGBoosterPredict(booster, dtest, 0, 0, &out_len, &f);
  assert(out_len == num_row);
  std::cout << f[0] << std::endl;

  // free memory
  XGDMatrixFree(dtest);
  XGBoosterFree(booster);

请注意,当您想要加载现有模型(如上面的代码所示)时,您必须确保训练中的数据格式与预测中的数据格式相同。因此,如果您使用接受密集矩阵作为参数的XGBoosterPredict进行预测,则必须在训练中使用密集矩阵。
使用libsvm格式进行训练并使用密集矩阵进行预测可能会导致错误的预测,正如XGBoost FAQ所说:
“稀疏”元素被树增强器视为“缺失”,而线性增强器则将其视为零。对于树模型,在训练和评分期间使用一致的数据格式非常重要。

2

以下是您需要的内容:https://github.com/EmbolismSoil/xgboostpp

#include "xgboostpp.h"
#include <algorithm>
#include <iostream>

int main(int argc, const char* argv[])
{
    auto nsamples = 2;
    auto xgb = XGBoostPP(argv[1], 3); //特征列有4列, label有3个, iris例子中分别为三种类型的花,回归任何的话,这里nlabel=1即可

    //result = array([[9.9658281e-01, 2.4966884e-03, 9.2058454e-04],
    //       [9.9608469e-01, 2.4954407e-03, 1.4198524e-03]], dtype=float32)
    XGBoostPP::Matrix features(2, 4);
    features <<
        5.1, 3.5, 1.4, 0.2,
        4.9, 3.0, 1.4, 0.2;

    XGBoostPP::Matrix y;
    auto ret = xgb.predict(features, y);
    if (ret != 0){
        std::cout << "predict error" << std::endl;
    }

    std::cout << "intput : \n" << features << std::endl << "output: \n" << y << std::endl;
}

1
如果您只需要在C++中运行预测,而Python的训练可以接受,那么有一个很好的工具可以从训练模型生成静态if/else代码:

https://github.com/popcorn/xgb2cpp

在花费一天时间尝试在C++中加载和使用xgboost模型失败后,我最终使用了这个。 xgb2cpp生成的代码立即起作用,并且还具有没有任何依赖项的好处。


0
为了解决这个问题,我们从 C++ 源代码运行 xgboost 程序。

0

我不知道有没有示例。但是有一个c_api.h文件,其中包含了该软件包的C/C++ API,您需要使用它来找到解决方案。我刚刚做到了这一点。花了我几个小时阅读代码并尝试了一些东西。但最终我成功地创建了一个可工作的xgboost C++示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接