class_docstr: Batch processing of CTCPrefixScore
  
  which is based on Algorithm 2 in WATANABE et al.
  "HYBRID CTC/ATTENTION ARCHITECTURE FOR END-TO-END SPEECH RECOGNITION,"
  but extended to efficiently compute the label probablities for multiple
  hypotheses simultaneously
  See also Seki et al. "Vectorized Beam Search for CTC-Attention-Based
  Speech Recognition," In INTERSPEECH (pp. 3825-3829), 2019.
class_docstr_tok: ["Batch","processing","of","CTCPrefixScore","which","is","based","on","Algorithm","2","in","WATANABE","et","al",".","``","HYBRID","CTC\/ATTENTION","ARCHITECTURE","FOR","END-TO-END","SPEECH","RECOGNITION",",","''","but","extended","to","efficiently","compute","the","label","probablities","for","multiple","hypotheses","simultaneously","See","also","Seki","et","al",".","``","Vectorized","Beam","Search","for","CTC-Attention-Based","Speech","Recognition",",","''","In","INTERSPEECH","(","pp",".","3825-3829",")",",","2019","."]
docstr: Compute CTC prefix scores for next labels
  
  :param list y: prefix label sequences
  :param tuple state: previous CTC state
  :param torch.Tensor pre_scores: scores for pre-selection of hypotheses (BW, O)
  :param torch.Tensor att_w: attention weights to decide CTC window
  :return new_state, ctc_local_scores (BW, O)
docstr_tok: ["Compute","CTC","prefix","scores","for","next","labels",":","param","list","y",":","prefix","label","sequences",":","param","tuple","state",":","previous","CTC","state",":","param","torch.Tensor","pre_scores",":","scores","for","pre-selection","of","hypotheses","(","BW",",","O",")",":","param","torch.Tensor","att_w",":","attention","weights","to","decide","CTC","window",":","return","new_state",",","ctc_local_scores","(","BW",",","O",")"]
code: def __call__(self, y, state, scoring_ids=None, att_w=None):
      """Compute CTC prefix scores for next labels
  
      :param list y: prefix label sequences
      :param tuple state: previous CTC state
      :param torch.Tensor pre_scores: scores for pre-selection of hypotheses (BW, O)
      :param torch.Tensor att_w: attention weights to decide CTC window
      :return new_state, ctc_local_scores (BW, O)
      """
      output_length = len(y[0]) - 1  # ignore sos
      last_ids = [yi[-1] for yi in y]  # last output label ids
      n_bh = len(last_ids)  # batch * hyps
      n_hyps = (
          n_bh // self.batch
      )  # assuming each utterance has the same # of hyps
      self.scoring_num = (
          scoring_ids.size(-1) if scoring_ids is not None else 0
      )
      # prepare state info
      if state is None:
          r_prev = torch.full(
              (self.input_length, 2, self.batch, n_hyps),
              self.logzero,
              dtype=self.dtype,
              device=self.device,
          )
          r_prev[:, 1] = torch.cumsum(
              self.x[0, :, :, self.blank], 0
          ).unsqueeze(2)
          r_prev = r_prev.view(-1, 2, n_bh)
          s_prev = 0.0
          f_min_prev = 0
          f_max_prev = 1
      else:
          r_prev, s_prev, f_min_prev, f_max_prev = state
  
      # select input dimensions for scoring
      if self.scoring_num > 0:
          scoring_idmap = torch.full(
              (n_bh, self.odim),
              -1,
              dtype=torch.long,
              device=self.device,
          )
          snum = self.scoring_num
          if self.idx_bh is None or n_bh > len(self.idx_bh):
              self.idx_bh = torch.arange(n_bh, device=self.device).view(
                  -1, 1
              )
          scoring_idmap[self.idx_bh[:n_bh], scoring_ids] = torch.arange(
              snum, device=self.device
          )
          scoring_idx = (
              scoring_ids + self.idx_bo.repeat(1, n_hyps).view(-1, 1)
          ).view(-1)
          x_ = torch.index_select(
              self.x.view(2, -1, self.batch * self.odim), 2, scoring_idx
          ).view(2, -1, n_bh, snum)
      else:
          scoring_ids = None
          scoring_idmap = None
          snum = self.odim
          x_ = (
              self.x.unsqueeze(3)
              .repeat(1, 1, 1, n_hyps, 1)
              .view(2, -1, n_bh, snum)
          )
  
      # new CTC forward probs are prepared as a (T x 2 x BW x S) tensor
      # that corresponds to r_t^n(h) and r_t^b(h) in a batch.
      r = torch.full(
          (self.input_length, 2, n_bh, snum),
          self.logzero,
          dtype=self.dtype,
          device=self.device,
      )
      if output_length == 0:
          r[0, 0] = x_[0, 0]
  
      r_sum = torch.logsumexp(r_prev, 1)
      log_phi = r_sum.unsqueeze(2).repeat(1, 1, snum)
      if scoring_ids is not None:
          for idx in range(n_bh):
              pos = scoring_idmap[idx, last_ids[idx]]
              if pos >= 0:
                  log_phi[:, idx, pos] = r_prev[:, 1, idx]
      else:
          for idx in range(n_bh):
              log_phi[:, idx, last_ids[idx]] = r_prev[:, 1, idx]
  
      # decide start and end frames based on attention weights
      if att_w is not None and self.margin > 0:
          f_arg = torch.matmul(att_w, self.frame_ids)
          f_min = max(int(f_arg.min().cpu()), f_min_prev)
          f_max = max(int(f_arg.max().cpu()), f_max_prev)
          start = min(
              f_max_prev, max(f_min - self.margin, output_length, 1)
          )
          end = min(f_max + self.margin, self.input_length)
      else:
          f_min = f_max = 0
          start = max(output_length, 1)
          end = self.input_length
  
      # compute forward probabilities log(r_t^n(h)) and log(r_t^b(h))
      for t in range(start, end):
          rp = r[t - 1]
          rr = torch.stack([rp[0], log_phi[t - 1], rp[0], rp[1]]).view(
              2, 2, n_bh, snum
          )
          r[t] = torch.logsumexp(rr, 1) + x_[:, t]
  
      # compute log prefix probabilities log(psi)
      log_phi_x = (
          torch.cat((log_phi[0].unsqueeze(0), log_phi[:-1]), dim=0)
          + x_[0]
      )
      if scoring_ids is not None:
          log_psi = torch.full(
              (n_bh, self.odim),
              self.logzero,
              dtype=self.dtype,
              device=self.device,
          )
          log_psi_ = torch.logsumexp(
              torch.cat(
                  (log_phi_x[start:end], r[start - 1, 0].unsqueeze(0)),
                  dim=0,
              ),
              dim=0,
          )
          for si in range(n_bh):
              log_psi[si, scoring_ids[si]] = log_psi_[si]
      else:
          log_psi = torch.logsumexp(
              torch.cat(
                  (log_phi_x[start:end], r[start - 1, 0].unsqueeze(0)),
                  dim=0,
              ),
              dim=0,
          )
  
      for si in range(n_bh):
          log_psi[si, self.eos] = r_sum[
              self.end_frames[si // n_hyps], si
          ]
  
      # exclude blank probs
      log_psi[:, self.blank] = self.logzero
  
      return (log_psi - s_prev), (
          r,
          log_psi,
          f_min,
          f_max,
          scoring_idmap,
      )
  
file_path: espnet/espnet/nets/ctc_prefix_score.py
imports: import numpy
  import torch
label_desc: Use image node_id 2 for calling the CTCPrefixScoreTH obj's underlying member method code with example usage: obj.__call__(y, state, scoring_ids, att_w) and returns: unknown,  r,  log_psi,  f_min,  f_max,  scoring_idmap