API Reference¶
Automatically generated from docstrings (mkdocstrings).
Quick start: recommend()¶
The high-level entry point. Given donor scores it fits a cold-start method and returns ranked recommendations for cold items — the fastest way to get started.
warmtransfer.recommend.recommend
¶
recommend(
interactions: DataFrame,
content: ItemFeatures,
donor_scores: DataFrame,
*,
item_meta: DataFrame | None = None,
metric: str = "auc",
ks: tuple[int, ...] = (1, 5, 10),
methods: list[str] | None = None,
holdout: HoldoutConfig | None = None,
seed: int = 42,
n_seeds: int = 1,
min_rela_gain: float = 0.02,
verbose: bool = True,
) -> AutoResult
Auto-select a cold-start method on the user's own data via an honest holdout.
metric is the headline metric (default per-user auc). methods optionally
restricts the candidate method names. Embedding methods are skipped in v1. Returns an
:class:AutoResult with a leaderboard, a verdict, and a ready-to-use fitted winner.
The structured result returned by recommend():
warmtransfer.recommend.AutoResult
dataclass
¶
Outcome of :func:recommend: leaderboard + verdict + a ready-to-use winner.
Methods:
| Name | Description |
|---|---|
predict |
Predict scores for new cold items with the winner refit on ALL warm data. |
predict
¶
predict(
user_ids: ndarray, cold_item_ids: ndarray
) -> DataFrame
Predict scores for new cold items with the winner refit on ALL warm data.
The winner is refit lazily; the fit is cached per distinct cold_item_ids set
(a different set triggers a refit, since the production inputs depend on it).
Contracts and types¶
The canonical DataFrame column names shared across the whole API:
warmtransfer.columns.Columns
¶
Namespace with fixed column names.
Usage::
from warmtransfer.columns import Columns as C
df = df.rename(columns={"uid": C.User, "iid": C.Item})
warmtransfer.holdout.HoldoutConfig
dataclass
¶
Parameters of the pseudo-cold holdout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cold_frac
|
float
|
fraction of items placed in test-cold (ground truth). |
0.2
|
val_frac
|
float
|
fraction of items placed in val-cold (for supervised methods). |
0.1
|
n_pop_buckets
|
int
|
number of popularity buckets for stratification. |
5
|
min_item_interactions
|
int
|
minimum interactions for an item to be eligible as cold. |
5
|
warmtransfer.types
¶
Internal data types (hot path): dataclasses + numpy/pandas, no pydantic.
Pydantic is used only at the boundaries (configs, validation of public input in
schema.py). Here we keep lightweight containers for exchange between components.
Classes:
| Name | Description |
|---|---|
ItemFeatures |
Content features of items, aligned with |
Dataset |
Dataset: interactions + item content. |
SplitResult |
Result of an honest cold-start split. |
TransferInputs |
Everything a cold-start method receives as input ( |
ItemFeatures
dataclass
¶
Content features of items, aligned with item_ids.
matrix[i] is the feature vector of item item_ids[i] (external id).
Methods:
| Name | Description |
|---|---|
subset |
Subset by external ids (order follows |
Dataset
dataclass
¶
Dataset: interactions + item content.
Interactions are a long-format DataFrame with Columns columns (User, Item,
Weight, Datetime). item_features is optional (content may be delegated to
the library user).
SplitResult
dataclass
¶
Result of an honest cold-start split.
Invariant (checked by tests): cold_items do not appear in train or
val; their interactions are present only in test.
Methods:
| Name | Description |
|---|---|
cold_in_train |
Set of cold items leaked into train (must be empty). |
TransferInputs
dataclass
¶
Everything a cold-start method receives as input (ColdStartMethod.fit).
The bundle is assembled by the benchmark runner from Dataset/SplitResult
and the donor. When using the library directly, the user fills in the needed
fields themselves (at minimum — donor_scores + one content/similarity source).
Base method¶
warmtransfer.methods.base.ColdStartMethod
¶
Bases: ABC
Abstract cold-start method.
Subclasses declare:
* name — the name used in the registry/config;
* requires — which inputs are mandatory (validated in :meth:fit).
Contract:
* :meth:fit returns self;
* :meth:predict returns a DataFrame [user_id, item_id, score];
* deterministic for a fixed seed.
Methods:
| Name | Description |
|---|---|
fit |
Validate the mandatory inputs and train the method. |
get_params |
Method hyperparameters (for logging into artifacts). |
predict |
Predict scores for all (user_ids × cold_item_ids) pairs. |
fit
¶
fit(
inputs: TransferInputs, seed: int = 0
) -> ColdStartMethod
Validate the mandatory inputs and train the method.
predict
abstractmethod
¶
predict(
user_ids: ndarray, cold_item_ids: ndarray
) -> DataFrame
Predict scores for all (user_ids × cold_item_ids) pairs.
Returns a long-format DataFrame [user_id, item_id, score].
Cold-start methods¶
warmtransfer.methods.linmap.LinMap
¶
Bases: ColdStartMethod
Ridge mapping content -> donor score vector across all users.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
Ridge L2 regularization coefficient. |
10.0
|
warmtransfer.methods.stacking_plus.StackingPlus
¶
Bases: ColdStartMethod
Meta logreg over [linmap, genre_affinity, genre_popularity], trained on val-cold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
L2 regularization of the inner Ridge (linmap signal). |
10.0
|
C_reg
|
float
|
inverse regularization of the meta logistic regression. |
1.0
|
warmtransfer.methods.stacking.StackingTransfer
¶
Bases: ColdStartMethod
Meta logistic regression on signals [affinity, genre_pop, knn], trained on val-cold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of content neighbors for the knn signal. |
20
|
C_reg
|
float
|
inverse regularization of the logistic regression. |
1.0
|
warmtransfer.methods.baselines.GroupedMostPopularPersonalized
¶
Bases: ColdStartMethod
Personalized GroupedMP: user affinity to the cold item's genres.
score(u, i) = Σ_g [item i has genre g] · (how many times u interacted with warm items of genre g in train). A strong personalized baseline — the project's main target. Leak-free: only train + static content.
warmtransfer.methods.baselines.GroupedMostPopular
¶
Bases: ColdStartMethod
Popularity within the cold item's category (genre).
Genre popularity = sum of train popularities of warm items of that genre. The cold item score = sum of its genres' popularities. Leak-free: uses only train + static content. A strong baseline.
warmtransfer.methods.knn.KNNScoreAggregation
¶
Bases: ColdStartMethod
Similarity-weighted average of donor scores over k content neighbors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm neighbors. |
20
|
clip_negative
|
bool
|
zero out negative similarities (cosine can be < 0). |
True
|
warmtransfer.methods.attention_knn.AttentionKNN
¶
Bases: ColdStartMethod
Softmax-weighted average of donor scores over k content neighbors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm neighbors. |
20
|
temperature
|
float
|
softmax temperature; smaller → sharper (top neighbor dominates). |
0.1
|
warmtransfer.methods.debiased_knn.DebiasedKNN
¶
Bases: ColdStartMethod
KNN over content neighbors with subtraction of neighbor popularity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm neighbors. |
20
|
clip_negative
|
bool
|
zero out negative similarities (cosine can be <0). |
True
|
warmtransfer.methods.logreg_calib.LogRegCalibration
¶
Bases: ColdStartMethod
Logistic calibration of knn aggregates of donor scores (trained on val-cold).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of content neighbors. |
20
|
warmtransfer.methods.scale_shift.ScaleShift
¶
Bases: ColdStartMethod
Content-based KNN over donor scores + calibration to warm statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm neighbors. |
20
|
clip_negative
|
bool
|
zero out negative similarities. |
True
|
warmtransfer.methods.linmap_emb.LinMapEmbedding
¶
Bases: ColdStartMethod
Ridge mapping of content -> donor latent factors (Gantner).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
L2 regularization coefficient of Ridge. |
10.0
|
warmtransfer.methods.embedding_avg.EmbeddingAverage
¶
Bases: ColdStartMethod
Scores via averaged embeddings of content warm-neighbors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm-neighbors to average embeddings over. |
20
|
warmtransfer.methods.attention_emb.AttentionEmbedding
¶
Bases: ColdStartMethod
Content-based softmax-weighted averaging of donor neighbors' embeddings.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
k
|
int
|
number of nearest warm neighbors. |
20
|
temperature
|
float
|
softmax temperature (lower → sharper weights). |
0.1
|
warmtransfer.methods.magnitude_scaling.MagnitudeScaling
¶
Bases: LinMapEmbedding
Gantner generation of cold embeddings + popularity debiasing by magnitude.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
alpha
|
float
|
L2 regularization of Ridge (content → factors generator). |
10.0
|
ms_alpha
|
float
|
strength of pulling the norm toward |
1.0
|
warmtransfer.methods.dropoutnet.DropoutNet
¶
Bases: ColdStartMethod
MLP [latent⊕content]->latent with preference dropout (item embedding reconstruction).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
hidden
|
int
|
hidden layer size. |
128
|
epochs
|
int
|
number of training epochs. |
200
|
lr
|
float
|
learning rate (Adam). |
0.001
|
dropout_pref
|
float
|
fraction of examples in the batch with a zeroed latent branch. |
0.5
|
weight_decay
|
float
|
L2 regularization. |
1e-05
|
Config and results¶
warmtransfer.bench.config.BenchConfig
¶
Bases: BaseModel
Run specification: datasets × donors × methods × seeds.
warmtransfer.bench.results
¶
Collecting and exporting benchmark results.
Functions:
| Name | Description |
|---|---|
add_rela_impr |
Add a |
save_table |
Save the table to parquet + markdown. Returns the paths. |
to_table |
List of run records -> DataFrame, averaged over seeds. |
add_rela_impr
¶
add_rela_impr(
table: DataFrame, base_method: str, metric: str = "auc"
) -> DataFrame
Add a rela_impr column — the relative AUC improvement over base_method.
RelaImpr = (AUC_model − 0.5)/(AUC_base − 0.5) − 1, computed within each (dataset, donor) pair. For the base method itself = 0.0; if the base is missing — NaN.
save_table
¶
save_table(
df: DataFrame,
out_dir: str | Path,
name: str = "results",
) -> dict[str, Path]
Save the table to parquet + markdown. Returns the paths.
to_table
¶
to_table(
records: list[dict], *, with_std: bool = False
) -> DataFrame
List of run records -> DataFrame, averaged over seeds.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
with_std
|
bool
|
add |
False
|
Metrics¶
warmtransfer.metrics
¶
Recommendation quality metrics (our own correct implementation).
Public entry point — :func:calc_metrics: takes recommendations and ground truth in
Columns format and returns a dict {"recall@10": ..., "auc": ...}.
Modules:
| Name | Description |
|---|---|
classification |
AUC (area under ROC) via the Mann-Whitney rank formula. |
ranking |
Ranking metrics (per-user). Binary relevance. |
relative |
RelaImpr — relative AUC improvement over a baseline. |
Functions:
| Name | Description |
|---|---|
auc |
AUC from binary labels |
calc_metrics |
Full metric set: ranking@k (+ per-user and global AUC over the candidate grid). |
global_auc |
Global AUC: pool all (user, cold_item) pairs with 1/0 labels into one common AUC. |
mean_user_auc |
Mean per-user AUC. |
ranking_metrics |
All ranking metrics for all |
rela_impr |
Relative AUC improvement of the model over the baseline (a fraction, not percent). |
auc
¶
auc(y_true: ndarray, y_score: ndarray) -> float
AUC from binary labels y_true and scores y_score.
Returns nan if the sample contains only one class (AUC is undefined).
calc_metrics
¶
calc_metrics(
reco: DataFrame,
ground_truth: DataFrame,
ks: tuple[int, ...] = (1, 5, 10),
*,
include_auc: bool = True,
) -> dict[str, float]
Full metric set: ranking@k (+ per-user and global AUC over the candidate grid).
global_auc
¶
global_auc(
reco: DataFrame, ground_truth: DataFrame
) -> float
Global AUC: pool all (user, cold_item) pairs with 1/0 labels into one common AUC.
Exposes the popularity signal more strongly than per-user averaging; used to cross-check against protocols where AUC is computed over all pairs at once.
mean_user_auc
¶
mean_user_auc(
reco: DataFrame, ground_truth: DataFrame
) -> float
Mean per-user AUC.
reco must contain scores for ALL candidate items of each user
(the full user × cold_item grid). Positives are items from ground_truth.
Averaged over users that have both classes present.
ranking_metrics
¶
ranking_metrics(
reco: DataFrame,
ground_truth: DataFrame,
ks: tuple[int, ...] = (1, 5, 10),
) -> dict[str, float]
All ranking metrics for all k values: {"recall@10": ..., ...}.
rela_impr
¶
rela_impr(model_auc: float, base_auc: float) -> float
Relative AUC improvement of the model over the baseline (a fraction, not percent).
Benchmark¶
warmtransfer.bench.adapters.base.ModelAdapter
¶
Bases: ABC
Abstract donor.
Contract:
* :meth:fit trains ONLY on warm interactions (no cold items there);
* :meth:score returns [user_id, item_id, score] for the requested pairs;
* :meth:embeddings — optional user/item latent factors (for [EMB] methods).
Methods:
| Name | Description |
|---|---|
embeddings |
Latent factors, if the model has them: |
fit |
Train the donor on |
score |
Scores for pairs (user_ids × item_ids), long-format |
embeddings
¶
embeddings() -> dict[str, ndarray] | None
Latent factors, if the model has them: {"user": ..., "item": ...}.
fit
abstractmethod
¶
fit(dataset: Dataset, seed: int = 0) -> ModelAdapter
Train the donor on dataset.interactions (warm).
score
abstractmethod
¶
score(user_ids: ndarray, item_ids: ndarray) -> DataFrame
Scores for pairs (user_ids × item_ids), long-format [user_id, item_id, score].
warmtransfer.bench.datasets.base.DatasetLoader
¶
Bases: ABC
Abstract loader.
:meth:load converts raw data into a unified format: a Dataset with interactions
(long-format, Columns columns) and item content (ItemFeatures).
Methods:
| Name | Description |
|---|---|
describe |
Brief description for docs/datasets.md (domain, size, features). |
load |
Load (downloading if necessary) and normalize the dataset. |
warmtransfer.bench.splitters.base.Splitter
¶
Bases: ABC
Abstract warm/cold splitter.
Methods:
| Name | Description |
|---|---|
split |
Split the dataset: pick pseudo-cold items and remove them from train/val. |
split
abstractmethod
¶
split(dataset: Dataset, seed: int = 0) -> SplitResult
Split the dataset: pick pseudo-cold items and remove them from train/val.
warmtransfer.bench.runner.BenchmarkRunner
¶
Runs the matrix from BenchConfig and returns result records.
warmtransfer.bench.splitters.pseudo_cold.PseudoColdSplitter
¶
Bases: Splitter
Warm / val-cold / test-cold split by items (logic in warmtransfer.holdout).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cold_frac
|
float
|
fraction of items in test-cold (ground truth). |
0.2
|
val_frac
|
float
|
fraction of items in val-cold (hyperparameter tuning). |
0.1
|
n_pop_buckets
|
int
|
number of popularity buckets for stratification. |
5
|
min_item_interactions
|
int
|
min interactions for an item to be eligible as cold. |
1
|
Utilities¶
Seeding helpers for reproducible runs:
warmtransfer.seeding
¶
Reproducibility: a single point for seeding.
torch is seeded optionally (it lives in the deep extra), so that core does not depend on it.
Functions:
| Name | Description |
|---|---|
make_rng |
Local numpy generator (preferable to global state). |
set_global_seed |
Seed |
Decorator to register a custom cold-start method in the methods registry:
warmtransfer.methods.base.register_method
¶
register_method(
name: str,
) -> Callable[[type[_M]], type[_M]]
Decorator that registers a method under name (sets cls.name).
Preserves the concrete class type (does not collapse it to the base) so that pyright
sees the subclass __init__ signature.