vector-quantize-pytorch

repository·master·Indexed 26 days ago

https://github.com/lucidrains/vector-quantize-pytorch

A PyTorch library for vector quantization providing implementations of standard VQ, Residual VQ (RVQ), and Grouped Residual VQ. It includes advanced techniques such as DiVeQ for gradient-based codebook updates, the rotation trick, Finite Scalar Quantization (FSQ), Lookup-Free Quantization (LFQ), and Finite Scalar Perturbation (FSP). The library also features specialized modules like SimVQ, LatentQuantize, RandomProjectionQuantizer, and BinaryMapper for mapping continuous logits to binary representations.

Tokens
13.2K
Snippets
16
Records
87
Agent score
87%

What's inside vector-quantize-pytorch

  1. Combat dead codebook entries in VectorQuantize

    master

    To prevent 'dead' codebook entries in VectorQuantize, you can use several techniques:

    1. Lower codebook dimension: Project encoder values to a lower dimension before quantization using codebook_dim.
    2. Cosine similarity: Use L2 normalization for codes and encoded vectors by setting use_cosine_sim = True.
    3. Expiring stale codes: Replace codes with low EMA cluster sizes using threshold_ema_dead_code (e.g., set to 2 to replace codes with fewer than 2 hits).
    import torch
    from vector_quantize_pytorch import VectorQuantize
    
    # Example: Lower codebook dimension
    vq = VectorQuantize(
        dim = 256,
        codebook_size = 256,
        codebook_dim = 16
    )
    
    # Example: Cosine similarity
    vq = VectorQuantize(
        dim = 256,
        codebook_size = 256,
        use_cosine_sim = True
    )
    
    # Example: Expiring stale codes
    vq = VectorQuantize(
        dim = 256,
        codebook_size = 512,
        threshold_ema_dead_code = 2
    )
  2. Initialize codebooks with K-Means

    master

    To initialize codebooks using the k-means centroids of the first batch (as proposed in SoundStream), set kmeans_init = True in either VectorQuantize or ResidualVQ.

    from vector_quantize_pytorch import ResidualVQ
    
    residual_vq = ResidualVQ(
        dim = 256,
        codebook_size = 256,
        num_quantizers = 4,
        kmeans_init = True,
        kmeans_iters = 10
    )
  3. Handle variable length sequences with mask or lens

    master

    To handle sequences with padding, you can provide either a boolean mask or a tensor of sequence lens to the forward method.

    • If lens is provided, it is converted to a mask internally.
    • Note: You cannot provide both mask and lens simultaneously.
    • When a mask is used, the returned quantize tensor can either contain the original input values or zeros at masked positions, depending on the return_zeros_for_masked_padding configuration.
    • The returned embed_ind will have -1 at masked positions.
  4. Use the GroupedResidualVQ class

    master

    The GroupedResidualVQ class performs residual VQ on groups of the feature dimension. This allows for efficient quantization using fewer codebooks.

    Parameters:

    • dim: The dimensionality of the input vectors.
    • num_quantizers: Number of quantizers to use.
    • groups: The number of groups to split the dimension into.
    • codebook_size: The size of each codebook.
    import torch
    from vector_quantize_pytorch import GroupedResidualVQ
    
    residual_vq = GroupedResidualVQ(
        dim = 256,
        num_quantizers = 8,
        groups = 2,
        codebook_size = 1024,
    )
    
    x = torch.randn(1, 1024, 256)
    quantized, indices, commit_loss = residual_vq(x)
  5. Use the ResidualVQ class

    master

    The ResidualVQ class implements residual vector quantization, which uses multiple quantizers to recursively quantize residuals. This is useful for high-quality audio or image generation.

    Parameters:

    • dim: The dimensionality of the input vectors.
    • num_quantizers: Number of quantizers to use.
    • codebook_size: The size of each codebook.
    • diveq: Set to True to use the DiVeQ technique (gradient-based codebook updates) instead of EMA.
    • stochastic_sample_codes: Set to True to stochastically sample codes (RQ-VAE style).
    • sample_codebook_temp: Temperature for stochastic sampling.
    • shared_codebook: Set to True to share the same codebook across all quantizers.
    • kmeans_init: Set to True to initialize the codebook using k-means centroids of the first batch.
    • kmeans_iters: Number of k-means iterations for initialization.

    Returns (on call):

    • quantized: The quantized vectors.
    • indices: The indices for each quantization layer.
    • commit_loss: The commitment loss.
    • all_codes: (Optional) If return_all_codes=True is passed to the call, returns all codes across quantization layers.
    import torch
    from vector_quantize_pytorch import ResidualVQ
    
    residual_vq = ResidualVQ(
        dim = 256,
        num_quantizers = 8,
        codebook_size = 1024,
    )
    
    x = torch.randn(1, 1024, 256)
    
    # Standard call
    quantized, indices, commit_loss = residual_vq(x)
    
    # Get all codes across layers
    quantized, indices, commit_loss, all_codes = residual_vq(x, return_all_codes = True)
  6. Use the VectorQuantize class

    master

    The VectorQuantize class implements standard vector quantization using exponential moving averages (EMA) to update the dictionary. It is suitable for tasks like VQ-VAE.

    Parameters:

    • dim: The dimensionality of the input vectors.
    • codebook_size: The number of vectors in the codebook.
    • decay: The EMA decay (lower values make the dictionary change faster).
    • commitment_weight: The weight applied to the commitment loss.
    • rotation_trick: (Optional) Set to True to use the rotation trick for gradient computation; otherwise, it uses the straight-through estimator (STE).
    • directional_reparam: (Optional) Set to True to use the DiVeQ method for gradient computation.
    • directional_reparam_variance: (Optional) Variance for the DiVeQ method.

    Returns (on call):

    • quantized: The quantized vectors.
    • indices: The indices of the chosen codebook vectors.
    • commit_loss: The commitment loss.
    import torch
    from vector_quantize_pytorch import VectorQuantize
    
    vq = VectorQuantize(
        dim = 256,
        codebook_size = 512,
        decay = 0.8,
        commitment_weight = 1.
    )
    
    x = torch.randn(1, 1024, 256)
    quantized, indices, commit_loss = vq(x) # (1, 1024, 256), (1, 1024), (1)
  7. Use RandomProjectionQuantizer

    master

    The RandomProjectionQuantizer uses a randomly initialized matrix and codebook, meaning the quantizer does not need to be learned. This is useful for masked speech modeling.

    • num_codebooks: Set to > 1 to support multiple codebooks (e.g., for USM-style modeling).
    import torch
    from vector_quantize_pytorch import RandomProjectionQuantizer
    
    quantizer = RandomProjectionQuantizer(
        dim = 512,
        num_codebooks = 16,
        codebook_dim = 256,
        codebook_size = 1024
    )
    
    x = torch.randn(1, 1024, 512)
    indices = quantizer(x)
    # indices shape: (1, 1024, 16)
  8. Use Finite Scalar Perturbation (FSP)

    master

    FSP treats discretization as structured noise injected into continuous representations. It differs from FSQ by perturbing the continuous variable during training and using bin centers as targets.

    • levels: Number of bins per scalar dimension.
    • act_name: CDF activation (tanh, sigmoid, normal, laplace, or cauchy).
    • quantize_rate: Stochasticity level (0. is full stochastic perturbation, 1. is no perturbation).
    • vector_norm: Statistical regularization (none, var, kurt, var_tanh, var_sigmoid, etc.).
    import torch
    from vector_quantize_pytorch import FSP
    
    quantizer = FSP(
        levels = [8, 5, 5, 5],
        act_name = 'normal',
        quantize_rate = 0.5,
        vector_norm = 'var'
    )
    
    x = torch.randn(1, 1024, 4)
    quantized, indices, norm_loss, other_info = quantizer(x)
  9. Use Lookup Free Quantization (LFQ)

    master

    LFQ eliminates the codebook and embedding lookup entirely using independent binary latents. It supports image, video, and sequence inputs.

    • codebook_size: Must be a power of 2.
    • dim: Input feature dimension (defaults to log2(codebook_size) if not defined).
    • entropy_loss_weight: Weight for entropy loss.
    • diversity_gamma: Weight for diversity of codes within entropy loss.
    • num_codebooks: Supports multiple codebooks.
    • ResidualLFQ: An improvised residual version for audio compression.
    import torch
    from vector_quantize_pytorch import LFQ, ResidualLFQ
    
    # Standard LFQ
    quantizer = LFQ(
        codebook_size = 65536,
        dim = 16,
        entropy_loss_weight = 0.1,
        diversity_gamma = 1.
    )
    
    image_feats = torch.randn(1, 16, 32, 32)
    quantized, indices, entropy_aux_loss = quantizer(image_feats, inv_temperature=100.)
    
    # Residual LFQ
    residual_lfq = ResidualLFQ(
        dim = 256,
        codebook_size = 256,
        num_quantizers = 8
    )
  10. Use Latent Quantization

    master

    LatentQuantize encodes and decodes within an organized latent space by assigning discrete code vectors through an individual learnable scalar codebook for each dimension.

    • levels: Number of levels per codebook dimension.
    • dim: Input dimension.
    • num_codebooks: Supports multiple codebooks.
    • Supports input shapes: (batch, feat, height, width), (batch, seq, feat), and (batch, feat, time, height, width).
    import torch
    from vector_quantize_pytorch import LatentQuantize
    
    # Single codebook
    quantizer = LatentQuantize(
        levels = [5, 5, 8],
        dim = 16,
        commitment_loss_weight=0.1,
        quantization_loss_weight=0.1,
    )
    
    # Multiple codebooks
    model = LatentQuantize(
        levels = [4, 8, 16],
        dim = 9,
        num_codebooks = 3
    )
    
    input_tensor = torch.randn(2, 3, 9)
    output_tensor, indices, loss = model(input_tensor)
  11. Use Multi-headed VectorQuantize

    master

    Implement a multi-headed approach where the same codebook is used to quantize across the input dimension head times.

    • heads: Number of heads to quantize.
    • separate_codebook_per_head: If True, each head has its own codebook. If False, all heads share one codebook.
    import torch
    from vector_quantize_pytorch import VectorQuantize
    
    vq = VectorQuantize(
        dim = 256,
        codebook_dim = 32,
        heads = 8,
        separate_codebook_per_head = True,
        codebook_size = 8196,
        accept_image_fmap = True
    )
    
    img_fmap = torch.randn(1, 256, 32, 32)
    quantized, indices, loss = vq(img_fmap)
    # quantized shape: (1, 256, 32, 32)
    # indices shape: (1, 32, 32, 8)