compressai.latent_codecs#
A LatentCodec is an abstraction for compressing a latent space using some entropy modeling technique.
A LatentCodec can be thought of as a miniature CompressionModel.
In fact, it implements some of the same methods: forward, compress, and decompress, as described in Defining a custom latent codec.
By composing latent codecs, we can easily create more complex entropy models.
CompressAI provides the following predefined LatentCodec subclasses:
Module name |
Description |
|---|---|
Uses an |
|
Uses a |
|
Uses an |
|
Uses an e.g. |
|
Encodes |
|
Like |
|
Like |
|
Encodes |
|
Encodes |
Diagrams for some of the above predefined latent codecs:
HyperLatentCodec:
βββββ z βββββ z_hat z_hat βββββ
y βββΊβββ€h_aββββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊββββ€h_sββββΊββ params
βββββ βββββ EB βββββ
Entropy bottleneck codec with surrounding `h_a` and `h_s` transforms.
GaussianConditionalLatentCodec:
ctx_params
β
βΌ
β
ββββ΄βββ
β EP β
ββββ¬βββ
β
βββββ y_hat βΌ
y βββΊβββ€ Q ββββββΊββββΒ·Β·Β·Β·βββΊββ y_hat
βββββ GC
Gaussian conditional for compressing latent `y` using `ctx_params`.
HyperpriorLatentCodec:
βββββ z ββββββββ z_hat βββββ
βββΊββ€h_aββββΊβββ€ lc_z βββββΊββββ€h_sβββΊββ
β βββββ ββββββββ βββββ β
β βΌ params
β β
β ββββ΄ββββ
y βββ΄ββββββββββββββββββββΊββββββββββββββ€ lc_y βββββΊββ y_hat
ββββββββ
Composes a "lc_z" latent codec such as EntropyBottleneckLatentCodec,
and a "lc_y" latent codec such as
GaussianConditionalLatentCodec or RasterScanLatentCodec.
RasterScanLatentCodec:
ctx_params
β
βΌ
β βββββββββ
βββ΄ββ΄ββ ββββ΄βββ
β EP β β CP β
ββββ¬βββ ββββ¬βββ
β β
β β²
βββββ y_hat βΌ β
y βββΊβββ€ Q ββββββΊββββΒ·Β·Β·Β·ββββΊβββ΄βββΊββ y_hat
βββββ GC
Rationale#
This abstraction makes it easy to swap between different entropy models such as βfactorizedβ, βhyperpriorβ, βraster scan autoregressiveβ, βcheckerboardβ, or βchannel conditional groupsβ.
It also aids in composition: we may now easily take any complicated composition of the above LatentCodec subclasses. For example, we may create models containing multiple hyperprior branches (Hu et al., 2020), or a βchannel conditional groupβ context model which encodes each group using βraster-scanβ (Minnen et al., 2020) or βcheckerboardβ (He et al., 2022) autoregression, and so on.
Lastly, it reduces code duplication, and favors composition instead of inheritance.
Example models#
A simple VAE model with an arbitrary latent codec can be implemented as follows:
class SimpleVAECompressionModel(CompressionModel):
"""Simple VAE model with arbitrary latent codec.
.. code-block:: none
βββββ y ββββββ y_hat βββββ
x βββΊβββ€g_aββββΊβββ€ lc βββββΊββββ€g_sββββΊββ x_hat
βββββ ββββββ βββββ
"""
g_a: nn.Module
g_s: nn.Module
latent_codec: LatentCodec
def forward(self, x):
y = self.g_a(x)
y_out = self.latent_codec(y)
y_hat = y_out["y_hat"]
x_hat = self.g_s(y_hat)
return {
"x_hat": x_hat,
"likelihoods": y_out["likelihoods"],
}
def compress(self, x):
y = self.g_a(x)
outputs = self.latent_codec.compress(y)
return outputs
def decompress(self, strings, shape):
y_out = self.latent_codec.decompress(strings, shape)
y_hat = y_out["y_hat"]
x_hat = self.g_s(y_hat).clamp_(0, 1)
return {
"x_hat": x_hat,
}
This pattern is so common that CompressAI provides it via the import:
from compressai.models.base import SimpleVAECompressionModel
Using SimpleVAECompressionModel, some Google-style VAE models may be implemented as follows:
@register_model("bmshj2018-factorized")
class FactorizedPrior(SimpleVAECompressionModel):
def __init__(self, N, M, **kwargs):
super().__init__(**kwargs)
self.g_a = nn.Sequential(...)
self.g_s = nn.Sequential(...)
self.latent_codec = EntropyBottleneckLatentCodec(channels=M)
@register_model("mbt2018-mean")
class MeanScaleHyperprior(SimpleVAECompressionModel):
def __init__(self, N, M, **kwargs):
super().__init__(**kwargs)
self.g_a = nn.Sequential(...)
self.g_s = nn.Sequential(...)
h_a = nn.Sequential(...)
h_s = nn.Sequential(...)
self.latent_codec = HyperpriorLatentCodec(
h_a=h_a,
h_s=h_s,
# A HyperpriorLatentCodec is made of "z" and "y" latent codecs.
latent_codec={
# Side-information branch with entropy bottleneck for "z":
"z": EntropyBottleneckLatentCodec(
entropy_bottleneck=EntropyBottleneck(N),
),
# Encode y using GaussianConditional:
"y": GaussianConditionalLatentCodec(),
},
)
@register_model("mbt2018")
class JointAutoregressiveHierarchicalPriors(SimpleVAECompressionModel):
def __init__(self, N, M, **kwargs):
super().__init__(**kwargs)
self.g_a = nn.Sequential(...)
self.g_s = nn.Sequential(...)
h_a = nn.Sequential(...)
h_s = nn.Sequential(...)
self.latent_codec = HyperpriorLatentCodec(
h_a=h_a,
h_s=h_s,
# A HyperpriorLatentCodec is made of "z" and "y" latent codecs.
latent_codec={
# Side-information branch with entropy bottleneck for "z":
"z": EntropyBottleneckLatentCodec(
entropy_bottleneck=EntropyBottleneck(N),
),
# Encode y using autoregression in raster-scan order:
"y": RasterScanLatentCodec(
gaussian_conditional=GaussianConditional(None),
entropy_parameters=nn.Sequential(...),
context_prediction=MaskedConv2d(
M, M * 2, kernel_size=5, padding=2, stride=1
),
),
},
)
Defining a custom latent codec#
Latent codecs should inherit from the abstract base class LatentCodec, which is defined as:
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
Like CompressionModel, a subclass of LatentCodec should implement:
forward: differentiable function for training, returning adictin the form of:{ "likelihoods": { "y": y_likelihoods, ... }, "y_hat": y_hat, }
compress: compressor to generate bitstreams from input tensor, returning adictin the form of:{ "strings": [y_strings, z_strings], "shape": ..., }
decompress: decompressor to reconstruct the input tensors using the bitstreams, returning adictin the form of:{ "y_hat": y_hat, }
Please refer to any of the predefined latent codecs for more concrete examples.
EntropyBottleneckLatentCodec#
- class compressai.latent_codecs.EntropyBottleneckLatentCodec(entropy_bottleneck: Optional[compressai.entropy_models.entropy_models.EntropyBottleneck] = None, quantizer: str = 'noise', **kwargs)[source]#
Entropy bottleneck codec.
Factorized prior βentropy bottleneckβ introduced in βVariational Image Compression with a Scale Hyperpriorβ, by J. Balle, D. Minnen, S. Singh, S.J. Hwang, and N. Johnston, International Conference on Learning Representations (ICLR), 2018.
βββββ y_hat y βββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊβββ y_hat βββββ EB
GaussianConditionalLatentCodec#
- class compressai.latent_codecs.GaussianConditionalLatentCodec(scale_table: Optional[Union[List, Tuple]] = None, gaussian_conditional: Optional[compressai.entropy_models.entropy_models.GaussianConditional] = None, entropy_parameters: Optional[torch.nn.modules.module.Module] = None, quantizer: str = 'noise', chunks: Tuple[str, ...] = ('scales', 'means'), **kwargs)[source]#
Gaussian conditional for compressing latent
yusingctx_params.Probability model for Gaussian of
(scales, means).Gaussian conditonal entropy model introduced in βVariational Image Compression with a Scale Hyperpriorβ, by J. Balle, D. Minnen, S. Singh, S.J. Hwang, and N. Johnston, International Conference on Learning Representations (ICLR), 2018.
Note
Unlike the original paper, which models only the scale (i.e. βwidthβ) of the Gaussian, this implementation models both the scale and the mean (i.e. βcenterβ) of the Gaussian.
ctx_params β βΌ β ββββ΄βββ β EP β ββββ¬βββ β βββββ y_hat βΌ y βββΊβββ€ Q ββββββΊββββΒ·Β·Β·Β·βββΊββ y_hat βββββ GC
HyperLatentCodec#
- class compressai.latent_codecs.HyperLatentCodec(entropy_bottleneck: compressai.entropy_models.entropy_models.EntropyBottleneck, h_a: torch.nn.modules.module.Module, h_s: torch.nn.modules.module.Module, quantizer: str = 'noise', **kwargs)[source]#
Entropy bottleneck codec with surrounding h_a and h_s transforms.
βHyperβ side-information branch introduced in βVariational Image Compression with a Scale Hyperpriorβ, by J. Balle, D. Minnen, S. Singh, S.J. Hwang, and N. Johnston, International Conference on Learning Representations (ICLR), 2018.
Note
HyperLatentCodecshould be used insideHyperpriorLatentCodecto construct a full hyperprior.βββββ z βββββ z_hat z_hat βββββ y βββΊβββ€h_aββββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊββββ€h_sββββΊββ params βββββ βββββ EB βββββ
HyperpriorLatentCodec#
- class compressai.latent_codecs.HyperpriorLatentCodec(latent_codec: Mapping[str, compressai.latent_codecs.base.LatentCodec], h_a: Optional[torch.nn.modules.module.Module] = None, h_s: Optional[torch.nn.modules.module.Module] = None, **kwargs)[source]#
Hyperprior codec constructed from latent codec for
ythat compressesyusingparamsderived fromz_hat.Hyperprior entropy modeling introduced in βVariational Image Compression with a Scale Hyperpriorβ, by J. Balle, D. Minnen, S. Singh, S.J. Hwang, and N. Johnston, International Conference on Learning Representations (ICLR), 2018.
βββββ z ββββββββ z_hat βββββ βββΊββ€h_aββββΊβββ€ lc_z βββββΊββββ€h_sβββΊββ β βββββ ββββββββ βββββ β β βΌ params β β β ββββ΄ββββ y βββ΄ββββββββββββββββββββΊββββββββββββββ€ lc_y βββββΊββ y_hat ββββββββThe original hyperprior is the combination of an entropy bottleneck for
zand a gaussian conditional fory:βββββ z βββββ z_hat z_hat βββββ βββΊβββ€h_aββββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊββββ€h_sββββΊββ β βββββ βββββ EB βββββ β β β β βββββββββββββββββββββββββββββ β β params β ββββ΄βββ β β EP β β ββββ¬βββ β β β βββββ y_hat βΌ y βββ΄ββΊββ€ Q ββββββΊββββΒ·Β·Β·Β·βββββΊββ y_hat βββββ GC- Common configurations of latent codecs include:
entropy bottleneck
zand gaussian conditionalyentropy bottleneck
zand autoregressivey
RasterScanLatentCodec#
- class compressai.latent_codecs.RasterScanLatentCodec(gaussian_conditional: compressai.entropy_models.entropy_models.GaussianConditional, entropy_parameters: torch.nn.modules.module.Module, context_prediction: compressai.layers.layers.MaskedConv2d, **kwargs)[source]#
Autoregression in raster-scan order with local decoded context.
PixelCNN context model introduced in βPixel Recurrent Neural Networksβ, by Aaron van den Oord, Nal Kalchbrenner, and Koray Kavukcuoglu, International Conference on Machine Learning (ICML), 2016.
First applied to learned image compression in βJoint Autoregressive and Hierarchical Priors for Learned Image Compressionβ, by D. Minnen, J. Balle, and G.D. Toderici, Adv. in Neural Information Processing Systems 31 (NeurIPS 2018).
ctx_params β βΌ β βββββββββ βββ΄ββ΄ββ ββββ΄βββ β EP β β CP β ββββ¬βββ ββββ¬βββ β β β β² βββββ y_hat βΌ β y βββΊβββ€ Q ββββββΊββββΒ·Β·Β·Β·ββββΊβββ΄βββΊββ y_hat βββββ GC
GainHyperLatentCodec#
- class compressai.latent_codecs.GainHyperLatentCodec(entropy_bottleneck: compressai.entropy_models.entropy_models.EntropyBottleneck, h_a: torch.nn.modules.module.Module, h_s: torch.nn.modules.module.Module, **kwargs)[source]#
Entropy bottleneck codec with surrounding h_a and h_s transforms.
Gain-controlled side branch for hyperprior introduced in βAsymmetric Gained Deep Image Compression With Continuous Rate Adaptationβ, by Ze Cui, Jing Wang, Shangyin Gao, Bo Bai, Tiansheng Guo, and Yihui Feng, CVPR, 2021.
Note
GainHyperLatentCodecshould be used insideGainHyperpriorLatentCodecto construct a full hyperprior.gain gain_inv β β βΌ βΌ βββββ z β βββββ z_hat z_hat β βββββ y βββΊβββ€h_aββββΊββΓβββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊββββΓβββββΊβββ€h_sββββΊββ params βββββ βββββ EB βββββ
GainHyperpriorLatentCodec#
- class compressai.latent_codecs.GainHyperpriorLatentCodec(latent_codec: Mapping[str, compressai.latent_codecs.base.LatentCodec], h_a: Optional[torch.nn.modules.module.Module] = None, h_s: Optional[torch.nn.modules.module.Module] = None, **kwargs)[source]#
Hyperprior codec constructed from latent codec for
ythat compressesyusingparamsderived fromz_hat.Gain-controlled hyperprior introduced in βAsymmetric Gained Deep Image Compression With Continuous Rate Adaptationβ, by Ze Cui, Jing Wang, Shangyin Gao, Bo Bai, Tiansheng Guo, and Yihui Feng, CVPR, 2021.
z_gain z_gain_inv β β βΌ βΌ βββββ z ββ΄βββββββββ΄β z_hat βββββ βββΊββ€h_aββββΊβββ€ lc_z βββββΊββββ€h_sββββΊββ β βββββ ββββββββββββ βββββ β β β β y_gain βΌ params y_gain_inv β β β β β βΌ β βΌ β β ββββ΄ββββ β y βββ΄ββββββββββββββββΊβββΓββββΊβββββββββββββββ€ lc_y ββββββΊβββββΓββββββΊββ y_hat ββββββββThe original gain hyperprior is the combination of an entropy bottleneck for
zand a gaussian conditional fory:z_gain z_gain_inv β β βΌ βΌ βββββ z β z_g βββββ z_hat z_hat β βββββ βββΊβββ€h_aββββΊββΓβββΊβββ€ Q βββββΊβββΒ·Β·Β·Β·ββββΊββββΓβββββΊβββ€h_sββββ β βββββ βββββ EB βββββ β β β β ββββββββββββββββββββββββββββββ β β params β ββββ΄βββ β y_gain β EP β y_gain_inv β β ββββ¬βββ β β βΌ β βΌ β β βββββ βΌ β y βββ΄ββββΊβββΓββββΊββββ€ Q ββββββΊββββΒ·Β·Β·Β·ββββΊβββββΓββββββΊββ y_hat βββββ GC- Common configurations of latent codecs include:
entropy bottleneck
zand gaussian conditionalyentropy bottleneck
zand autoregressivey
ChannelGroupsLatentCodec#
- class compressai.latent_codecs.ChannelGroupsLatentCodec(latent_codec: Mapping[str, compressai.latent_codecs.base.LatentCodec], channel_context: Mapping[str, torch.nn.modules.module.Module], *, groups: List[int], support_slices: Optional[List[List[int]]] = None, **kwargs)[source]#
Reconstructs groups of channels using previously decoded groups.
Context model from [Minnen2020] and [He2022]. Also known as a βchannel-conditionalβ (CC) entropy model.
See
Elic2022Officialfor example usage.[Minnen2020]: βChannel-wise Autoregressive Entropy Models for Learned Image Compressionβ, by David Minnen, and Saurabh Singh, ICIP 2020.
[He2022]: βELIC: Efficient Learned Image Compression with Unevenly Grouped Space-Channel Contextual Adaptive Codingβ, by Dailan He, Ziming Yang, Weikun Peng, Rui Ma, Hongwei Qin, and Yan Wang, CVPR 2022.
CheckerboardLatentCodec#
- class compressai.latent_codecs.CheckerboardLatentCodec(latent_codec: Mapping[str, compressai.latent_codecs.base.LatentCodec], entropy_parameters: torch.nn.modules.module.Module, context_prediction: compressai.layers.layers.CheckerboardMaskedConv2d, anchor_parity='even', forward_method='twopass', **kwargs)[source]#
Reconstructs latent using 2-pass context model with checkerboard anchors.
Checkerboard context model introduced in [He2021].
See
Cheng2020AnchorCheckerboardfor example usage.forward_method=βonepassβ is fastest, but does not use quantization based on the intermediate means. Uses noise to model quantization.
forward_method=βtwopassβ is slightly slower, but accurately quantizes via STE based on the intermediate means. Uses the same operations as [Chandelier2023].
forward_method=βtwopass_fasterβ uses slightly fewer redundant operations.
[He2021]: βCheckerboard Context Model for Efficient Learned Image Compressionβ, by Dailan He, Yaoyan Zheng, Baocheng Sun, Yan Wang, and Hongwei Qin, CVPR 2021.
[Chandelier2023]: βELiC-ReImplemetationβ, by Vincent Chandelier, 2023.
Warning
This implementation assumes that
entropy_parametersis a pointwise function, e.g., a composition of 1x1 convs and pointwise nonlinearities.0. Input: β‘ β‘ β‘ β‘ β‘ β‘ β‘ β‘ β‘ β‘ β‘ β‘ 1. Decode anchors: β β‘ β β‘ β‘ β β‘ β β β‘ β β‘ 2. Decode non-anchors: β β β β β β β β β β β β 3. End result: β β β β β β β β β β β β LEGEND: β decoded β currently decoding β‘ empty