class_docstr: This class calculates Viterbi alignments in the forward method.
  
  It also records alignments and creates batches of them for use
  in Viterbi training.
  
  Arguments
  ---------
  states_per_phoneme : int
      Number of hidden states to use per phoneme.
  output_folder : str
      It is the folder that the alignments will be stored in when
      saved to disk. Not yet implemented.
  neg_inf : float
      The float used to represent a negative infinite log probability.
      Using `-float("Inf")` tends to give numerical instability.
      A number more negative than -1e5 also sometimes gave errors when
      the `genbmm` library was used (currently not in use). (default: -1e5)
  batch_reduction : string
      One of "none", "sum" or "mean".
      What kind of batch-level reduction to apply to the loss calculated
      in the forward method.
  input_len_norm : bool
      Whether to normalize the loss in the forward method by the length of
      the inputs.
  target_len_norm : bool
      Whether to normalize the loss in the forward method by the length of
      the targets.
  lexicon_path : string
      The location of the lexicon.
  
  Example
  -------
  >>> log_posteriors = torch.tensor([[[ -1., -10., -10.],
  ...                                 [-10.,  -1., -10.],
  ...                                 [-10., -10.,  -1.]],
  ...
  ...                                [[ -1., -10., -10.],
  ...                                 [-10.,  -1., -10.],
  ...                                 [-10., -10., -10.]]])
  >>> lens = torch.tensor([1., 0.66])
  >>> phns = torch.tensor([[0, 1, 2],
  ...                      [0, 1, 0]])
  >>> phn_lens = torch.tensor([1., 0.66])
  >>> aligner = HMMAligner()
  >>> forward_scores = aligner(
  ...        log_posteriors, lens, phns, phn_lens, 'forward'
  ... )
  >>> forward_scores.shape
  torch.Size([2])
  >>> viterbi_scores, alignments = aligner(
  ...        log_posteriors, lens, phns, phn_lens, 'viterbi'
  ... )
  >>> alignments
  [[0, 1, 2], [0, 1]]
  >>> viterbi_scores.shape
  torch.Size([2])
docstr: Do processing using the lexicon to return a sequence of the possible
  phonemes, the transition/pi probabilities, and the possible final
  states.
  Does processing on an utterance-by-utterance basis. Each utterance
  in the batch is processed by a helper method `_use_lexicon`.
  
  Arguments
  ---------
  words : list
      List of the words in the transcript
  interword_sils : bool
      If True, optional silences will be inserted between every word.
      If False, optional silences will only be placed at the beginning
      and end of each utterance.
  sample_pron: bool
      If True, it will sample a single possible sequence of phonemes.
      If False, it will return statistics for all possible sequences of
      phonemes.
  
  Returns
  -------
  poss_phns: torch.Tensor (batch, phoneme in possible phn sequence)
      The phonemes that are thought to be in each utterance.
  poss_phn_lens: torch.Tensor (batch)
      The relative length of each possible phoneme sequence in the batch.
  trans_prob: torch.Tensor (batch, from, to)
      Tensor containing transition (log) probabilities.
  pi_prob: torch.Tensor (batch, state)
      Tensor containing initial (log) probabilities.
  final_state: list of lists of ints
      A list of lists of possible final states for each utterance.
  
  Example
  -------
  >>> aligner = HMMAligner()
  >>> aligner.lexicon = {
  ...                     "a": {0: "a"},
  ...                     "b": {0: "b", 1: "c"}
  ...                   }
  >>> words = [["a", "b"]]
  >>> aligner.lex_lab2ind = {
  ...                   "sil": 0,
  ...                   "a":  1,
  ...                   "b":  2,
  ...                   "c":  3,
  ...                 }
  >>> poss_phns, poss_phn_lens, trans_prob, pi_prob, final_states = aligner.use_lexicon(
  ...     words,
  ...     interword_sils = True
  ... )
  >>> poss_phns
  tensor([[0, 1, 0, 2, 3, 0]])
  >>> poss_phn_lens
  tensor([1.])
  >>> trans_prob
  tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05,
            -1.0000e+05],
           [-1.0000e+05, -1.3863e+00, -1.3863e+00, -1.3863e+00, -1.3863e+00,
            -1.0000e+05],
           [-1.0000e+05, -1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00,
            -1.0000e+05],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -1.0000e+05,
            -6.9315e-01],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01,
            -6.9315e-01],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,
             0.0000e+00]]])
  >>> pi_prob
  tensor([[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05,
           -1.0000e+05]])
  >>> final_states
  [[3, 4, 5]]
  >>> # With no optional silences between words
  >>> poss_phns_, _, trans_prob_, pi_prob_, final_states_ = aligner.use_lexicon(
  ...     words,
  ...     interword_sils = False
  ... )
  >>> poss_phns_
  tensor([[0, 1, 2, 3, 0]])
  >>> trans_prob_
  tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05],
           [-1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00, -1.0000e+05],
           [-1.0000e+05, -1.0000e+05, -6.9315e-01, -1.0000e+05, -6.9315e-01],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,  0.0000e+00]]])
  >>> pi_prob_
  tensor([[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05]])
  >>> final_states_
  [[2, 3, 4]]
  >>> # With sampling of a single possible pronunciation
  >>> import random
  >>> random.seed(0)
  >>> poss_phns_, _, trans_prob_, pi_prob_, final_states_ = aligner.use_lexicon(
  ...     words,
  ...     sample_pron = True
  ... )
  >>> poss_phns_
  tensor([[0, 1, 0, 2, 0]])
  >>> trans_prob_
  tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05],
           [-1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00, -1.0000e+05],
           [-1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01, -1.0000e+05],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01],
           [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,  0.0000e+00]]])
docstr_tok: ["Do","processing","using","the","lexicon","to","return","a","sequence","of","the","possible","phonemes",",","the","transition\/pi","probabilities",",","and","the","possible","final","states",".","Does","processing","on","an","utterance-by-utterance","basis",".","Each","utterance","in","the","batch","is","processed","by","a","helper","method","`","_use_lexicon","`",".","Arguments","--","--","--","--","-","words",":","list","List","of","the","words","in","the","transcript","interword_sils",":","bool","If","True",",","optional","silences","will","be","inserted","between","every","word",".","If","False",",","optional","silences","will","only","be","placed","at","the","beginning","and","end","of","each","utterance",".","sample_pron",":","bool","If","True",",","it","will","sample","a","single","possible","sequence","of","phonemes",".","If","False",",","it","will","return","statistics","for","all","possible","sequences","of","phonemes",".","Returns","--","--","--","-","poss_phns",":","torch.Tensor","(","batch",",","phoneme","in","possible","phn","sequence",")","The","phonemes","that","are","thought","to","be","in","each","utterance",".","poss_phn_lens",":","torch.Tensor","(","batch",")","The","relative","length","of","each","possible","phoneme","sequence","in","the","batch",".","trans_prob",":","torch.Tensor","(","batch",",","from",",","to",")","Tensor","containing","transition","(","log",")","probabilities",".","pi_prob",":","torch.Tensor","(","batch",",","state",")","Tensor","containing","initial","(","log",")","probabilities",".","final_state",":","list","of","lists","of","ints","A","list","of","lists","of","possible","final","states","for","each","utterance",".","Example","--","--","--","-",">",">",">","aligner","=","HMMAligner","(",")",">",">",">","aligner.lexicon","=","{","...","``","a","''",":","{","0",":","``","a","''","}",",","...","``","b","''",":","{","0",":","``","b","''",",","1",":","``","c","''","}","...","}",">",">",">","words","=","[","[","``","a","''",",","``","b","''","]","]",">",">",">","aligner.lex_lab2ind","=","{","...","``","sil","''",":","0",",","...","``","a","''",":","1",",","...","``","b","''",":","2",",","...","``","c","''",":","3",",","...","}",">",">",">","poss_phns",",","poss_phn_lens",",","trans_prob",",","pi_prob",",","final_states","=","aligner.use_lexicon","(","...","words",",","...","interword_sils","=","True","...",")",">",">",">","poss_phns","tensor","(","[","[","0",",","1",",","0",",","2",",","3",",","0","]","]",")",">",">",">","poss_phn_lens","tensor","(","[","1",".","]",")",">",">",">","trans_prob","tensor","(","[","[","[","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.3863e+00",",","-1.3863e+00",",","-1.3863e+00",",","-1.3863e+00",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0986e+00",",","-1.0986e+00",",","-1.0986e+00",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-1.0000e+05",",","-6.9315e-01","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-6.9315e-01","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","0.0000e+00","]","]","]",")",">",">",">","pi_prob","tensor","(","[","[","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05","]","]",")",">",">",">","final_states","[","[","3",",","4",",","5","]","]",">",">",">","#","With","no","optional","silences","between","words",">",">",">","poss_phns_",",","_",",","trans_prob_",",","pi_prob_",",","final_states_","=","aligner.use_lexicon","(","...","words",",","...","interword_sils","=","False","...",")",">",">",">","poss_phns_","tensor","(","[","[","0",",","1",",","2",",","3",",","0","]","]",")",">",">",">","trans_prob_","tensor","(","[","[","[","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0986e+00",",","-1.0986e+00",",","-1.0986e+00",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-1.0000e+05",",","-6.9315e-01","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-6.9315e-01","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","0.0000e+00","]","]","]",")",">",">",">","pi_prob_","tensor","(","[","[","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05","]","]",")",">",">",">","final_states_","[","[","2",",","3",",","4","]","]",">",">",">","#","With","sampling","of","a","single","possible","pronunciation",">",">",">","import","random",">",">",">","random.seed","(","0",")",">",">",">","poss_phns_",",","_",",","trans_prob_",",","pi_prob_",",","final_states_","=","aligner.use_lexicon","(","...","words",",","...","sample_pron","=","True","...",")",">",">",">","poss_phns_","tensor","(","[","[","0",",","1",",","0",",","2",",","0","]","]",")",">",">",">","trans_prob_","tensor","(","[","[","[","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0986e+00",",","-1.0986e+00",",","-1.0986e+00",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-6.9315e-01",",","-1.0000e+05","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-6.9315e-01",",","-6.9315e-01","]",",","[","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","-1.0000e+05",",","0.0000e+00","]","]","]",")"]
code: def use_lexicon(self, words, interword_sils=True, sample_pron=False):
      """Do processing using the lexicon to return a sequence of the possible
      phonemes, the transition/pi probabilities, and the possible final
      states.
      Does processing on an utterance-by-utterance basis. Each utterance
      in the batch is processed by a helper method `_use_lexicon`.
  
      Arguments
      ---------
      words : list
          List of the words in the transcript
      interword_sils : bool
          If True, optional silences will be inserted between every word.
          If False, optional silences will only be placed at the beginning
          and end of each utterance.
      sample_pron: bool
          If True, it will sample a single possible sequence of phonemes.
          If False, it will return statistics for all possible sequences of
          phonemes.
  
      Returns
      -------
      poss_phns: torch.Tensor (batch, phoneme in possible phn sequence)
          The phonemes that are thought to be in each utterance.
      poss_phn_lens: torch.Tensor (batch)
          The relative length of each possible phoneme sequence in the batch.
      trans_prob: torch.Tensor (batch, from, to)
          Tensor containing transition (log) probabilities.
      pi_prob: torch.Tensor (batch, state)
          Tensor containing initial (log) probabilities.
      final_state: list of lists of ints
          A list of lists of possible final states for each utterance.
  
      Example
      -------
      >>> aligner = HMMAligner()
      >>> aligner.lexicon = {
      ...                     "a": {0: "a"},
      ...                     "b": {0: "b", 1: "c"}
      ...                   }
      >>> words = [["a", "b"]]
      >>> aligner.lex_lab2ind = {
      ...                   "sil": 0,
      ...                   "a":  1,
      ...                   "b":  2,
      ...                   "c":  3,
      ...                 }
      >>> poss_phns, poss_phn_lens, trans_prob, pi_prob, final_states = aligner.use_lexicon(
      ...     words,
      ...     interword_sils = True
      ... )
      >>> poss_phns
      tensor([[0, 1, 0, 2, 3, 0]])
      >>> poss_phn_lens
      tensor([1.])
      >>> trans_prob
      tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05,
                -1.0000e+05],
               [-1.0000e+05, -1.3863e+00, -1.3863e+00, -1.3863e+00, -1.3863e+00,
                -1.0000e+05],
               [-1.0000e+05, -1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00,
                -1.0000e+05],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -1.0000e+05,
                -6.9315e-01],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01,
                -6.9315e-01],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,
                 0.0000e+00]]])
      >>> pi_prob
      tensor([[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05,
               -1.0000e+05]])
      >>> final_states
      [[3, 4, 5]]
      >>> # With no optional silences between words
      >>> poss_phns_, _, trans_prob_, pi_prob_, final_states_ = aligner.use_lexicon(
      ...     words,
      ...     interword_sils = False
      ... )
      >>> poss_phns_
      tensor([[0, 1, 2, 3, 0]])
      >>> trans_prob_
      tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05],
               [-1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00, -1.0000e+05],
               [-1.0000e+05, -1.0000e+05, -6.9315e-01, -1.0000e+05, -6.9315e-01],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,  0.0000e+00]]])
      >>> pi_prob_
      tensor([[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05]])
      >>> final_states_
      [[2, 3, 4]]
      >>> # With sampling of a single possible pronunciation
      >>> import random
      >>> random.seed(0)
      >>> poss_phns_, _, trans_prob_, pi_prob_, final_states_ = aligner.use_lexicon(
      ...     words,
      ...     sample_pron = True
      ... )
      >>> poss_phns_
      tensor([[0, 1, 0, 2, 0]])
      >>> trans_prob_
      tensor([[[-6.9315e-01, -6.9315e-01, -1.0000e+05, -1.0000e+05, -1.0000e+05],
               [-1.0000e+05, -1.0986e+00, -1.0986e+00, -1.0986e+00, -1.0000e+05],
               [-1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01, -1.0000e+05],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -6.9315e-01, -6.9315e-01],
               [-1.0000e+05, -1.0000e+05, -1.0000e+05, -1.0000e+05,  0.0000e+00]]])
      """
      self.silence_index = self.lex_lab2ind["sil"]
  
      poss_phns = []
      trans_prob = []
      start_states = []
      final_states = []
  
      for words_ in words:
          (
              poss_phns_,
              trans_prob_,
              start_states_,
              final_states_,
          ) = self._use_lexicon(words_, interword_sils, sample_pron)
          poss_phns.append(poss_phns_)
          trans_prob.append(trans_prob_)
          start_states.append(start_states_)
          final_states.append(final_states_)
  
      # pad poss_phns, trans_prob with 0 to have same length
      poss_phn_lens = [len(poss_phns_) for poss_phns_ in poss_phns]
      U_max = max(poss_phn_lens)
  
      batch_size = len(poss_phns)
      for index in range(batch_size):
          phn_pad_length = U_max - len(poss_phns[index])
          poss_phns[index] = torch.nn.functional.pad(
              poss_phns[index], (0, phn_pad_length), value=0
          )
          trans_prob[index] = torch.nn.functional.pad(
              trans_prob[index],
              (0, phn_pad_length, 0, phn_pad_length),
              value=self.neg_inf,
          )
  
      # Stack into single tensor
      poss_phns = torch.stack(poss_phns)
      trans_prob = torch.stack(trans_prob)
      trans_prob[trans_prob == -float("Inf")] = self.neg_inf
  
      # make pi prob
      pi_prob = self.neg_inf * torch.ones([batch_size, U_max])
      for start_state in start_states:
          pi_prob[:, start_state] = 1
  
      pi_prob = torch.nn.functional.log_softmax(pi_prob, dim=1)
  
      # Convert poss_phn_lens from absolute to relative lengths
      poss_phn_lens = torch.tensor(poss_phn_lens).float() / U_max
      return poss_phns, poss_phn_lens, trans_prob, pi_prob, final_states
  
imports: import torch
  import random
  from speechbrain.utils.checkpoints import register_checkpoint_hooks
  from speechbrain.utils.checkpoints import mark_as_saver
  from speechbrain.utils.checkpoints import mark_as_loader
  from speechbrain.utils.data_utils import undo_padding
label_desc: Use image node_id 3 for calling the HMMAligner obj's underlying member method code with example usage: obj.use_lexicon(words, interword_sils, sample_pron) and returns: poss_phns,  poss_phn_lens,  trans_prob,  pi_prob,  final_states