CatBoost
CatBoost is Yandex's open-source gradient boosting library that encodes categorical features with ordered target statistics and grows symmetric trees.
CatBoost is an open-source gradient boosting library for decision trees, developed by Yandex and released in 2017. Its name comes from "categorical boosting": it accepts categorical columns such as city, product ID, or device type as raw strings and converts them to numbers internally, so tabular data needs no manual one-hot or target encoding before training. Two ideas from its NeurIPS 2018 paper, ordered target statistics and ordered boosting, keep each training row's own label out of the numbers used to fit it, a leak that biases both plain target encoding and standard boosting. CatBoost trains on CPUs and GPUs, ships Python, R, and command-line interfaces, and handles classification, regression, and ranking.
How CatBoost Encodes Categorical Features#
One-hot encoding creates one column per category, which becomes unwieldy for a feature with thousands of values such as a merchant or user ID. Target encoding replaces each category with the average label of its rows, which is compact but leaks the answer: a row's own label is part of the number that describes it, so the model learns a shortcut that fails on new data. This is a form of data leakage that shows up as overfitting, worst for rare categories.
CatBoost's ordered target statistics fix this with a random permutation of the training rows. Each row's category is encoded from the labels of only the rows that come before it in the permutation, smoothed toward a prior, so no row ever sees its own label. CatBoost repeats this over several permutations, one-hot encodes features with very few distinct values, and greedily builds combinations of categorical features, such as city crossed with device type, as new features during training.
In the CatBoost Python package, categorical columns are passed by name through cat_features. This example gives each of 50 subscription plans its own hidden churn rate and checks whether the model recovers the rates from raw plan names:
import numpy as np
import pandas as pd
from catboost import CatBoostClassifier
# Synthetic churn data: each of 50 plans has its own hidden churn rate
rng = np.random.default_rng(0)
rates = rng.uniform(0.05, 0.6, size=50)
plan_ids = rng.integers(0, 50, size=5000)
X = pd.DataFrame({"plan": [f"plan_{i}" for i in plan_ids], "tenure_months": rng.integers(1, 60, size=5000)})
y = rng.random(5000) < rates[plan_ids]
# Raw strings go in directly; CatBoost encodes them with ordered target statistics
model = CatBoostClassifier(iterations=200, depth=4, verbose=0, random_seed=0)
model.fit(X, y, cat_features=["plan"])
# Compare true and predicted churn for the safest and riskiest plans
lo, hi = rates.argmin(), rates.argmax()
probe = pd.DataFrame({"plan": [f"plan_{lo}", f"plan_{hi}"], "tenure_months": [30, 30]})
print("True churn rates: ", rates[[lo, hi]].round(2))
print("Predicted churn rates:", model.predict_proba(probe)[:, 1].round(2))The script prints true rates of 0.05 and 0.60 and predicted rates of 0.06 and 0.59. The model recovered each plan's churn rate from the raw string column, with only about 100 training rows per plan.
Ordered Boosting and Symmetric Trees#
Standard gradient boosting computes each new tree's targets, the gradients of the loss, on the same rows the earlier trees were fit to, which biases those gradients, an effect the CatBoost authors call prediction shift. Ordered boosting applies the permutation trick again: the gradient for each row comes from a model trained only on rows earlier in the permutation. It is a training option, boosting_type="Ordered", that usually improves quality on small datasets at the cost of speed. The CPU default is the classic "Plain" scheme, and GPU training defaults to "Ordered" for datasets of up to 50,000 rows except in multiclass mode.
By default CatBoost grows symmetric, or oblivious, trees, in which every node at the same depth uses the same split condition. A tree of depth 6, the default, is therefore just six yes-or-no tests whose answers form a 6-bit index into 64 leaves, which makes prediction fast and restricts each tree's complexity, a form of regularization. The grow_policy parameter switches to depthwise or leaf-wise growth when a dataset needs less constrained trees.
Real-World Applications#
- Credit risk: Lenders combine categorical applicant fields such as occupation, region, and loan purpose with numeric income and debt figures to predict default, without one-hot encoding hundreds of occupation codes.
- Ranking and recommendations: CatBoost provides ranking losses such as YetiRank, used to order search results or products by predicted relevance from user, item, and context features in a recommendation system.
- Property valuation: A custom-trained YOLO26 detector can count amenities such as pools or solar panels in listing photos, and those counts enter a CatBoost price model as numeric columns beside categorical ones like neighborhood and property type.
CatBoost vs. XGBoost and LightGBM#
All three libraries build an ensemble of trees sequentially, each tree correcting the errors of the trees before it, which sets them apart from random forest and its independently trained trees.
- XGBoost: Grows trees level by level by default and adds L1 and L2 regularization to its objective. Native categorical support arrived in later versions, and many pipelines still encode categories before training.
- LightGBM: Grows trees leaf-wise, splitting whichever leaf reduces the loss most, and bins features into histograms, which makes it fast on large datasets. It also accepts integer-coded categorical columns natively.
- CatBoost: Builds symmetric trees, encodes categories with ordered target statistics, and gives strong results before any hyperparameter tuning. Its defaults are 1,000 trees of depth 6, with the learning rate chosen automatically from the iteration count for log loss, multiclass, and RMSE objectives.










