CTC greedy decoding. The output hypotheses will have blanks and repeats removed (via `_map_label_sequences`). Args: input_batch: A dict containing: inputs: A Tensor of shape [batch_size, num_frames, dim]. paddings: A 0/1 Tensor of shape [
(self, input_batch: Nested[Tensor])
| 558 | ) |
| 559 | |
| 560 | def greedy_decode(self, input_batch: Nested[Tensor]) -> DecodeOutputs: |
| 561 | """CTC greedy decoding. |
| 562 | |
| 563 | The output hypotheses will have blanks and repeats removed (via `_map_label_sequences`). |
| 564 | |
| 565 | Args: |
| 566 | input_batch: A dict containing: |
| 567 | inputs: A Tensor of shape [batch_size, num_frames, dim]. |
| 568 | paddings: A 0/1 Tensor of shape [batch_size, num_frames]. 1's represent paddings. |
| 569 | |
| 570 | Returns: |
| 571 | DecodeOutputs, containing: |
| 572 | raw_sequences: An int Tensor of shape [batch_size, 1, num_frames]. |
| 573 | sequences: An int Tensor of shape [batch_size, 1, num_frames]. |
| 574 | paddings: A 0/1 Tensor of shape [batch_size, 1, num_frames]. |
| 575 | scores: A Tensor of shape [batch_size, 1]. |
| 576 | """ |
| 577 | cfg: CTCDecoderModel.Config = self.config |
| 578 | paddings: Tensor = input_batch["paddings"] |
| 579 | # [batch_size, num_frames, vocab_size]. |
| 580 | logits = self.predict(input_batch) |
| 581 | # [batch, 1, num_frames]. |
| 582 | sequences = jnp.argmax(logits, axis=-1)[:, None, :] |
| 583 | # Remove repeats and blanks. |
| 584 | # We make the assumption that the trailing padding positions have 0 as the argmax index. |
| 585 | outputs = _map_label_sequences( |
| 586 | inputs=sequences, remove_repeats=True, blank_id=cfg.blank_id, pad_id=0 |
| 587 | ) |
| 588 | |
| 589 | # [batch_size, num_frames, vocab_size]. |
| 590 | log_probs = jax.nn.log_softmax(logits, axis=-1) |
| 591 | log_probs += paddings[..., None] * NEG_INF |
| 592 | # [batch, num_frames, 1]. |
| 593 | scores = jnp.take_along_axis(log_probs, sequences[:, 0, :, None], axis=-1) |
| 594 | # [batch, 1]. |
| 595 | scores = jnp.sum(jnp.squeeze(scores, axis=-1) * safe_not(paddings), axis=1, keepdims=True) |
| 596 | |
| 597 | return DecodeOutputs( |
| 598 | raw_sequences=sequences, |
| 599 | sequences=outputs["sequences"], |
| 600 | paddings=outputs["paddings"], |
| 601 | scores=scores, |
| 602 | ) |
| 603 | |
| 604 | def _postprocess_outputs(self, *, sequences: Tensor, paddings: Tensor, scores: Tensor): |
| 605 | cfg: CTCDecoderModel.Config = self.config |
nothing calls this directly
no test coverage detected