Quantization with mse loss. Gradients for the codebook are computed only from MSE loss, while the gradients for the inputs are computed from both MSE and decoder losses approximated using the straight-through estimator. Args: inputs: Tensor of shape [bat
(self, inputs: Tensor, *, paddings: Tensor)
| 455 | return None |
| 456 | |
| 457 | def forward(self, inputs: Tensor, *, paddings: Tensor) -> BaseQuantizer.Output: |
| 458 | """Quantization with mse loss. |
| 459 | |
| 460 | Gradients for the codebook are computed only from MSE loss, while the gradients for |
| 461 | the inputs are computed from both MSE and decoder losses approximated using |
| 462 | the straight-through estimator. |
| 463 | |
| 464 | Args: |
| 465 | inputs: Tensor of shape [batch_size, seq_len, input_dim]. input_dim must equal to |
| 466 | cfg.num_codebooks * cfg.codebook_dim. |
| 467 | paddings: 0/1 Tensor of shape [batch_size, seq_len]. |
| 468 | |
| 469 | Returns: |
| 470 | BaseQuantizer.Output. |
| 471 | module_outputs contains kmeans_loss and commitment_loss. |
| 472 | |
| 473 | Raises: |
| 474 | ValueError: if inputs' last dimension does not match with the codebook dimensions. |
| 475 | """ |
| 476 | cfg = self.config |
| 477 | input_dim = cfg.num_codebooks * cfg.codebook_dim |
| 478 | batch_size, seq_len = inputs.shape[:2] |
| 479 | if inputs.shape[-1] != input_dim: |
| 480 | raise ValueError( |
| 481 | "inputs feature dimension should match with dims from all codebooks." |
| 482 | f"{inputs.shape[-1]} != {cfg.num_codebooks} x {cfg.codebook_dim}." |
| 483 | ) |
| 484 | inputs_by_group = jnp.reshape( |
| 485 | inputs, [batch_size, seq_len, cfg.num_codebooks, cfg.codebook_dim] |
| 486 | ) |
| 487 | quantized_inputs = quantize_by_nearest_neighbor( |
| 488 | inputs=inputs_by_group, |
| 489 | codebook=self.parameters["codebook"], |
| 490 | metric=( |
| 491 | SimilarityMetric.DOT_PRODUCT |
| 492 | if cfg.normalize_codebook |
| 493 | else SimilarityMetric.L2_DISTANCE |
| 494 | ), |
| 495 | ) |
| 496 | if cfg.normalize_inputs: |
| 497 | inputs_by_group = l2_normalize(inputs_by_group, axis=-1, eps=1e-12) |
| 498 | if cfg.normalize_codebook: |
| 499 | self.parameters["codebook"] = l2_normalize( |
| 500 | self.parameters["codebook"], axis=-1, eps=1e-12 |
| 501 | ) |
| 502 | quantized_inputs = _apply_paddings(outputs=quantized_inputs, paddings=paddings) |
| 503 | |
| 504 | # [batch_size, seq_len, input_dim]. |
| 505 | q_vecs = jnp.reshape(quantized_inputs.quantized_vectors, [batch_size, seq_len, input_dim]) |
| 506 | |
| 507 | # Compute mean squared errors between q_vecs and inputs on non-padded frames. |
| 508 | # Number of valid frames * input_dim. |
| 509 | num_frames = jnp.sum(safe_not(paddings)) |
| 510 | denominator = jnp.maximum(num_frames * input_dim, 1) |
| 511 | # Eq.3 of VQ-VAE paper https://arxiv.org/pdf/1711.00937.pdf. |
| 512 | # The codebook is optimized by kmeans_loss only. |
| 513 | inputs_to_loss = ( |
| 514 | jnp.reshape(inputs_by_group, [batch_size, seq_len, -1]) |
nothing calls this directly
no test coverage detected