Computes CTC loss. Args: input_batch: A dict containing: inputs: A Tensor of shape [batch_size, num_frames, dim]. paddings: A 0/1 Tensor of shape [batch_size, num_frames]. 1's represent paddings. target_labels: An int Tensor of sha
(
self,
input_batch: Nested[Tensor],
)
| 351 | return ret_dict |
| 352 | |
| 353 | def forward( |
| 354 | self, |
| 355 | input_batch: Nested[Tensor], |
| 356 | ) -> tuple[Tensor, Nested[Tensor]]: |
| 357 | """Computes CTC loss. |
| 358 | |
| 359 | Args: |
| 360 | input_batch: A dict containing: |
| 361 | inputs: A Tensor of shape [batch_size, num_frames, dim]. |
| 362 | paddings: A 0/1 Tensor of shape [batch_size, num_frames]. 1's represent paddings. |
| 363 | target_labels: An int Tensor of shape [batch_size, num_labels]. |
| 364 | Values should be in the range [0, vocab_size). We assume there are no BOS |
| 365 | tokens, and that sequences are not truncated. Out-of-range values are excluded |
| 366 | from the loss calculation (e.g., paddings and EOS can be represented this way). |
| 367 | |
| 368 | Returns: |
| 369 | A tuple (loss, aux_outputs): |
| 370 | loss: A scalar loss value. |
| 371 | aux_outputs: A dict containing: |
| 372 | per_example_loss: A float Tensor of shape [batch_size]. |
| 373 | per_example_weight: A float Tensor of shape [batch_size]. |
| 374 | """ |
| 375 | cfg: CTCDecoderModel.Config = self.config |
| 376 | paddings: Tensor = input_batch["paddings"] |
| 377 | target_labels: Tensor = input_batch["target_labels"] |
| 378 | target_paddings: Tensor = _compute_target_paddings(target_labels, vocab_size=cfg.vocab_size) |
| 379 | |
| 380 | # Compute CTC loss. |
| 381 | logits = self.predict(input_batch) |
| 382 | per_example_loss = optax.ctc_loss( |
| 383 | logits=logits, |
| 384 | logit_paddings=paddings, |
| 385 | labels=target_labels, |
| 386 | label_paddings=target_paddings, |
| 387 | blank_id=cfg.blank_id, |
| 388 | ) |
| 389 | |
| 390 | # Drop examples with targets longer than inputs. |
| 391 | per_example_weight = _is_valid_ctc_seq( |
| 392 | paddings=paddings, target_labels=target_labels, target_paddings=target_paddings |
| 393 | ) |
| 394 | per_example_weight = per_example_weight.astype(per_example_loss.dtype) |
| 395 | |
| 396 | # Compute weighted loss. |
| 397 | loss = jnp.sum(per_example_loss * per_example_weight) / jnp.maximum( |
| 398 | per_example_weight.sum(), 1 |
| 399 | ) |
| 400 | aux_outputs = dict(per_example_weight=per_example_weight, per_example_loss=per_example_loss) |
| 401 | # Add summaries. |
| 402 | summary = self._input_stats_summaries( |
| 403 | input_batch=input_batch, |
| 404 | target_paddings=target_paddings, |
| 405 | is_valid_example=per_example_weight, |
| 406 | ) |
| 407 | summary.update( |
| 408 | self._loss_summaries( |
| 409 | total_ctc_loss=jnp.sum(per_example_loss * per_example_weight), |
| 410 | per_example_weight=per_example_weight, |
nothing calls this directly
no test coverage detected