Skip to content

ChimeraBoostRegressor

Gradient boosted oblivious trees for regression. See the User Guide: regression basics, quantile regression, and custom objectives.

Bases: RegressorMixin, BaseEstimator

Gradient boosted oblivious trees for regression.

A scikit-learn compatible regressor supporting squared-error, absolute-error, and quantile losses, native categorical features, sample weights, bagging, and exact SHAP attributions.

Read more in the User Guide.

Parameters:

Name Type Description Default
n_estimators int

Maximum number of boosting rounds (trees). With early_stopping on, this is an upper bound and the best round is selected automatically.

2000
learning_rate float or None

Shrinkage applied to each tree. When early stopping is active, None resolves to 0.1 on data of about 15,000 training rows or more and fades to 0.07 at 5,000 or fewer; see adaptive_learning_rate.

None
depth int or None

Depth of each oblivious tree; a depth-d tree makes d splits. None resolves to 6 for squared-error/absolute-error losses, and to 4 for loss="Quantile" -- estimating an extreme conditional quantile from a leaf needs more samples per leaf than estimating a mean, so deep trees overfit the tails and the predicted quantiles collapse toward the median. Raise to 8-10 for large, interaction-heavy problems; set it explicitly to override the per-loss default.

None
l2_leaf_reg float

L2 regularization on leaf values.

1.0
max_bins int

Histogram bins per numeric feature.

128
subsample float

Row subsampling fraction per tree. Below 1.0, rows are drawn by Minimum Variance Sampling (gradient-weighted, unbiased) rather than uniformly.

1.0
colsample float or None

Fraction of features eligible for each tree. None resolves to 1.0 for a single model and to the bagged-member default 0.85 inside n_ensembles > 1 fits (see member_params_).

None
cat_smoothing float

Prior strength for ordered target statistics; higher shrinks rare categories harder toward the global mean. Must be > 0 -- it is the Bayesian pseudocount in the encoder denominator, so 0 is undefined.

1.0
cat_n_permutations int

Number of random orderings averaged by the ordered target encoder.

4
early_stopping_rounds int or None

Rounds without validation improvement before stopping. None becomes 50 when early stopping is active.

None
loss str or object

Training objective. Built in: "RMSE", "MAE", "Quantile" (level set by alpha), "Huber" (transition set by delta), and the log-link losses "Poisson", "Gamma", "Tweedie" (power set by tweedie_variance_power), whose predictions are exp(raw score) > 0. Alternatively a custom objective instance: subclass chimeraboost.CustomObjective and implement grad_hess(y, raw) and eval(y, raw, sample_weight=None).

"RMSE"
alpha float

Quantile level for loss="Quantile" (e.g. 0.9 for the 90th percentile).

0.5
delta float

Huber transition point for loss="Huber", in y units: quadratic within delta of the target, linear beyond. Fixed, not quantile-adaptive -- scale it to the data.

1.0
tweedie_variance_power float

Variance power for loss="Tweedie", strictly between 1 (Poisson) and 2 (Gamma).

1.5
eval_metric callable or None

Custom validation metric metric(y_true, y_pred[, sample_weight]) -> float scored on the validation set each round and used for early stopping and the internal model selections instead of the training loss. y_pred is the prediction (after the loss link). Lower is better, unless the callable carries a greater_is_better = True attribute -- validation_history_ then records negated values so the internal lower-is-better machinery is unchanged. The training loss still drives the gradients; the verbose per-round "train" column stays in training-loss units.

None
min_child_weight float

Minimum total hessian required on each side of a split.

1.0
thread_count int or None

numba thread count. None or -1 uses all detected cores.

None
random_state int or None

Seed for reproducibility (deterministic for a fixed thread_count).

None
verbose bool

Print per-round train and validation metrics.

False
ordered_boosting bool

Use the leave-one-out leaf training step instead of plain Newton updates.

False
cat_combinations bool or None

Add all pairwise categorical-by-categorical features. None enables them automatically only when the data is entirely categorical (where the interaction columns help without crowding out numeric splits); set True/False to force it on/off.

None
cat_count_features bool

Add, for every categorical column with at least 256 training categories, a numeric column holding the category's training-row count (the weight total when sample_weight is given; unseen categories at predict time read 0). A rarity signal for high-cardinality columns; ignored by the cross-feature and linear-leaf machinery. Only columns with at least 256 training categories get one, so data without such a column fits exactly as with False. Set False to turn it off.

True
leaf_estimation_iterations int

Newton refinement steps per leaf.

1
linear_leaves bool or None

Fit a ridge linear model per leaf over the numeric split features instead of a constant value, adding local slope where step leaves underfit. Leaves with too few rows fall back to a constant. Not available with MAE or quantile loss. None (the default) = validation-selected: both variants are fit and the one with the lower validation loss is kept (~2x fit time; requires an early-stopping split or eval_set, RMSE loss, and >= 1000 rows -- otherwise constant leaves are used). Set True/False to force one variant and skip the double fit.

None
linear_lambda float

Ridge penalty on per-leaf linear slopes; larger is closer to a constant.

1.0
quantize_gradients bool

Run the split search on quantized gradients/hessians packed into integer histograms (LightGBM-style quantized training, ~15-bit): ~20-25% faster fits at benchmark-flat accuracy. Leaf values always use the exact float gradients; the rounding noise touches only split selection and is deterministic for a fixed random_state. False restores exact float64 histograms.

True
cross_features (bool, always or None)

Numeric interaction columns. None (the default) and True refit with difference and product columns for the pairs of the top numeric features of the base fit and keep whichever model reaches the lower validation loss (cross_features_selected_ records the outcome, cross_pairs_ the columns kept); applies to RMSE loss with >= 2000 rows and >= 2 numeric features, and is skipped otherwise. False turns it off. Oblivious trees can only staircase a numeric interaction such as x_i < x_j; a cross column makes it a single split. Costs up to ~2x fit time when the refit runs. "always" skips the validation race and keeps the cross columns unconditionally (a narrower top-4 block, ranked by a short importance probe): one full fit instead of the race, for the fast one-fit operating point. quality=1 pins this on the regressor. Same applicability gates; inert where they fail.

None
cross_top_columns int or None

Cap on how many candidate cross columns the augmented fit carries. None (the default) carries all of them. An integer k keeps only the k candidates whose values correlate most strongly with the base fit's validation residuals, which cuts the augmented fit's per-round cost; the validation race still decides whether the surviving block is used at all (under cross_features="always" it trims the forced block instead). Inert wherever cross features do not apply.

None
selection_rounds int or None

Round budget for the internal selection fits. The constant/linear-leaf variants and the pre-cross base fit run at most this many rounds (auditions, judged on their best validation loss within the budget); the winning candidate continues to full early stopping, and the audition winner is refit in full only when the cross-augmented model loses or cross features do not apply. An audition that early-stops before the budget is the full fit already (no extra cost). None runs every variant to full early stopping instead (the pre-0.15 behavior, ~1.5x slower fits); an audition can occasionally pick a different variant than full fits would.

100
early_stopping bool

Hold out a validation split and stop when its score stops improving.

True
validation_fraction float

Validation fraction used when early_stopping is on and no eval_set is passed to fit.

0.2
n_ensembles int or None

Number of bagged members. None or 1 trains a single model; >= 2 averages independent members, each fit on its own random row sample (max_samples, without replacement by default).

None
ensemble_n_jobs int

Worker processes fitting ensemble members concurrently, each on an equal share of the thread budget (same total cores as a single fit; models are identical either way, wall-clock 1.2-2x faster). -1 sizes the pool from the budget, capped at n_ensembles; 1 fits members sequentially, each with the full budget.

-1
max_samples float

Fraction of rows each ensemble member trains on, drawn WITHOUT replacement ("subagging"). The default 0.8 beats the classic bootstrap on strength and fit time (a full-size bootstrap holds only ~0.63n unique rows at n rows of compute). 1.0 restores the classic full-size with-replacement bootstrap. Unsampled rows are each member's early-stopping eval set either way. When groups is passed to fit, the draw is over whole groups instead of rows (a cluster bootstrap at 1.0), so each member's eval set is made of groups it never trained on.

0.8
refit_full (replay, bool)

After the automatic early-stopping split has chosen the tree budget (and model selection / calibration have used it), retrain the winning configuration on 100% of the rows -- rounds scaled by the train-size ratio, learning rate pinned -- so the final model does not pay the holdout data tax. Only affects fits that used the automatic split (an explicit eval_set or early_stopping=False is unchanged); loss="Quantile" ignores it to keep its conformal holdout honest. validation_history_ keeps the early-stopped fit's curve. Costs one extra refit; on by default since 0.25.0, as the strongest single-model setting measured (benchmarks/SELECT_PLAN.md). Set False, or quality=2, for the faster pre-0.25 behaviour.

The default is "replay", which gets the same thing for about two thirds of the cost. Growing trees is 83-85% of a fit and is a SEARCH; "replay" reuses the winner's tree structures and refits only the leaf values against full-data gradients, so the held-out rows still shape every leaf value while the split search is not paid for twice.

Measured against True at 3 seeds: on Grinsztajn accuracy was flat (27W-32L over 59 datasets, mean +0.005%) and fit time fell 34% on all 59; on high-cardinality categorical data it ran slightly behind (mean -0.256%) for 17% less fit time. Pass True for the from-scratch refit -- marginally stronger on high-card data, and the setting benchmarked in REFIT_PLAN.md. Multiclass ignores "replay" and always uses the from-scratch refit (benchmarks/REPLAY_PLAN.md).

"replay"
refit_members bool

The bagged analogue of refit_full, and off by default. A bag member trains on max_samples of the rows and early-stops on its out-of-bag complement, so its leaf values never see the rows it stopped on -- the full-data refit that helps a single model has never fired for it. With True each member replays its own tree structure against gradients from every row once early stopping is done. Only the leaf values move; the splits stay exactly as that member's own sample grew them, which is where a bag's diversity actually lives.

Measured on the decision suites, an 8-member bag improves in every stratum, with perfect sweeps on the small-data ones (Grinsztajn at a quarter of the rows 12W-0L, +1.206%), for about 10-17% more fit time. Because each member is individually stronger you can also spend the gain on fewer members: 5 refit members beat a plain 8-member bag on accuracy while fitting about 20% faster. Ignored unless the fit is bagged (n_ensembles >= 2), and ignored for multiclass, where a member would need a full refit rather than a cheap structure replay.

False
adaptive_learning_rate bool

Let the auto learning_rate depend on how much data it has, instead of being size-blind: a linear fade from 0.07 at 5,000 training rows or fewer up to the historical flat 0.1 at 15,000 or more. Small data is where a lower rate pays, and it is also where the extra trees it needs are cheap. Default-on since 0.30.0; above the upper threshold it is a no-op and the model is byte-identical to earlier versions, so only small-data fits move. Set False for the flat 0.1 everywhere.

Measured on the decision suites, the mean is positive in six of seven strata, with sign-test passes at a quarter of the rows on both Grinsztajn (9W-3L) and high-card (3W-0L) and no losses at all on high-card at full size (6W-0L). Gains are individually small (medians of +0.13% to +0.31%) and cost 1.09x to 1.31x fit time on the sizes it touches. Only consulted when learning_rate is None and early stopping is on -- without early stopping the rate already scales with the round budget. Bagged fits (n_ensembles >= 2) are unaffected too, since their members already carry an explicit member learning rate.

True
cat_features list of int or str, or None

Default categorical columns, given as integer positions and/or column names (names resolved against the DataFrame at fit). Used when fit is called without its own cat_features (the fit argument overrides). Provided as a constructor argument so GridSearchCV/Pipeline can carry it.

None
random_effects bool

Fit a random intercept per group: the model becomes F(X) + b_g, trees for the global part plus one shrunk intercept per group from fit(..., groups=...). For grouped data (users, stores, clinics, panel IDs) where a plain categorical burns tree depth isolating IDs. Shrinkage is empirical-Bayes under a REML variance ratio, so small groups pool toward zero while large groups stand on their own means. predict takes the row groups and adds the fitted intercepts; unseen groups get exactly 0. Slice 1: loss="RMSE" single models only (not n_ensembles > 1).

False
store_training_data bool

Keep the rows the final booster's leaves came from, so refresh can fold in new rows later without a from-scratch refit. What is stored is compact, not raw X: plain numeric columns as binner bins, the raw values of only the cross-feature parent columns, categoricals as integer codes plus their per-column categories, the target as the booster saw it, and the raw sample weights. The store rides along in pickles and grows with every refresh call. Roughly 3x smaller than float64 X for numeric data when cross features engage, about 6.5x when they do not; far smaller for object-dtype categoricals.

False

Attributes:

Name Type Description
feature_importances_ ndarray of shape (n_features,)

Split-gain importance per input feature, normalized to sum to 1.

best_iteration_ int

Number of trees retained after early stopping.

expected_value_ float

SHAP baseline in the same additive space as shap_values. For the identity-link losses it is the mean prediction over the background (with the conformal quantile offset folded in when present); for the log-link losses and custom losses with a non-identity transform it is the mean raw score over the background. Set after calling shap_values.

estimators_ list or None

Fitted members when n_ensembles > 1, otherwise None.

member_params_ dict

Bagged-mode member defaults that were auto-applied (params the user left on auto resolve to tuned member values inside a bag; explicit values always win). Set only when n_ensembles > 1.

quantile_offset_ float

Split-conformal correction added to every prediction when loss="Quantile" and a validation split was available: the conformal order statistic of the validation residuals, restoring the nominal coverage that learning-rate shrinkage of the per-leaf quantile steps otherwise starves. 0.0 for other losses or without a validation set.

linear_leaves_selected_ bool or None

With linear_leaves=None, whether the linear-leaf variant won the validation selection. None when no selection took place.

group_intercepts_ ndarray of shape (n_groups,) or None

Fitted random intercepts in group_labels_ order. None unless fit with random_effects=True.

group_labels_ ndarray of shape (n_groups,) or None

Fit-time group labels the intercepts align with. None unless fit with random_effects=True.

group_ratio_ float or None

Fitted noise-to-group variance ratio (inf means no group signal was found). None unless fit with random_effects=True.

n_samples_trained_ int

Number of rows the final booster's leaves came from: all rows when the full-data refit ran, else the post-split training rows. Grown by refresh.

Source code in chimeraboost/sklearn_api.py
def __init__(self, n_estimators=2000, learning_rate=None, depth=None,
             l2_leaf_reg=1.0, max_bins=128, subsample=1.0, colsample=None,
             cat_smoothing=1.0, cat_n_permutations=4,
             early_stopping_rounds=None,
             loss="RMSE", alpha=0.5, min_child_weight=1.0, thread_count=None,
             random_state=None, verbose=False, ordered_boosting=False,
             cat_combinations=None, cat_count_features=True,
             leaf_estimation_iterations=1,
             linear_leaves=None, linear_lambda=1.0, cross_features=None,
             cross_top_columns=None, selection_rounds=100,
             early_stopping=True, validation_fraction=0.2,
             n_ensembles=None, ensemble_n_jobs=-1, max_samples=0.8,
             cat_features=None, quantize_gradients=True,
             eval_metric=None, delta=1.0, tweedie_variance_power=1.5,
             refit_full="replay", refit_members=False, quality=None,
             adaptive_learning_rate=True, random_effects=False,
             store_training_data=False):
    self.n_estimators = n_estimators
    self.learning_rate = learning_rate
    self.depth = depth
    self.l2_leaf_reg = l2_leaf_reg
    self.max_bins = max_bins
    self.subsample = subsample
    self.colsample = colsample
    self.cat_smoothing = cat_smoothing
    self.cat_n_permutations = cat_n_permutations
    self.early_stopping_rounds = early_stopping_rounds
    self.cat_features = cat_features
    self.loss = loss
    self.alpha = alpha
    self.delta = delta
    self.tweedie_variance_power = tweedie_variance_power
    self.eval_metric = eval_metric
    self.min_child_weight = min_child_weight
    self.thread_count = thread_count
    self.random_state = random_state
    self.verbose = verbose
    self.ordered_boosting = ordered_boosting
    self.cat_combinations = cat_combinations
    self.cat_count_features = cat_count_features
    self.leaf_estimation_iterations = leaf_estimation_iterations
    self.linear_leaves = linear_leaves
    self.linear_lambda = linear_lambda
    self.cross_features = cross_features
    self.cross_top_columns = cross_top_columns
    self.selection_rounds = selection_rounds
    self.early_stopping = early_stopping
    self.validation_fraction = validation_fraction
    self.n_ensembles = n_ensembles
    self.ensemble_n_jobs = ensemble_n_jobs
    self.max_samples = max_samples
    self.quantize_gradients = quantize_gradients
    self.refit_full = refit_full
    self.refit_members = refit_members
    self.quality = quality
    # Size fade for the auto learning rate, default-on since 0.30.0; only
    # consulted when learning_rate is None. False == the historical flat 0.1.
    self.adaptive_learning_rate = adaptive_learning_rate
    self.random_effects = random_effects
    self.store_training_data = store_training_data

validation_history_ property

validation_history_

Per-round validation score recorded during fit.

The training loss (RMSE space for regression), or the custom eval_metric when one was set -- negated if the metric declares greater_is_better = True, so lower is always better here.

A list as long as the number of rounds run. Empty when no eval_set or early-stopping split was available; a list of the members' histories for a bagged model (n_ensembles > 1).

fit

fit(
    X,
    y,
    cat_features=None,
    eval_set=None,
    groups=None,
    sample_weight=None,
    callbacks=None,
)

Fit the model.

Parameters:

Name Type Description Default
X array - like

Training data.

required
y array - like

Training data.

required
cat_features list of int or str, or None

Columns to treat as categoricals, given as integer positions and/or column names (names resolved against the DataFrame). Falls back to the cat_features constructor argument when not given here; passing it here overrides the constructor value. (The constructor form lets GridSearchCV/Pipeline carry it, which a fit-only kwarg can't.)

None
eval_set (X_val, y_val) tuple or None

Explicit validation set. When provided, automatic splitting is skipped regardless of the early_stopping setting.

None
groups array-like of shape (n_samples,) or None

Group labels for the samples (e.g. df['subject_id']). With the default random_effects=False, groups shape the automatic validation split: each group stays intact across the train/validation boundary (GroupShuffleSplit). With random_effects=True the split is random instead, and the groups get one shrunk intercept each, added to predictions by predict(X, groups=...).

None
sample_weight array-like of shape (n_samples,) or None

Per-sample weights, normalized to mean 1 internally. Applied throughout: the gradient/leaf fit, the categorical target encoder, the quantile bin borders, and the early-stopping metric on an automatically split (or bagged out-of-bag) validation set, so a zero-weight row never influences the model. An explicitly passed eval_set carries no weights and is scored unweighted.

None
callbacks callable or list of callable, or None

Per-round fit hooks cb(iteration, train_loss, val_loss, model); a callback returning True requests an early stop. Used for live validation-curve capture and instrumentation. Not supported with n_ensembles > 1 (members fit in parallel worker processes).

None
Source code in chimeraboost/sklearn_api.py
def fit(self, X, y, cat_features=None, eval_set=None, groups=None,
        sample_weight=None, callbacks=None):
    """Fit the model.

    Parameters
    ----------
    X, y : array-like
        Training data.
    cat_features : list of int or str, or None
        Columns to treat as categoricals, given as integer positions and/or
        column names (names resolved against the DataFrame). Falls back to the
        ``cat_features`` constructor argument when not given here; passing it
        here overrides the constructor value. (The constructor form lets
        ``GridSearchCV``/``Pipeline`` carry it, which a fit-only kwarg can't.)
    eval_set : (X_val, y_val) tuple or None
        Explicit validation set. When provided, automatic splitting is
        skipped regardless of the *early_stopping* setting.
    groups : array-like of shape (n_samples,) or None
        Group labels for the samples (e.g. ``df['subject_id']``). With
        the default ``random_effects=False``, groups shape the
        automatic validation split: each group stays intact across
        the train/validation boundary (``GroupShuffleSplit``). With
        ``random_effects=True`` the split is random instead, and the
        groups get one shrunk intercept each, added to predictions
        by ``predict(X, groups=...)``.
    sample_weight : array-like of shape (n_samples,) or None
        Per-sample weights, normalized to mean 1 internally. Applied
        throughout: the gradient/leaf fit, the categorical target encoder,
        the quantile bin borders, and the early-stopping metric on an
        automatically split (or bagged out-of-bag) validation set, so a
        zero-weight row never influences the model. An explicitly passed
        ``eval_set`` carries no weights and is scored unweighted.
    callbacks : callable or list of callable, or None
        Per-round fit hooks ``cb(iteration, train_loss, val_loss, model)``;
        a callback returning True requests an early stop. Used for live
        validation-curve capture and instrumentation. Not supported with
        ``n_ensembles > 1`` (members fit in parallel worker processes).
    """
    cat_features = _resolve_cat_features(self, cat_features)
    cat_features = _resolve_cat_feature_names(cat_features, X)
    _validate_hyperparams(self)
    y = _validate_fit_input(self, X, y, cat_features, sample_weight,
                            classification=False)
    # Cached shap_importances describe the previous fit; drop them.
    self._shap_importances_cache_ = None
    # Random-effects state from any previous fit is stale now.
    self.group_intercepts_ = None
    self.group_labels_ = None
    self.group_ratio_ = None

    if eval_set is not None:
        _check_eval_set(eval_set, self.n_features_in_)

        # A reordered or renamed eval DataFrame is consumed positionally and
        # silently wrecks early stopping, and everything calibrated on the
        # holdout. Bag members skip this: their eval sets are built
        # internally from already-validated parent input.
        if not getattr(self, "_is_bag_member", False):
            _check_feature_names_match(self, eval_set[0])

    with _quality_applied(self):
        _check_store_fit(self)
        if self.random_effects:
            if self.loss != "RMSE":
                raise ValueError(
                    "random_effects=True is only supported with "
                    f"loss='RMSE' in slice 1; got {self.loss!r}.")
            if groups is None:
                raise ValueError(
                    "random_effects=True needs fit(..., groups=...) -- "
                    "there is nothing to fit intercepts for without "
                    "group labels.")
            if self.n_ensembles and self.n_ensembles > 1:
                raise ValueError(
                    "random_effects=True is not supported with "
                    "n_ensembles > 1 in slice 1; fit a single model.")
        if self.n_ensembles and self.n_ensembles > 1:
            if callbacks is not None:
                raise ValueError(
                    "callbacks are not supported with n_ensembles > 1.")
            self.estimators_ = _fit_bagged(self, X, y, cat_features,
                                           eval_set, groups, sample_weight)
            return self

        self.estimators_ = None
        return self._fit_single(X, y, cat_features, eval_set, groups,
                                sample_weight, callbacks)

refresh

refresh(X, y, sample_weight=None)

Fold new rows into this fitted model without a from-scratch refit.

Appends (X, y[, sample_weight]) to the rows stored at fit time (store_training_data=True), rebuilds a raw-equivalent training matrix from the store, and replays the FITTED booster's configuration on it -- the same structure-transfer replay the default full-data refit uses. Every tree's structure, the round count and the learning rate stay pinned; leaf values and linear-leaf coefficients are refit against the combined gradients.

refresh replays the fitted configuration and ignores any set_params made after fit. The binner borders, the count and cross selections, the validation history and the fitted selections are unchanged; n_samples_trained_ grows by the number of new rows.

Parameters:

Name Type Description Default
X array - like

New rows with the same features the model was fit on. Zero rows are allowed, in which case predictions are unchanged.

required
y array - like

New rows with the same features the model was fit on. Zero rows are allowed, in which case predictions are unchanged.

required
sample_weight array-like of shape (n_samples,) or None

Weights for the new rows, in the same units as the fit weights. Required when the model was fit with weights, rejected when it was not.

None

Returns:

Type Description
self
Source code in chimeraboost/sklearn_api.py
def refresh(self, X, y, sample_weight=None):
    """Fold new rows into this fitted model without a from-scratch refit.

    Appends ``(X, y[, sample_weight])`` to the rows stored at fit time
    (``store_training_data=True``), rebuilds a raw-equivalent training
    matrix from the store, and replays the FITTED booster's configuration
    on it -- the same structure-transfer replay the default full-data
    refit uses. Every tree's structure, the round count and the learning
    rate stay pinned; leaf values and linear-leaf coefficients are refit
    against the combined gradients.

    ``refresh`` replays the fitted configuration and ignores any
    ``set_params`` made after fit. The binner borders, the count and
    cross selections, the validation history and the fitted selections
    are unchanged; ``n_samples_trained_`` grows by the number of new
    rows.

    Parameters
    ----------
    X, y : array-like
        New rows with the same features the model was fit on. Zero rows
        are allowed, in which case predictions are unchanged.
    sample_weight : array-like of shape (n_samples,) or None
        Weights for the new rows, in the same units as the fit weights.
        Required when the model was fit with weights, rejected when it
        was not.

    Returns
    -------
    self
    """
    return _refresh_single(self, X, y, sample_weight,
                           classification=False)

predict_raw

predict_raw(X)

Raw additive score before the loss link and conformal quantile offset.

For the identity-link losses (RMSE/MAE/Huber) this equals predict; for loss="Quantile" it is predict minus the fitted quantile_offset_. For the log-link losses (Poisson/Gamma/Tweedie) and custom losses with a non-identity transform it is the pre-link score -- the space shap_values reconstructs exactly. Averaged across the bag when n_ensembles > 1, mirroring predict. With random_effects=True this stays trees-only -- group intercepts are added by predict only, so SHAP rows still sum here exactly.

Source code in chimeraboost/sklearn_api.py
def predict_raw(self, X):
    """Raw additive score before the loss link and conformal quantile offset.

    For the identity-link losses (RMSE/MAE/Huber) this equals ``predict``;
    for ``loss="Quantile"`` it is ``predict`` minus the fitted
    ``quantile_offset_``. For the log-link losses (Poisson/Gamma/Tweedie)
    and custom losses with a non-identity ``transform`` it is the pre-link
    score -- the space ``shap_values`` reconstructs exactly. Averaged across
    the bag when ``n_ensembles > 1``, mirroring ``predict``. With
    ``random_effects=True`` this stays trees-only -- group intercepts are
    added by ``predict`` only, so SHAP rows still sum here exactly.
    """
    Xv = _check_predict_input(self, X)
    X = X if Xv is None else Xv

    if self.estimators_ is not None:
        with _thread_limit(self.thread_count):
            Xc, ctx = _bag_predict_context(self, X)
            return np.mean([m.model_.predict_raw(Xc, ctx)
                            for m in self.estimators_], axis=0)
    return self.model_.predict_raw(X)

predict

predict(X, groups=None)

Predict regression targets.

groups (labels matching fit's) adds the fitted random intercept per row; unseen labels get exactly 0. None returns the trees-only prediction even for a random-effects model.

Source code in chimeraboost/sklearn_api.py
def predict(self, X, groups=None):
    """Predict regression targets.

    ``groups`` (labels matching ``fit``'s) adds the fitted random
    intercept per row; unseen labels get exactly 0. ``None`` returns the
    trees-only prediction even for a random-effects model.
    """
    Xv = _check_predict_input(self, X)
    X = X if Xv is None else Xv

    if self.estimators_ is not None:
        # One shared conversion and factorization cache for the whole bag,
        # and one thread-limit switch (members' re-entries are no-ops). Each
        # member applies its own link and conformal offset; the bag
        # prediction is the mean of the member predictions.
        with _thread_limit(self.thread_count):
            Xc, ctx = _bag_predict_context(self, X)
            base = np.mean(
                [m._transform_raw(m.model_.predict_raw(Xc, ctx))
                 + m.quantile_offset_
                 for m in self.estimators_], axis=0)
    else:
        base = (self._transform_raw(self.model_.predict_raw(X))
                + self.quantile_offset_)
    off = self._group_offsets(groups, base.shape[0])
    return base if off is None else base + off

staged_predict

staged_predict(X, groups=None)

Yield the prediction after each successive tree.

The conformal quantile offset is a post-fit constant and is included in every stage, so the final stage equals predict. groups adds the fitted random intercepts (constant across stages) the same way.

Source code in chimeraboost/sklearn_api.py
def staged_predict(self, X, groups=None):
    """Yield the prediction after each successive tree.

    The conformal quantile offset is a post-fit constant and is included in
    every stage, so the final stage equals ``predict``. ``groups`` adds the
    fitted random intercepts (constant across stages) the same way.
    """
    Xv = _check_predict_input(self, X)
    X = X if Xv is None else Xv

    if self.estimators_ is not None:
        raise NotImplementedError("staged_predict is not defined for a "
                                  "bagged ensemble (n_ensembles > 1).")

    off = None
    started = False
    for staged in self.model_.staged_predict_raw(X):
        if not started:
            # Sized from the first stage's row count.
            off = self._group_offsets(groups, staged.shape[0])
            started = True
        base = self._transform_raw(staged) + self.quantile_offset_
        yield base if off is None else base + off

report

report(
    X, y, sample_weight=None, baseline=None, groups=None
)

Score this model on (X, y): RMSE, MAE and the R2 skill score.

Returns the chimeraboost.metrics.regression_report dict; chimeraboost.metrics.format_report prints it. baseline sets what the skill score is measured against -- pass the training targets to score against the mean the model actually had, rather than the hindsight mean of y. groups adds random intercepts before scoring; without it a random-effects model reports F-only.

Source code in chimeraboost/sklearn_api.py
def report(self, X, y, sample_weight=None, baseline=None, groups=None):
    """Score this model on ``(X, y)``: RMSE, MAE and the R2 skill score.

    Returns the `chimeraboost.metrics.regression_report` dict;
    `chimeraboost.metrics.format_report` prints it. ``baseline`` sets what
    the skill score is measured against -- pass the training targets to
    score against the mean the model actually had, rather than the
    hindsight mean of ``y``. ``groups`` adds random intercepts before
    scoring; without it a random-effects model reports F-only.
    """
    from . import metrics
    return metrics.regression_report(y, self.predict(X, groups=groups),
                                     sample_weight, baseline)

shap_values

shap_values(X, X_background=None)

Exact interventional TreeSHAP contributions in the model's additive space.

Returns an array of shape (n_samples, n_features) whose rows sum to the model's additive score minus expected_value_. For the identity- link losses this is predict(X) - expected_value_; for loss="Quantile" the fitted conformal offset is folded into expected_value_ too, so the rows still sum to predict(X) - expected_value_. For the log-link losses (Poisson/Gamma/Tweedie) and custom losses with a non-identity transform, attributions stay in raw (link) space and rows sum to predict_raw(X) - expected_value_. expected_value_ (set as an attribute by this call) is the mean additive score over the background. Each entry is a feature's signed additive contribution; linear-leaf slopes are included exactly. Averaged across the bag when n_ensembles > 1 -- the bag prediction is the members' mean, so the averaged attribution stays exact. X_background overrides the reference distribution (default: a sample of the training data).

Source code in chimeraboost/sklearn_api.py
def shap_values(self, X, X_background=None):
    """Exact interventional TreeSHAP contributions in the model's additive space.

    Returns an array of shape ``(n_samples, n_features)`` whose rows sum to
    the model's additive score minus ``expected_value_``. For the identity-
    link losses this is ``predict(X) - expected_value_``; for
    ``loss="Quantile"`` the fitted conformal offset is folded into
    ``expected_value_`` too, so the rows still sum to ``predict(X) -
    expected_value_``. For the log-link losses (Poisson/Gamma/Tweedie) and
    custom losses with a non-identity ``transform``, attributions stay in raw
    (link) space and rows sum to ``predict_raw(X) - expected_value_``.
    ``expected_value_`` (set as an attribute by this call) is the mean
    additive score over the background. Each entry is a feature's signed
    additive contribution; linear-leaf slopes are included exactly. Averaged
    across the bag when ``n_ensembles > 1`` -- the bag prediction is the
    members' mean, so the averaged attribution stays exact. ``X_background``
    overrides the reference distribution (default: a sample of the training
    data).
    """
    Xv = _check_predict_input(self, X)
    X = X if Xv is None else Xv

    if X_background is not None:
        # The background matrix is consumed positionally too; a reordered
        # DataFrame would silently skew every baseline.
        bg = _check_predict_input(self, X_background)
        X_background = X_background if bg is None else bg

    if self.estimators_ is not None:
        out = [m.model_.shap_values(X, background=X_background)
               for m in self.estimators_]

        # Fold each member's conformal quantile offset into the baseline so
        # rows still sum to predict(X) - expected_value_.
        self.expected_value_ = float(np.mean(
            [b + m.quantile_offset_ for m, (_, b) in zip(self.estimators_, out)]))
        return np.mean([p for p, _ in out], axis=0)

    phi, base = self.model_.shap_values(X, background=X_background)
    # The conformal quantile offset is a constant shift; it belongs to the
    # baseline, keeping rows summing to predict(X) - expected_value_.
    self.expected_value_ = base + self.quantile_offset_
    return phi

shap_importances

shap_importances(
    X, feature_names=None, n_features=None, prettified=False
)

Global SHAP importance: mean(abs(shap_values(X))) per feature.

Returns a structured (feature, importance) array sorted descending, or a {feature: importance} dict when prettified=True (CatBoost's flag). feature holds feature_names when given, else the names captured from a DataFrame at fit, else column indices. n_features truncates to the top N.

The expensive SHAP pass is cached on the instance, keyed by the data's content, so repeated calls on the same X -- including with different formatting options -- reuse it. The cache is dropped on refit. See shap_values for the attribution space and cost.

Source code in chimeraboost/sklearn_api.py
def shap_importances(self, X, feature_names=None, n_features=None,
                     prettified=False):
    """Global SHAP importance: ``mean(abs(shap_values(X)))`` per feature.

    Returns a structured ``(feature, importance)`` array sorted descending,
    or a ``{feature: importance}`` dict when ``prettified=True``
    (CatBoost's flag). ``feature`` holds ``feature_names`` when given,
    else the names captured from a DataFrame at fit, else column indices.
    ``n_features`` truncates to the top N.

    The expensive SHAP pass is cached on the instance, keyed by the data's
    content, so repeated calls on the same X -- including with different
    formatting options -- reuse it. The cache is dropped on refit. See
    ``shap_values`` for the attribution space and cost.
    """
    return _shap_importances(self, X, feature_names, n_features,
                             prettified)