CatBoost with the scikit-learn API
This deterministic synthetic example makes categorical handling visible without a network download. It uses CatBoost's scikit-learn-compatible estimator, while cat_features and early stopping remain CatBoost-specific.
1. Create mixed-type data and three partitions
import numpy as np
import pandas as pd
from catboost import CatBoostClassifier
from sklearn.metrics import brier_score_loss, log_loss, roc_auc_score
from sklearn.model_selection import train_test_split
rng = np.random.default_rng(42)
sample_count = 360
data = pd.DataFrame(
{
"age": rng.integers(18, 76, size=sample_count),
"income": rng.normal(55_000, 14_000, size=sample_count).round(0),
"region": rng.choice(["north", "south", "west"], size=sample_count),
"channel": rng.choice(["web", "store", "partner"], size=sample_count),
}
)
raw_score = (
-2.2
+ 0.035 * (data["age"] - 40)
+ 0.000025 * (data["income"] - 50_000)
+ 0.8 * (data["region"] == "north")
+ 0.6 * (data["channel"] == "web")
)
probability = 1.0 / (1.0 + np.exp(-raw_score))
target = (rng.random(sample_count) < probability).astype(int)
X_development, X_test, y_development, y_test = train_test_split(
data,
target,
test_size=0.20,
random_state=42,
stratify=target,
)
X_train, X_valid, y_train, y_valid = train_test_split(
X_development,
y_development,
test_size=0.20,
random_state=42,
stratify=y_development,
)
model = CatBoostClassifier(
loss_function="Logloss",
eval_metric="Logloss",
iterations=400,
learning_rate=0.05,
depth=5,
l2_leaf_reg=3.0,
random_seed=42,
thread_count=1,
allow_writing_files=False,
verbose=False,
)
model.fit(
X_train,
y_train,
cat_features=["region", "channel"],
eval_set=(X_valid, y_valid),
early_stopping_rounds=25,
use_best_model=True,
verbose=False,
)
test_probability = model.predict_proba(X_test)[:, 1]
print("Best iteration:", model.best_iteration_)
print("Test ROC AUC:", round(roc_auc_score(y_test, test_probability), 3))
print("Test log loss:", round(log_loss(y_test, test_probability), 3))
print("Test Brier score:", round(brier_score_loss(y_test, test_probability), 3))
assert X_train.shape[0] + X_valid.shape[0] + X_test.shape[0] == sample_count
assert test_probability.shape == y_test.shape
assert 0 <= model.best_iteration_ < model.tree_count_
2. What CatBoost learns
The strings in region and channel are declared categorical. CatBoost can form ordered category statistics without a global target encoder. This reduces a specific leakage mechanism; it does not excuse incorrect time/group splits or target-derived fields.
eval_set selects the iteration, so it is part of training. use_best_model=True retains the best prefix of trees. The isolated test set is used only for the three final metrics.
3. Tuning and evaluation
If depth, regularization, or category settings are tuned, conduct that search inside training-only folds. CatBoost's category processing must be refitted in each fold. ROC AUC measures ranking; log loss and Brier score assess probabilities. Choose a decision threshold or calibration method on validation data, not the test set.
4. Deployment
Store feature names/order, cat_features, category and missing-value conventions, class order, best_iteration_, model artifact, and CatBoost version. Test unknown categories and malformed schemas before serving.