Skip to content

Capability matrix

This page summarizes which combinations of components are supported in the current codebase: training paths, inference APIs, retrievers, and batch training. It is derived from the implementation (not aspirational). If behavior changes in a release, this matrix should be updated with it.

For the layered mental model, see Architecture overview.


Legend

Symbol Meaning
Yes Supported for typical configurations.
No Raises, documented as unsupported, or would violate the model contract.
Partial Works with constraints (see notes).
N/A Concept does not apply (e.g. no estimator plane).

Estimator training planes

Models fall into three training / scoring planes. Each plane uses different dataset shaping and entrypoints.

Plane Base type (typical) Training entrypoint Primary scoring path
Tabular BaseClassifier, BaseRegressor (e.g. XGB, LightGBM, sklearn, DeepFM as classifier) fit(X, y) on a joined feature matrix from the scorer predict / predict_proba on joined rows
Embedding BaseEmbeddingEstimator (e.g. MF, NCF, two-tower, DCN variants) fit_embedding_model(users, items, interactions, …) predict_proba_with_embeddings(…)
Sequential SequentialEstimator (SASRec, HRNN) fit_embedding_model(…) via SequentialScorer (not BaseEmbeddingEstimator) Forward pass over sequences; not Cartesian tabular join

Dispatch: recommender.recommender.training_coordinator.coordinate_training chooses batch tabular vs tabular vs embedding vs (via scorer) sequential training.


Scorer × estimator plane

Scorer Tabular estimator Embedding (BaseEmbeddingEstimator) Sequential (SequentialEstimator)
UniversalScorer Yes (factory yields TabularUniversalScorer) Yes (EmbeddingUniversalScorer) No (use SequentialScorer)
IndependentScorer Yes (single or dict of estimators) No (raises at init) No
MulticlassScorer Yes No (raises at init) No
MultioutputScorer YesBaseClassifier (binary-only; multi-class rejected at fit) or BaseRegressor. Per-label: MultiOutputClassifierEstimator / MultiOutputRegressorEstimator (N independent boosters). Joint single-booster: JointXGBMultiOutputClassifierEstimator / JointXGBMultiOutputRegressorEstimator. sklearn tree ensembles (RandomForest/ExtraTrees) are joint multi-output via the SklearnUniversal* wrappers. See per-label vs joint. No (raises at init) No
MixedTypeMultiTargetScorer Yes — accepts any MultiTargetEstimator (joint MLP, joint Transformer, or independent). Heterogeneous per-target types: binary + regression + multiclass + multilabel groups in one model. See decision rule for per-target metric dispatch. No (raises at init via Protocol check) No
SequentialScorer No No Yes
HierarchicalScorer No No Yes (HRNN estimators)
UpliftScorerAdapter Yes (internal tabular scorers) No (not exposed for uplift) No

Estimator config knobs (tabular)

These estimator_config keys apply to the sklearn-API tabular estimators (XGBoost / LightGBM / sklearn wrappers, single- and multi-target). All are introspectable via capability_matrix() so external callers (e.g. the agent) stay in lockstep.

Config path Values Applies to capability_matrix() key
weights.sample_weight 'balanced' (class-balanced at fit), a callable fn(y)->weights, or an explicit array (default: uniform) All sklearn-API estimators, all scorers (XGB/LightGBM/sklearn; single- & multi-target). For early stopping, 'balanced'/callable also weight the eval set; explicit arrays are train-only. weights_config_keys
weights.fit_params dict of static kwargs forwarded to the wrapped fit (feature_weights, base_margin, custom objective, callbacks, …) All sklearn-API estimators weights_config_keys
weights.action_weight, weights.item_sample_weights recsys item/action weighting (composes multiplicatively with sample_weight) WeightedXGBClassifierEstimator path weights_config_keys
multioutput_strategy 'per_label' (default; N independent boosters) or 'joint' (one joint XGBoost booster) scorer_type="multioutput" only. 'joint' is XGBoost-only and non-tuned-only (no HPO wrapper); pair with xgboost.multi_strategy='multi_output_tree' for cross-label learning (CPU-only) or 'one_output_per_tree' (GPU; per-label-equivalent). multioutput_strategy_types

recommend() vs recommend_online()

Recommender recommend() recommend_online() Notes
RankingRecommender Yes Partial With an attached retriever, recommend() uses two-stage candidates. recommend_online() does not use the retriever — it scores the full catalog (warning logged). Thread-safety: see retrieval when using retriever + shared instance.
GcslRecommender Yes No Goal injection is skipped on the fast path; use recommend().
SequentialRecommender Yes No Use recommend(); sequence models use their own forward path.
HierarchicalSequentialRecommender Yes No Same as sequential (inherits blocked recommend_online).
ContextualBanditsRecommender Yes Partial Inherits base fast path: same score_fast / _score_fast_np constraints as the underlying scorer. Strategy must be set before recommend() / sampling paths; embedding scorers still cannot use recommend_online().
UpliftRecommender Yes No UpliftScorerAdapter.score_fast raises; use recommend().

recommend_online() and scorers (Ranking + tabular path)

BaseRecommender.recommend_online builds a single-row feature row, then calls MultioutputScorer.score_fast (special return type) or _score_fast_np on other scorers.

Scorer recommend_online Notes
Tabular UniversalScorer Yes Single-row fast path.
Embedding UniversalScorer No score_fast raises; use recommend().
IndependentScorer Yes When estimator is tabular; score_fast validates exactly one row.
MulticlassScorer Yes Same one-row contract.
MultioutputScorer Partial Returns a DataFrame with one column per ITEM_<name> target — predicted class labels in classifier mode or predicted continuous values in regressor mode; top_k is ignored (documented on BaseRecommender.recommend_online). For ranking-style top-K-by-positive-probability output, use the batch recommend() path instead.
MixedTypeMultiTargetScorer Partial Returns a DataFrame of per-target point estimates (one column per fanned-out target, dtype preserved per TargetType). top_k is ignored. OBSERVED_* columns supported in v3 with a ConditionalMultiTargetEstimator — auto-preserved through interactions_schema.apply() via the preserved_inference_columns() hook (no client-schema changes required). Vanilla estimators still reject OBSERVED_*.
SequentialScorer No score_fast raises.
UpliftScorerAdapter No Use recommend().

Optional retrievers (RankingRecommender / GcslRecommender)

Retriever is optional on these classes. SequentialRecommender’s public constructor does not expose a retriever argument (inherits RankingRecommender with retriever default None).

Retriever Required train() datasets Estimator constraint
EmbeddingRetriever Depends on model; embedding index uses fitted estimator BaseEmbeddingEstimator on the scorer
ContentBasedRetriever items_ds None specific
PopularityRetriever interactions_ds None specific

Batch (partitioned) training

Support Details
Estimator In the shipped code, BatchXGBClassifierEstimator implements _batch_fit_model (see skrec/estimator/classification/xgb_classifier.py). Other estimators use in-memory fit unless extended.
Training coordinate_training uses the batch path when estimator.support_batch_training() is true: interactions_ds required; items_ds required for partitioned catalogue setup; validation datasets must satisfy the same rules as tabular validation (e.g. valid_users_ds when users + valid interactions).
Embedding No batch-training branch for BaseEmbeddingEstimator in the same iterator style.
Sequential support_batch_training() is False for SequentialEstimator.

Evaluation (evaluate())

All recommenders built on BaseRecommender share the evaluation session API, but metrics are only meaningful when the recommender’s ranking / probability behavior matches what you intend to measure.

Topic Note
ContextualBanditsRecommender Offline evaluate() uses scorer scores but ranking / probabilities follow the bandit policy when the strategy applies. For “raw model” metrics, use RankingRecommender (see docstring on ContextualBanditsRecommender).
STATIC_ACTION Probabilistic recommend() / temperature paths may raise (NotImplementedError); evaluation has a dedicated bundle path for static action.
MixedTypeMultiTargetScorer Restricted to RecommenderEvaluatorType.SIMPLE. Returns Dict[str, float] (always — heterogeneous types can't macro-average). Per-TargetType metric dispatch: BINARY/MULTILABEL → ROC_AUC/PR_AUC; REGRESSION → RMSE/MAE; MULTICLASS → MULTICLASS_ACCURACY. Ranking metrics rejected. Use metric_type=Dict[str, RecommenderMetricType] for per-target overrides. For metrics outside the named set, use scorer.score_per_target(metric_callables=...). See decision rule for the dispatch table.

MULTICLASS_ACCURACY × scorer compatibility

MULTICLASS_ACCURACY (new v2 metric — top-1 multiclass accuracy) is the only multiclass-typed metric in v2/v3. Scorer compatibility:

Scorer MULTICLASS_ACCURACY
UniversalScorer No (binary / ranking shapes only)
IndependentScorer No (binary / ranking shapes only)
MulticlassScorer No — uses ranking metrics over the item-as-class catalogue; per-target multiclass-accuracy doesn't apply
MultioutputScorer No (binary-only or regression-only mode)
MixedTypeMultiTargetScorer Yes — for every declared MULTICLASS target. Ground-truth labels in logged_rewards are mapped to the training-time catalogue (_multiclass_classes) before the metric runs
SequentialScorer / HierarchicalScorer No

Thread safety (selected)

Component Concurrence
RankingRecommender + retriever Not thread-safe on one instance: per-user retrieval mutates scorer item subset.
IndependentScorer Docstring: not thread-safe for parallel inference / subset / executor configuration.

Mixing planes in one process (macOS)

If you train across planes in a single Python process on macOS — for example a tabular MF estimator followed by a torch NCF/Two-Tower/DCN/NeuralFactorization estimator (or vice versa) inside the same script, notebook, or HPO sweep — you may hit a torch segfault (process exits with status 139). This is an OpenMP runtime collision between numpy's OpenBLAS and PyTorch's Apple Accelerate, not a scikit-rec issue. Set OMP_NUM_THREADS, MKL_NUM_THREADS, and VECLIB_MAXIMUM_THREADS to 1 before Python imports numpy or torch. See Installation → macOS notes for details.