mixle.represent.generative module

Generative objective for fitting embeddings and optional codebooks.

Rather than tune the encoder to a label, train it to reconstruct its input as an autoencoder over units. The shared-space vector must retain enough information to rebuild the unit, so the representation has an explicit generative objective. Add a VectorQuantizer and the model becomes a VQ-VAE: encode -> quantize (straight-through) -> decode, with the codebook periodically refit on the current embeddings. The learned vocabulary is then selected by reconstruction quality instead of being fixed by a tokenizer chosen outside the model.

fit_autoencoder returns the trained encoder + decoder (+ codebook) and the reconstruction-loss history. It is modality-agnostic: feed it the unit-feature array from any continuous segmenter (patches, windows, atoms, …).

exception AutoencoderFitError(message, losses, epoch)[source]

Bases: RuntimeError

Reconstruction training did not complete, so no representation is returned.

Carries the losses recorded before the failure and the epoch it happened on, so a caller can see where the fit diverged instead of receiving an AutoencoderResult that looks trained.

Parameters:
Return type:

None

class AutoencoderResult(encoder, decoder, quantizer, losses=<factory>)[source]

Bases: object

A reconstruction-trained representation with encoder, decoder, optional codebook, and loss curve.

Only returned for a fit that ran every requested epoch to a finite loss: an untrained or diverged encoder is an AutoencoderFitError, never a result. That sentence was previously a claim the class did not enforce (MXR-080-1906) – with no __post_init__, AutoencoderResult(encoder=FeatureEmbedding(6, 3), decoder=None, quantizer=None, losses=[]) was accepted and is indistinguishable from a fitted result, which is the exact state AutoencoderFitError exists to keep out of the shared representation space.

Two things are now bound rather than assumed:

  • losses must be a non-empty run of finite numbers. It is the only evidence that training happened at all, so a result carrying none is not a trained representation.

  • a quantizer, when present, must be fitted. _train refits the codebook at epoch 0 unconditionally, so every quantizer that reaches a real result has one.

losses is also converted to a tuple. fit_autoencoder used to hand over the SAME list object the training loop was appending to, so the fitted loss curve stayed writable through a reference the result did not know about: res.losses.append(-999.0) rewrote recorded evidence (verified). Note AutoencoderFitError.losses stays a list – it is type-tested as one by represent_generative_test and is already a defensive copy.

Deliberately NOT enforced: that losses actually descends, or that the final loss is what encoder/decoder would reproduce on the training units. A legitimate fit may plateau or bounce, and re-running the forward pass to check would make constructing a result cost a full inference pass over data the result does not retain.

Parameters:
  • encoder (FeatureEmbedding)

  • decoder (Any)

  • quantizer (VectorQuantizer | None)

  • losses (tuple[float, ...])

encode(units)[source]

Encode units through the trained autoencoder encoder.

Parameters:

units (ndarray)

Return type:

ndarray

fit_autoencoder(units, dim, *, hidden=(), quantizer=None, epochs=200, lr=1e-2, refit_codebook_every=25, commitment=0.25, seed=0)[source]

Train an encoder+decoder to reconstruct units (N, in_features) with an optional VQ bottleneck.

Without quantizer this is a standard autoencoder. With one, it is a VQ-VAE: the encoder’s vectors are quantized (straight-through) before decoding and the codebook is refit every refit_codebook_every epochs on the current embeddings. commitment weights the VQ codebook-commitment term.

Architecture and training controls are validated rather than truncated: epochs=0, -2, and .9 each used to return an ordinary result carrying a randomly initialized encoder and an empty loss history – an untrained representation indistinguishable from a trained one. The global Torch RNG is seeded for reproducibility and restored on the way out, so fitting a representation does not silently reseed the caller’s other Torch randomness.

Raises:
  • ValueError – for non-finite/ragged/empty units or a non-exact-positive control.

  • AutoencoderFitError – if the loss goes non-finite – training did not complete, so there is no trained representation to return.

Parameters:
Return type:

AutoencoderResult