Saving, exporting and serving models

CatBoost · Expert · 12 min

A model only creates value once it serves predictions reliably, often outside Python.

model.save_model(path, format="cbm") writes CatBoost's native binary format, and CatBoostClassifier().load_model(path) reads it back. The .cbm format keeps everything: trees, CTR tables for categorical features, feature names and parameters. Pickle also works but ties you to Python and library versions.

Other formats (format=):

  • "json": human-readable, for inspection or custom evaluators
  • "onnx": for ONNX Runtime and other platforms; categorical features are not supported in ONNX export, so it suits numeric-only models
  • "coreml" for Apple devices, "cpp" and "python" to generate standalone source code, "pmml" for PMML consumers

For serving, options include the Python package itself, the C/C++ evaluation library (libcatboostmodel) and the official Java and .NET appliers, all reading .cbm with categorical support. Prediction is fast thanks to symmetric trees; batch requests rather than predicting one row at a time.

Consistency rules:

  • Feed the same columns in the same order and types as in training; categorical values as the same strings.
  • Record the feature list (model.feature_names_) and the version of CatBoost used.
  • prediction_type matters: "Probability", "Class", "RawFormulaVal" (log-odds) give different numbers.

model.shrink(ntree_end=...) cuts trees for faster, smaller models; sum_models blends several models into one.

Example

import numpy as np
import pandas as pd
from catboost import CatBoostClassifier

rng = np.random.default_rng(0)
X = pd.DataFrame({"amount": rng.uniform(1, 500, 400),
                  "country": rng.choice(["fr", "de", "us"], 400)})
y = ((X["amount"] > 250) | (X["country"] == "us")).astype(int)
model = CatBoostClassifier(iterations=100, verbose=0, random_seed=0,
                           allow_writing_files=False).fit(X, y, cat_features=["country"])

model.save_model("fraud.cbm")                              # native, keeps CTRs
loaded = CatBoostClassifier().load_model("fraud.cbm")
row = pd.DataFrame({"amount": [120.0], "country": ["us"]})
print(np.allclose(model.predict_proba(row), loaded.predict_proba(row)))   # True
print(loaded.feature_names_)                               # ['amount', 'country']

print(loaded.predict(row, prediction_type="RawFormulaVal").round(2))   # [3.83] log-odds
print(loaded.predict(row, prediction_type="Probability").round(3))     # [[0.021 0.979]]

num = CatBoostClassifier(iterations=50, verbose=0, allow_writing_files=False)
num.fit(X[["amount"]], y)
num.save_model("numeric.onnx", format="onnx")              # numeric-only for ONNX
model.shrink(ntree_end=50)
print(model.tree_count_)                                    # 50

Remember

  • save_model/load_model with .cbm keeps trees and categorical CTR tables
  • Export to json, onnx (numeric only), coreml, cpp, python as needed
  • Serve with the same columns, order and types as training
  • Be explicit about prediction_type: Probability, Class or RawFormulaVal

Watch out for

  • Exporting a model with categorical features to ONNX and expecting it to work.

Check yourself

  1. Your model uses categorical features and must run in a Java service. Which approach fits?
  2. What does prediction_type='RawFormulaVal' return for a binary classifier?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: catboost.ai/docs/en/concepts/python-reference_catboost_save_model