I had to use a Catboost model in some programming languages, Golang and Python. The best option (for performance and compatibility) is to use an evaluation library which can be a C or C++ API. I followed the official documentation to compile the C API, but it has a lot of problems to solve so that work.
These are the problems we encountered while trying to create the evaluation library in C:
1.
error: variable has incomplete type 'ModelCalcerHandle' (aka 'void')
ModelCalcerHandle modelHandle;
c_wrapper.c:16:13: warning: incompatible pointer types passing 'float (*)[3]' to parameter of type 'const float **' [-Wincompatible-pointer-types]
&floatFeatures, 3,
^~~~~~~~~~~~~~
/Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:151:19: note: passing argument to parameter 'floatFeatures' here
const float** floatFeatures, size_t floatFeaturesSize,
^
c_wrapper.c:17:13: warning: incompatible pointer types passing 'char *(*)[4]' to parameter of type 'const char ***' [-Wincompatible-pointer-types]
&catFeatures, 4,
^~~~~~~~~~~~
/Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:152:19: note: passing argument to parameter 'catFeatures' here
const char*** catFeatures, size_t catFeaturesSize,
^
c_wrapper.c:18:13: warning: incompatible pointer types passing 'double (*)[1]' to parameter of type 'double *' [-Wincompatible-pointer-types]
&result, 1
^~~~~~~
/Users/eli/workspace/test_c_api/catboost/catboost/libs/model_interface/c_api.h:153:13: note: passing argument to parameter 'result' here
double* result, size_t resultSize);
Solution:
modelHandle
variable as:ModelCalcerHandle *modelHandle = ModelCalcerCreate();
After this change it was posible to compile the C program, but we got a new error:
[1] 6489 segmentation fault ./program
float floatFeaturesRaw[100];
const float *floatFeatures = floatFeaturesRaw;
const char *catFeaturesRaw[2] = {"1", "2"};
const char **catFeatures = catFeaturesRaw;
double resultRaw[1];
double *result = resultRaw;
and
if (!CalcModelPredictionSingle(
modelHandle,
&floatFeatures, 3,
&catFeatures, 4,
result, 1)) //We remove `&`
{
printf("CalcModelPrediction error message: %s\n", GetErrorString());
}
I'll add the complete solution, from code fixes to how to compile C code, in a comment.
Here is the complete solution:
git clone https://github.com/catboost/catboost.git
Open the catboost directory from the local copy of the CatBoost repository.
Build the evaluation library (I've chosen the shared library, but you can select what you need). In my case I had to change the --target-platform
argument, I was using a Mac M1 with macOS Ventura 13.1 and the clang version was 14.0.0:
./ya make -r catboost/libs/model_interface --target-platform CLANG14-DARWIN-ARM64
#include <stdio.h>
#include <c_api.h>
int main()
{
float floatFeaturesRaw[3] = {0, 89, 1};
const float *floatFeatures = floatFeaturesRaw;
const char *catFeaturesRaw[4] = {"Others", "443_HTTPS", "6", "24"};
const char **catFeatures = catFeaturesRaw;
double resultRaw[4];
double *result = resultRaw;
ModelCalcerHandle *modelHandle = ModelCalcerCreate();
if (!LoadFullModelFromFile(modelHandle, "catboost_model"))
{
printf("LoadFullModelFromFile error message: %s\n", GetErrorString());
}
SetPredictionType(modelHandle, 3);
if (!CalcModelPredictionSingle(
modelHandle,
floatFeatures, 3,
catFeatures, 4,
result, 4))
{
printf("CalcModelPrediction error message: %s\n", GetErrorString());
}
printf("%f\n", result[0]);
printf("%f\n", result[1]);
printf("%f\n", result[2]);
printf("%f\n", result[3]);
ModelCalcerDelete(modelHandle);
}
To Consider:
SetPredictionType
to APT_PROBABILITYresult[4]
.CalcModelPredictionSingle
method.gcc -v -o program.out c_code.c -l catboostmodel -I /path/to/catboost/repo/catboost/catboost/libs/model_interface/ -L /path/to/catboost/repo/catboost/catboost/libs/model_interface/
IMPORTANT: Make sure that no warning or error messages have been displayed.
IMPORTANT: Make sure the catboost model file is in the same path as program.out
.
./program.out