VectorQuantizer
ModuleVectorQuantizer(num_embeddings: int, embedding_dim: int, commitment_cost: float = 0.25, device: DeviceLike = None, dtype: DTypeLike = None)Nearest-neighbour codebook lookup with a straight-through gradient.
Maps each position of a continuous feature field to the closest entry of a learned codebook :
This is the discretisation layer of van den Oord, Vinyals, and Kavukcuoglu, "Neural Discrete Representation Learning" (2017) — the bottleneck that turns an auto-encoder into a tokeniser whose latent is an integer field a downstream model can treat as a vocabulary.
Like Linear and Embedding, the layer acts on the
trailing axis: an input of shape (*, embedding_dim) produces a
quantised field of the same shape and an index field of shape (*).
Image models holding (N, C, H, W) should permute the channel axis
last before calling and back afterwards.
Because has zero gradient almost everywhere, the
forward value is routed through lucid.nn.functional. straight_through, so the producer of x trains as if the
quantisation were the identity. The codebook itself receives no
gradient from that path, which is why the layer also returns the two
terms that train it — see VectorQuantizerOutput.
Parameters
num_embeddingsintembedding_dimintcommitment_costfloat= 0.25commitment_loss. Stored for introspection and reused by
loss; the returned commitment_loss is unweighted so
callers can log the raw term. Default 0.25 (the paper's
value).deviceDeviceLike= NonedtypeDTypeLike= NoneAttributes
weightParameter(num_embeddings, embedding_dim).
Initialised Uniform(-1/K, 1/K): entries must start inside the
range the producer emits early in training, or a subset is never
selected and never receives gradient.Notes
Reference: van den Oord, Vinyals, and Kavukcuoglu, NeurIPS, 2017 (arXiv:1711.00937). The straight-through estimator is Bengio, Léonard, and Courville (arXiv:1308.3432).
Distances go through lucid.cdist, whose p=2 path uses the
numerically stable expansion
rather than
materialising an (N, K, D) difference.
Perplexity is computed on every forward. It costs one (N, K)
one-hot, the same order as the distance matrix already built, so it is
always on rather than gated behind a flag — codebook collapse is the
dominant failure mode of this layer and is invisible in the loss.
Examples
>>> import lucid
>>> import lucid.nn as nn
>>> vq = nn.VectorQuantizer(num_embeddings=64, embedding_dim=8)
>>> x = lucid.randn((2, 5, 8)) # (batch, positions, D)
>>> out = vq(x)
>>> out.quantized.shape, out.indices.shape
((2, 5, 8), (2, 5))
>>> bool((out.indices.max() < 64).item())
TrueUsed by 1
Constructors
1Instance methods
5Return the nearest-entry index field for x, shape (*).
Return a string representation of the layer's configuration.
forward(x: Tensor)Quantise x along its trailing axis.
Map an index field (*) back to codes (*, embedding_dim).
Combine the two codebook terms using this layer's commitment_cost.