cleverly.SuperLearner#

class cleverly.SuperLearner(library: Sequence[Any] | None = None, *, task: Literal['regression', 'classification'] | None = None, meta_learner: Literal['auto', 'nnls', 'nnloglik', 'discrete'] = 'auto', n_folds: int = 10, clip: tuple[float, float] | None = None, random_state: int | None = None, n_jobs: int = 1)[source]#

Cross-validated convex ensemble of a library of learners.

Parameters:
librarysequence of estimators or None

A sequence of scikit-learn estimators or (name, estimator) pairs. When omitted, the concrete default library is histogram gradient boosting, a random forest, and a task-appropriate lasso model.

task{“classification”, “regression”} or None

"classification" for a 0/1 target, "regression" otherwise; None infers it from y at fit time.

meta_learner{“auto”, “nnls”, “nnloglik”, “discrete”}

How to combine candidates. See the module docstring. "auto" picks "nnloglik" for a classification task and "nnls" otherwise.

n_foldsint

Inner cross-validation folds used to score candidates.

cliptuple of float or None

Optional (low, high) bounds applied to predictions. Nuisance models for probabilities pass (0, 1), since a regression candidate can otherwise predict outside the unit interval.

random_stateint or None

Seed for the inner fold split, for reproducibility.

n_jobsint

Number of joblib workers. Candidate fits across folds are independent and are dispatched in parallel.

Attributes:
coef_ndarray

Convex ensemble weights, aligned with learner_names_.

cv_risk_ndarray

Cross-validated risk per candidate.

cv_predictions_ndarray

(n, n_candidates) matrix of out-of-fold predictions. The validation module reuses it to assess calibration without refitting.

See also

cleverly.ModelSpec

Where an ensemble is passed as a nuisance learner.

cleverly.learners.default_library

The candidates used when none are given.

cleverly.learners.SuperLearnerDiagnostics

Per-candidate risk and weight.

Examples

>>> import numpy as np
>>> from sklearn.linear_model import LinearRegression, Ridge
>>> from cleverly import SuperLearner
>>> rng = np.random.default_rng(0)
>>> X = rng.normal(size=(200, 3))
>>> y = X[:, 0] + rng.normal(size=200)
>>> ensemble = SuperLearner(
...     library=[LinearRegression(), Ridge(alpha=1.0)], n_folds=3, random_state=0
... )
>>> ensemble.fit(X, y).learner_names_
('LinearRegression', 'Ridge')

The fitted weights form a convex combination:

>>> float(round(ensemble.coef_.sum(), 6))
1.0
>>> ensemble.predict(X).shape
(200,)

Methods#

SuperLearner.fit(X: ndarray[tuple[Any, ...], dtype[float64]], y: ndarray[tuple[Any, ...], dtype[float64]], sample_weight: ndarray[tuple[Any, ...], dtype[float64]] | None = None, *, groups: ndarray[tuple[Any, ...], dtype[int64]] | None = None) → SuperLearner[source]#

Fit the ensemble.

groups keeps clustered observations inside the same inner fold, so a candidate cannot be scored on a row correlated with its training set.

Parameters:
Xndarray

(n, p) covariates.

yndarray

(n,) target.

sample_weightndarray or None

(n,) weights, or None for equal weights.

groupsndarray or None

(n,) cluster codes. Rows of a cluster stay in the same inner fold, so a candidate cannot be scored on a row correlated with its training set.

Returns:
SuperLearner

This object, fitted, as scikit-learn expects.

SuperLearner.predict(X: ndarray[tuple[Any, ...], dtype[float64]]) → ndarray[tuple[Any, ...], dtype[float64]][source]#

Ensemble prediction of the conditional mean.

Parameters:
Xndarray

(n, p) covariates.

Returns:
ndarray

(n,) ensemble prediction of the conditional mean.

SuperLearner.predict_proba(X: ndarray[tuple[Any, ...], dtype[float64]]) → ndarray[tuple[Any, ...], dtype[float64]][source]#

Class probabilities, columns following classes_.

(n, 2) for a binary target, (n, K) for a one-vs-rest multi-class fit, where the per-class ensembles are normalised to sum to one across the row.

Parameters:
Xndarray

(n, p) covariates.

Returns:
ndarray

(n, n_classes) probabilities, columns following classes_.

SuperLearner.set_fit_request(*, groups: bool | None | str = '$UNCHANGED$', sample_weight: bool | None | str = '$UNCHANGED$') → SuperLearner#

Configure whether metadata should be requested to be passed to the fit method.

Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with enable_metadata_routing=True (see sklearn.set_config()). Please check the User Guide on how the routing mechanism works.

The options for each parameter are:

  • True: metadata is requested, and passed to fit if provided. The request is ignored if metadata is not provided.

  • False: metadata is not requested and the meta-estimator will not pass it to fit.

  • None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.

  • str: metadata should be passed to the meta-estimator with this given alias instead of the original name.

The default (sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.

Added in version 1.3.

Parameters:
groupsstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for groups parameter in fit.

sample_weightstr, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED

Metadata routing for sample_weight parameter in fit.

Returns:
selfobject

The updated object.

Attributes#

SuperLearner.classes_#

Return fitted outcome classes.

SuperLearner.is_multiclass#

Whether this was fit one-vs-rest on a target with more than two levels.

SuperLearner.weights#

Ensemble weight per candidate, as a mapping.