CompressAI Documentation

repository·master·Indexed 23 days ago

https://github.com/interdigitalinc/compressai

A PyTorch library and evaluation platform for end-to-end compression research. CompressAI provides custom deep learning layers, pre-trained models, and tools to compare learned compression models against classical codecs. It includes support for image, video, and point cloud datasets, as well as utilities for training with rate-distortion loss, evaluating models on datasets like Kodak, and converting models into standalone C++ encoders/decoders using the SADL submodule.

Tokens
10.5K
Snippets
25
Records
78
Agent score
82%

What's inside CompressAI

  1. Overview of CompressAI capabilities

    master

    CompressAI is a PyTorch-based library designed for deep learning-based data compression. It provides the following core resources:

    • Custom Operations & Models: Specialized layers and models for deep learning compression tasks.
    • TensorFlow Compression Port: A partial port of the official tensorflow/compression library.
    • Pre-trained Models: A collection of end-to-end compression models for learned image compression (available in the Model Zoo).
    • Evaluation Tools: Scripts to compare learned machine learning models against classical image and video compression codecs.
  2. What is a LatentCodec and how does it work?

    master

    A LatentCodec is an abstraction used to compress a latent space using various entropy modeling techniques. It functions as a miniature version of a CompressionModel, implementing the core methods forward, compress, and decompress.

    By composing different LatentCodec subclasses, you can build complex entropy models (e.g., combining a side-information branch for 'z' with a conditional branch for 'y'). This modularity allows for easy swapping between different modeling strategies like factorized, hyperprior, raster-scan autoregressive, checkerboard, or channel conditional groups.

    class LatentCodec(nn.Module):
        def forward(self, y: Tensor, *args, **kwargs) -> Dict[str, Any]:
            raise NotImplementedError
    
        def compress(self, y: Tensor, *args, **kwargs) -> Dict[str, Any]:
            raise NotImplementedError
    
        def decompress(
            self, strings: List[List[bytes]], shape: Any, *args, **kwargs
        ) -> Dict[str, Any]:
            raise NotImplementedError
  3. Access pre-trained compression models in the Model Zoo

    master
    CompressAI provides a 'Model Zoo' containing pre-trained models for various compression tasks. These models are trained at different bit-rate distortion points and using different metrics. For specific details on how to load and use these models, refer to the Model Zoo documentation section.
  4. Implement Rate-Distortion and Auxiliary loss functions

    master

    Training a compression model requires balancing reconstruction quality (distortion) against bit-rate (rate), typically using a loss term $\mathcal{L} = \mathcal{D} + \lambda * \mathcal{R}$.

    1. Rate-Distortion Loss:

      • Distortion ($\mathcal{D}$): Usually Mean Squared Error (F.mse_loss) between input $x$ and reconstruction $\hat{x}$.
      • Rate ($\mathcal{R}$): Calculated using the log-likelihoods from the entropy bottleneck. The bits-per-pixel (bpp) loss is calculated as: torch.log(y_likelihoods).sum() / (-math.log(2) * num_pixels).
    2. Auxiliary Loss: The entropy bottleneck parameters must be trained to minimize the density model evaluation. This is accessed via net.entropy_bottleneck.loss() or, if using CompressionModel, via the net.aux_loss() method.

    import math
    import torch.nn as nn
    import torch.nn.functional as F
    
    x = torch.rand(1, 3, 64, 64)
    net = Network()
    x_hat, y_likelihoods = net(x)
    
    # bitrate of the quantized latent
    N, _, H, W = x.size()
    num_pixels = N * H * W
    bpp_loss = torch.log(y_likelihoods).sum() / (-math.log(2) * num_pixels)
    
    # mean square error
    mse_loss = F.mse_loss(x, x_hat)
    
    # final loss term
    loss = mse_loss + lmbda * bpp_loss
  5. Switch between training and evaluation modes

    master

    Compression models behave differently depending on whether they are in training or evaluation mode. For example, quantization operations may be performed differently. Use standard PyTorch methods to switch modes:

    • model.train(): Sets the model to training mode.
    • model.eval(): Sets the model to evaluation mode (typically used for inference/compression tasks).
  6. Compute metrics on 8-bit reconstructed images

    master

    When evaluating image models, standard PSNR and MS-SSIM are typically computed on floating-point reconstructed pictures. However, to ensure fair comparisons with traditional codecs, you should compute metrics on 8-bit rescaled reconstructed images (matching the input format).

    The compressai.utils.eval_model implementation now includes support for computing metrics on 8-bit reconstructed images automatically.

  7. Configure and use entropy coders

    master

    CompressAI uses a range Asymmetric Numeral Systems (ANS) entropy coder by default.

    • To see a list of implemented entropy coders, use compressai.available_entropy_coders().
    • To change the default entropy coder, use compressai.set_entropy_coder().

    Manual Compression/Decompression Workflow

    To manually handle the bit-stream via the entropy bottleneck:

    1. Compress: Encode the image tensor, then compress the resulting latent representation into bit-strings.
    2. Decompress: Decompress the bit-strings back into a latent representation (providing the original shape), then decode the latent representation back into an image tensor.
    # 1. Compress an image tensor to a bit-stream
    x = torch.rand(1, 3, 64, 64)
    y = net.encode(x)
    strings = net.entropy_bottleneck.compress(y)
    
    # 2. Decompress a bit-stream to an image tensor
    shape = y.size()[2:]
    y_hat = net.entropy_bottleneck.decompress(strings, shape)
    x_hat = net.decode(y_hat)
  8. Install CompressAI

    master

    CompressAI requires Python 3.8+ and PyTorch 1.7+. You can install it via pip or from source.

    Using pip: Wheels are available for Linux and MacOS.

    From source: Requires a C++17 compiler, pip 19.0+, and standard Python packages. It is recommended to install in a virtual environment.

    Development/Tutorial installations: You can install specific extras for development or tutorials using pip editable mode.

    # Standard installation
    pip install compressai
    
    # Install development version from source
    git clone https://github.com/InterDigitalInc/CompressAI compressai
    cd compressai
    pip install -U pip && pip install -e .
    
    # Install with development dependencies (testing, linting, docs)
    pip install -e '.[dev]'
    
    # Install with tutorial dependencies (notebooks)
    pip install -e '.[tutorials]'
  9. Train a custom model using CompressionModel

    master

    When inheriting from compressai.models.CompressionModel, you can simplify the training loop by separating the compression network parameters from the entropy bottleneck (quantiles) parameters. This allows you to use two different optimizers.

    To identify the parameter groups:

    • Compression parameters: All parameters except those ending in .quantiles.
    • Auxiliary parameters: Parameters ending in .quantiles.

    Example training loop structure:

    1. Zero both optimizers.
    2. Forward pass to get $\hat{x}$ and y_likelihoods.
    3. Compute and backpropagate the rate-distortion loss using the main optimizer.
    4. Compute and backpropagate the auxiliary loss using the auxiliary optimizer.
    from compressai.models import CompressionModel
    from compressai.models.utils import conv, deconv
    
    class Network(CompressionModel):
        def __init__(self, N=128):
            super().__init__()
            self.encode = nn.Sequential(
                conv(3, N),
                GDN(N),
                conv(N, N),
                GDN(N),
                conv(N, N),
            )
    
            self.decode = nn.Sequential(
                deconv(N, N),
                GDN(N, inverse=True),
                deconv(N, N),
                GDN(N, inverse=True),
                deconv(N, 3),
            )
    
        def forward(self, x):
            y = self.encode(x)
            y_hat, y_likelihoods = self.entropy_bottleneck(y)
            x_hat = self.decode(y_hat)
            return x_hat, y_likelihoods
    
    # Optimizer setup
    parameters = set(p for n, p in net.named_parameters() if not n.endswith(".quantiles"))
    aux_parameters = set(p for n, p in net.named_parameters() if n.endswith(".quantiles"))
    optimizer = optim.Adam(parameters, lr=1e-4)
    aux_optimizer = optim.Adam(aux_parameters, lr=1e-3)
    
    # Training loop
    x = torch.rand(1, 3, 64, 64)
    for i in range(10):
        optimizer.zero_grad()
        aux_optimizer.zero_grad()
    
        x_hat, y_likelihoods = net(x)
        # ... compute loss ...
        loss.backward()
        optimizer.step()
    
        aux_loss = net.aux_loss()
        aux_loss.backward()
        aux_optimizer.step()