如何在 C++ 中使用 XGBOOST https://github.com/dmlc/xgboost/库?我已经创建了 Python 和 Java API,但我找不到 C++ 的 API
6 回答
我最终使用了 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);
使用 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所说:
“稀疏”元素被树助推器视为“缺失”,而线性助推器则视为零。对于树模型,在训练和评分过程中使用一致的数据格式很重要。
这是您需要的:<a href="https://github.com/EmbolismSoil/xgboostpp" rel="nofollow noreferrer">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;
}
如果在 Python 中训练没问题,并且您只需要在 C++ 中运行预测,那么有一个很好的工具可以从训练好的模型生成静态 if/else 代码:
https://github.com/popcorn/xgb2cpp
在花了一天时间尝试在 C++ 中加载和使用 xgboost 模型但没有成功后,我最终使用了它。由 xgb2cpp 生成的代码可以立即运行,并且还具有它没有任何依赖项的好处。
没有我知道的例子。有一个 c_api.h 文件,其中包含该包的 C/C++ api,您必须找到使用它的方法。我刚刚这样做了。花了我几个小时阅读代码并尝试了一些事情。但最终我设法创建了一个有效的 xgboost 的 C++ 示例。
为了解决这个问题,我们从 C++ 源代码运行 xgboost 程序。