Booster使用先前的DMatrix后,XGDMatrixCreateFromMat失败

时间:2019-06-25 19:06:38

标签: c++ xgboost

如果在同一过程中多次重复以下代码路径,则XGDMatrixCreateFromMat在第二次访问期间将失败,并返回-1。作为参考,我遵循了Using XGBOOST in c++

但是,如果我在助推器中删除了dtrainXGBoosterCreate和后续调用)的使用,则多次调用XGDMatrixCreateFromMat会在同一过程中成功,但是当然创建DMatrix的目的是要与增强器一起使用进行预测。请注意,以下代码路径在不同进程中多次调用时有效。


DMatrixHandle dtrain[1];

XGDMatrixCreateFromMat(reinterpret_cast<float*>(copied_inputs), 
 data_size, input_dim, -1, &dtrain[0]);
XGDMatrixSetFloatInfo(dtrain[0], "label", copied_labels, data_size);

XGDMatrixCreateFromMat(reinterpret_cast<float*>(copied_test_inputs), 
 test_data_size, input_dim, -1, &dtest);
XGDMatrixSetFloatInfo(dtest, "label", copied_test_labels, test_data_size);

XGBoosterCreate(&dtrain[0], 1, &h_booster_);
for (auto param : hyper_params_) {
    XGBoosterSetParam(h_booster_, param.first.c_str(), param.second.c_str());
}
for (int iter = 0; iter < num_boost_round_; ++iter) {
    XGBoosterUpdateOneIter(h_booster_, iter, dtrain);
    const char* eval_out;
    XGBoosterEvalOneIter(h_booster_, iter, &dtest, &evnames, 1, &eval_out);
}

std::cout << "Deleting dtrain: " << XGDMatrixFree(dtrain) << std::endl;
std::cout << "Deleting dtest: " << XGDMatrixFree(dtest) << std::endl;

std::cout << "XGBoosterFree: " << XGBoosterFree(h_booster_) << std::endl;

如何创建新的DMatrix并在同一过程中多次在booster中使用它。

1 个答案:

答案 0 :(得分:0)

通过添加以下行,我发现了实际错误。

if (XGDMatrixCreateFromMat(copied_inputs, data_size, input_dim, -1, &dmat) != 0) {
  std::string error_s(XGBGetLastError());
  std::cout << error_s << std::endl;
}

错误为There are NAN in the matrix, however, you did not set missing=NAN。这提示我创建float*输入的方式存在问题。虽然,它第一次运行没有问题,但是结果可能是错误的。我正在构建一个像下面的copied_inputs

float** copied_inputs = new float*[input_size];
float* copied_labels = new float[input_size];
for(size_t i = 0; i < input_size; ++i) {
  for(size_t j = 0; j < input_dim; ++j) {
    copied_inputs[i] = new float[input_dim];
    copied_inputs[i][j] = static_cast<float>(inputs[i][j]);
  }
  copied_labels[i] = static_cast<float>(outputs[i]);
}

copied_inputs的上述构造显然是错误的,因为在XGDMatrixCreateFromMat中访问它的方式是:

  for (xgboost::bst_ulong i = 0; i < nrow; ++i, data += ncol) {
    xgboost::bst_ulong matj = 0;
    for (xgboost::bst_ulong j = 0; j < ncol; ++j) {
      if (common::CheckNAN(data[j])) {
      } else {
        if (nan_missing || data[j] != missing) {
          data_vec[offset_vec[i] + matj] = Entry(j, data[j]);
          ++matj;
        }
      }
    }
  }

因此,我将copied_inputs的结构更改为:

  float* copied_inputs = new float[data_size * input_dim];
  float* copied_labels = new float[data_size];
  float* temp_copied_inputs = copied_inputs;
  for(size_t i = 0; i < data_size; ++i, temp_copied_inputs += input_dim) {
    for(size_t j = 0; j < input_dim; ++j) {
      temp_copied_inputs[j] = static_cast<float>(inputs[i][j]);
    }
    copied_labels[i] = static_cast<float>(outputs[i]);
  }

这解决了多次运行的问题。