Vector Quantization module using Exponential Moving Average (EMA) to learn the codebook parameters based on Neural Discrete Representation Learning by Oord et al. (https://arxiv.org/abs/1711.00937) and the official implementation that can be found at https://github.com/deepmind/sonnet/
| 20 | |
| 21 | |
| 22 | class EMAQuantizer(nn.Module): |
| 23 | """ |
| 24 | Vector Quantization module using Exponential Moving Average (EMA) to learn the codebook parameters based on Neural |
| 25 | Discrete Representation Learning by Oord et al. (https://arxiv.org/abs/1711.00937) and the official implementation |
| 26 | that can be found at https://github.com/deepmind/sonnet/blob/v2/sonnet/src/nets/vqvae.py#L148 and commit |
| 27 | 58d9a2746493717a7c9252938da7efa6006f3739. |
| 28 | |
| 29 | This module is not compatible with TorchScript while working in a Distributed Data Parallelism Module. This is due |
| 30 | to lack of TorchScript support for torch.distributed module as per https://github.com/pytorch/pytorch/issues/41353 |
| 31 | on 22/10/2022. If you want to TorchScript your model, please turn set `ddp_sync` to False. |
| 32 | |
| 33 | Args: |
| 34 | spatial_dims: number of spatial dimensions of the input. |
| 35 | num_embeddings: number of atomic elements in the codebook. |
| 36 | embedding_dim: number of channels of the input and atomic elements. |
| 37 | commitment_cost: scaling factor of the MSE loss between input and its quantized version. Defaults to 0.25. |
| 38 | decay: EMA decay. Defaults to 0.99. |
| 39 | epsilon: epsilon value. Defaults to 1e-5. |
| 40 | embedding_init: initialization method for the codebook. Defaults to "normal". |
| 41 | ddp_sync: whether to synchronize the codebook across processes. Defaults to True. |
| 42 | """ |
| 43 | |
| 44 | def __init__( |
| 45 | self, |
| 46 | spatial_dims: int, |
| 47 | num_embeddings: int, |
| 48 | embedding_dim: int, |
| 49 | commitment_cost: float = 0.25, |
| 50 | decay: float = 0.99, |
| 51 | epsilon: float = 1e-5, |
| 52 | embedding_init: str = "normal", |
| 53 | ddp_sync: bool = True, |
| 54 | ): |
| 55 | super().__init__() |
| 56 | self.spatial_dims: int = spatial_dims |
| 57 | self.embedding_dim: int = embedding_dim |
| 58 | self.num_embeddings: int = num_embeddings |
| 59 | |
| 60 | assert self.spatial_dims in [2, 3], ValueError( |
| 61 | f"EMAQuantizer only supports 4D and 5D tensor inputs but received spatial dims {spatial_dims}." |
| 62 | ) |
| 63 | |
| 64 | self.embedding: torch.nn.Embedding = torch.nn.Embedding(self.num_embeddings, self.embedding_dim) |
| 65 | if embedding_init == "normal": |
| 66 | # Initialization is passed since the default one is normal inside the nn.Embedding |
| 67 | pass |
| 68 | elif embedding_init == "kaiming_uniform": |
| 69 | torch.nn.init.kaiming_uniform_(self.embedding.weight.data, mode="fan_in", nonlinearity="linear") |
| 70 | self.embedding.weight.requires_grad = False |
| 71 | |
| 72 | self.commitment_cost: float = commitment_cost |
| 73 | |
| 74 | self.register_buffer("ema_cluster_size", torch.zeros(self.num_embeddings)) |
| 75 | self.register_buffer("ema_w", self.embedding.weight.data.clone()) |
| 76 | # declare types for mypy |
| 77 | self.ema_cluster_size: torch.Tensor |
| 78 | self.ema_w: torch.Tensor |
| 79 | self.decay: float = decay |
no outgoing calls
searching dependent graphs…