Checkpoint API

Item embeddings

See Using item embeddings for named feature spaces and missingness masks, whether the vectors are imported or computed by the user.

compresso_recsys.embeddings.save_item_embeddings(root, name, *, item_ids, embeddings, available=None, metadata=None)[source]

Save finite float32 features, explicit IDs, a presence mask, and provenance.

Call inside update_checkpoint. Names such as text/minilm are independent feature spaces. Missing rows are stored as zeros, never inferred from values.

compresso_recsys.embeddings.load_item_embeddings(root, name, *, item_ids=None)[source]

Load one feature space, optionally reindexing to a requested item catalog.

Unknown IDs become zero rows with available=False. Old checkpoints have no registered feature spaces; an absent name raises KeyError.

compresso_recsys.embeddings.list_item_embeddings(root)[source]

Return names and descriptors without loading feature matrices.

compresso_recsys.multimodal.enrich_multimodal_checkpoint(checkpoint_path, **kwargs)[source]

Atomically enrich an existing ML-1M, DBbook, or Last.fm checkpoint.

Checkpoint Contexts

compresso_recsys.checkpoint.update_checkpoint(path)[source]

Extract a zip checkpoint to a temp dir, let caller edit it, then rewrite it.

Return type:

Iterator[Path]

Parameters:

path (str | Path)

compresso_recsys.checkpoint.read_checkpoint(path)[source]

Extract a zip checkpoint to a read-only temp workspace.

Return type:

Iterator[Path]

Parameters:

path (str | Path)

Manifest and JSON Helpers

compresso_recsys.checkpoint.load_manifest(root)[source]
Return type:

dict[str, Any]

Parameters:

root (str | Path)

compresso_recsys.checkpoint.save_manifest(root, manifest)[source]
Return type:

None

Parameters:
  • root (str | Path)

  • manifest (dict[str, Any])

compresso_recsys.checkpoint.update_stage_manifest(root, stage, metadata)[source]
Return type:

None

Parameters:
  • root (str | Path)

  • stage (str)

  • metadata (dict[str, Any])

compresso_recsys.checkpoint.save_json(root, relpath, data)[source]
Return type:

Path

Parameters:
  • root (str | Path)

  • relpath (str)

  • data (dict[str, Any])

compresso_recsys.checkpoint.load_json(root, relpath)[source]
Return type:

dict[str, Any]

Parameters:
  • root (str | Path)

  • relpath (str)

Split and Cluster Stages

Item partitions

warm_item_indices, val_cold_item_indices and test_cold_item_indices are positions into item_ids naming the items each phase introduces, not the items it may score:

split_mode

Train partition

Val / test partitions

user_split

Full catalog range

Empty; no items are held out

item_split

Warm items

The disjoint cold items held out of training

leave_last_out

Every item; nothing is withheld from the catalog

Only items whose every occurrence falls in a held-out tail

temporal

Items in the first window

Items first seen in each later window

An empty partition means this phase introduces no new items, which is not the same as this phase has no candidates. A user split scores the whole catalog in every phase; it simply adds nothing new. The candidate space of a phase is {phase}_item_ids, which equals item_ids unless the split gives each phase its own item space (only temporal does, flagged by has_stage_item_spaces in the split metadata).

So to select feature or metadata rows for a phase, index with that phase’s *_item_ids, not by mirroring warm_item_indices: for splits that hold no items out, the latter yields an empty selection that fails much later and far from its cause. has_item_partitions in the split metadata tells you whether a split partitions items at all.

Chronological split modes additionally store sequence views — x_train_sequences and {stage}_source_sequences — holding the same events as the matrices in order, with duplicates preserved. They load as None for user_split and item_split, and for any checkpoint built before sequences existed.

compresso_recsys.checkpoint.save_recsys_split(root, *, item_ids, x_train, train_item_ids=None, val_item_ids=None, test_item_ids=None, val_source_indices, val_target_indices, test_source_indices, test_target_indices, train_source_matrix=None, train_target_matrix=None, val_source_matrix=None, val_target_matrix=None, test_source_matrix=None, test_target_matrix=None, train_user_ids=None, val_user_ids=None, test_user_ids=None, val_eval_user_ids=None, test_eval_user_ids=None, warm_item_indices=None, val_cold_item_indices=None, test_cold_item_indices=None, x_train_sequences=None, train_source_sequences=None, val_source_sequences=None, test_source_sequences=None, entity_tag_matrix=None, tag_names=None, entity_metadata=None, metadata=None)[source]

Write the split stage of a checkpoint.

Return type:

None

Parameters:
  • root (str | Path)

  • item_ids (ndarray)

  • x_train (csr_matrix)

  • train_item_ids (ndarray | list[str] | None)

  • val_item_ids (ndarray | list[str] | None)

  • test_item_ids (ndarray | list[str] | None)

  • val_source_indices (list[ndarray])

  • val_target_indices (list[ndarray])

  • test_source_indices (list[ndarray])

  • test_target_indices (list[ndarray])

  • train_source_matrix (csr_matrix | None)

  • train_target_matrix (csr_matrix | None)

  • val_source_matrix (csr_matrix | None)

  • val_target_matrix (csr_matrix | None)

  • test_source_matrix (csr_matrix | None)

  • test_target_matrix (csr_matrix | None)

  • train_user_ids (ndarray | list[str] | None)

  • val_user_ids (ndarray | list[str] | None)

  • test_user_ids (ndarray | list[str] | None)

  • val_eval_user_ids (ndarray | list[str] | None)

  • test_eval_user_ids (ndarray | list[str] | None)

  • warm_item_indices (ndarray | None)

  • val_cold_item_indices (ndarray | None)

  • test_cold_item_indices (ndarray | None)

  • x_train_sequences (ItemSequences | None)

  • train_source_sequences (ItemSequences | None)

  • val_source_sequences (ItemSequences | None)

  • test_source_sequences (ItemSequences | None)

  • entity_tag_matrix (csr_matrix | None)

  • tag_names (ndarray | list[str] | None)

  • entity_metadata (DataFrame | None)

  • metadata (dict[str, Any] | None)

Training matrices

Three keys describe the same training data, and the relationship between them is fixed:

x_train = train_source_matrix ∪ train_target_matrix

x_train is what a symmetric model trains on — an autoencoder reconstructs the whole window. The pair is what an asymmetric model trains on, mapping source to target. They must agree, and this function refuses a checkpoint where they do not.

How the training data is partitioned follows each split mode’s protocol, and only the chronological modes have one to follow:

  • temporal: by time. Source is everything before the first target window, target is the events inside it.

  • leave_last_out: by position. Target is the last interaction of the training window, source is everything earlier.

  • user_split and item_split: no partition. Both keys equal x_train, and the invariant holds trivially.

The last case is deliberate rather than a gap. A non-chronological split has no boundary to divide on, so any per-user division would be an arbitrary choice invented here rather than a property of the protocol. A model wanting asymmetric training on those modes can partition x_train itself, under its own seed, and own that choice. The same absence of an ordering is why sequences exist only for the chronological modes.

Sequence views

x_train_sequences and {stage}_source_sequences carry the same events as their matrix counterparts, in chronological order and with duplicates kept. A matrix row is a set; a sequence row is a history. Targets have no sequence view because a ranking target is a set — order is irrelevant to every metric — so {stage}_target_matrix serves both model families.

They are written only when the split mode produced them, which means the chronological modes. user_split and item_split have no ordering to preserve, and the same absence that makes their training partition arbitrary (above) makes a sequence meaningless.

Loading a checkpoint without them yields None rather than an error. A checkpoint that predates sequences, or comes from a non-chronological mode, is still complete for every matrix model, so refusing it would break working setups over a field they never touch. A sequential model fails later, where the message can name the split mode that would have produced them.

A sequence whose n_items disagrees with its own stage’s item IDs is refused: the two views must share a column space or a model scores one item and is credited for another. Per stage rather than globally, because temporal windows each have their own catalog — it grows window by window — which is the same allowance the matrix check above makes.

Item partitions

warm_item_indices, val_cold_item_indices and test_cold_item_indices are positions into item_ids naming the items that phase introduces, not the items it may score. Together they partition the catalog by first appearance: the warm partition is exactly the columns present in x_train, and each cold partition holds the items that become observable only at that stage.

They are named for what they hold rather than for their phase because the older {phase}_item_indices spelling promised a relationship to {phase}_item_ids that does not exist. The two answer different questions: *_item_ids is the column space a phase lives in, while these are a partition by first appearance. The two agree only by coincidence, and only under temporal and user_split, where the catalogs already encode the partition; under leave_last_out and item_split all three phases share one catalog and the partition is observed, so it cannot be recovered from the catalogs at all.

  • user_split: training spans every item and the later phases introduce none, so the train partition is the full range and val/test are empty.

  • item_split: three disjoint partitions, the val/test ones being the cold items held out of training.

  • leave_last_out: nothing is held out of the catalog. An item lands in the val or test partition only when every one of its occurrences falls in a held-out tail, so on dense data both partitions are empty and on sparse data they hold the genuinely new items.

  • temporal: each phase introduces the items first seen in its window, so the partitions are consecutive ranges of the growing catalog.

An empty partition therefore means “this phase introduces no new items”, which is not the same as “this phase has no candidates”. The candidate space of a phase is {phase}_item_ids, which defaults to item_ids when not given. Callers that select feature or metadata rows for a phase should index with that phase’s *_item_ids (or the union of partitions up to it), because mirroring warm_item_indices into a later phase silently yields an empty selection for splits that hold no items out.

Passing None for a partition omits its file, and load_recsys_split() then falls back to the whole catalog for the warm partition and to an empty array for the cold ones. Prefer writing all three explicitly, since those defaults turn an omission into a confident wrong answer rather than an error.

compresso_recsys.checkpoint.load_recsys_split(root)[source]

Read the split stage of a checkpoint.

See save_recsys_split() for what *_item_indices mean: they are the items each phase introduces, so they are empty for phases that hold no items out, while *_item_ids give the candidate space and default to item_ids.

For checkpoints written before every partition was stored explicitly, a missing warm_item_indices.npy loads as the full catalog range and missing cold files load as empty arrays. Checkpoints written before the rename are read under their old names first, because those defaults would otherwise turn a missing file into a confident wrong answer.

Return type:

dict[str, Any]

Parameters:

root (str | Path)

compresso_recsys.checkpoint.save_cluster_graph_stage(root, graph, *, stage_dir='clustering', metadata=None)[source]
Return type:

Path

Parameters:
  • root (str | Path)

  • graph (SparseClusterSet)

  • stage_dir (str)

  • metadata (dict[str, Any] | None)

compresso_recsys.checkpoint.load_cluster_graph_stage(root, *, stage_dir='clustering')[source]
Return type:

SparseClusterSet

Parameters:
  • root (str | Path)

  • stage_dir (str)