Quantization using Gumbel softmax trick. The code is selected based on the largest index of inputs. Inputs Gradients is computed with Gumbel softmax straight-through estimator. Args: inputs: tensor of shape [batch_size, seq_len, input_dim]. paddings:
( # pytype: disable=signature-mismatch
self, inputs: Tensor, *, paddings: Tensor
)
| 608 | return params |
| 609 | |
| 610 | def forward( # pytype: disable=signature-mismatch |
| 611 | self, inputs: Tensor, *, paddings: Tensor |
| 612 | ) -> tuple[BaseQuantizer.Output, dict[str, Tensor]]: |
| 613 | """Quantization using Gumbel softmax trick. |
| 614 | |
| 615 | The code is selected based on the largest index of inputs. Inputs Gradients is computed |
| 616 | with Gumbel softmax straight-through estimator. |
| 617 | |
| 618 | Args: |
| 619 | inputs: tensor of shape [batch_size, seq_len, input_dim]. |
| 620 | paddings: 0/1 Tensor of shape [batch_size, seq_len]. |
| 621 | |
| 622 | Returns: |
| 623 | BaseQuantizer.Output. |
| 624 | module_outputs contains temperature `tau` and prediction probability `probs`. |
| 625 | """ |
| 626 | cfg = self.config |
| 627 | # [batch_size, seq_len, num_codebooks, vocab_size]. |
| 628 | logits = self.input_proj(inputs=inputs) |
| 629 | |
| 630 | if self.is_training: |
| 631 | tau = self.temperature_schedule(self.parameters["step"]) |
| 632 | logits = ( |
| 633 | logits + jax.random.gumbel(self.prng_key, shape=logits.shape, dtype=logits.dtype) |
| 634 | ) / tau |
| 635 | self.add_state_update("step", self.parameters["step"] + 1) |
| 636 | |
| 637 | # [batch_size, seq_len, num_codebooks]. |
| 638 | ids = jnp.argmax(logits, axis=-1) |
| 639 | |
| 640 | if not self.is_training: |
| 641 | outputs = self.lookup(ids=ids) |
| 642 | outputs = _apply_paddings(outputs=outputs, paddings=paddings) |
| 643 | else: |
| 644 | # [batch_size, seq_len, 1]. |
| 645 | mask = safe_not(paddings)[:, :, None] |
| 646 | ids = ids * mask + (-1) * safe_not(mask) |
| 647 | # TODO(dhwang2): optimize memory by scan for long context training. |
| 648 | # [batch_size, seq_len, num_codebooks, vocab_size]. |
| 649 | onehots = _ids_to_onehots(ids, codebook_size=cfg.codebook_size, dtype=inputs.dtype) |
| 650 | # We need this to stop gradients on the padded frames. |
| 651 | onehots = onehots * mask[:, :, :, None] |
| 652 | # [batch_size, seq_len, num_codebooks, vocab_size]. |
| 653 | y_soft = jax.nn.softmax(logits, axis=-1) |
| 654 | y_soft = y_soft * mask[:, :, :, None] |
| 655 | |
| 656 | # Straight-through estimator such that dL/y_soft = dL/onehots. |
| 657 | onehots = y_soft + jax.lax.stop_gradient(onehots - y_soft) |
| 658 | batch_dims = _einsum_dims[: onehots.ndim - 2] |
| 659 | quantized_vectors = jnp.einsum( |
| 660 | f"{batch_dims}gv,vgh->{batch_dims}gh", onehots, self.parameters["codebook"] |
| 661 | ) |
| 662 | quantized_vectors = quantized_vectors * mask[:, :, :, None] |
| 663 | outputs = self.Output( |
| 664 | # [batch_size, seq_len, num_codebooks]. |
| 665 | ids=ids, |
| 666 | # [batch_size, seq_len, num_codebooks, codebook_dim]. |
| 667 | quantized_vectors=quantized_vectors, |
nothing calls this directly
no test coverage detected