lattice-incremental-online-decoder.cc
Go to the documentation of this file.
1 // decoder/lattice-incremental-online-decoder.cc
2 
3 // Copyright 2019 Zhehuai Chen
4 
5 // See ../../COPYING for clarification regarding multiple authors
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 // http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
15 // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
16 // MERCHANTABLITY OR NON-INFRINGEMENT.
17 // See the Apache 2 License for the specific language governing permissions and
18 // limitations under the License.
19 
20 // see note at the top of lattice-faster-decoder.cc, about how to maintain this
21 // file in sync with lattice-faster-decoder.cc
22 
25 #include "lat/lattice-functions.h"
26 #include "base/timer.h"
27 
28 namespace kaldi {
29 
30 // Outputs an FST corresponding to the single best path through the lattice.
31 template <typename FST>
33  bool use_final_probs) const {
34  olat->DeleteStates();
35  BaseFloat final_graph_cost;
36  BestPathIterator iter = BestPathEnd(use_final_probs, &final_graph_cost);
37  if (iter.Done())
38  return false; // would have printed warning.
39  StateId state = olat->AddState();
40  olat->SetFinal(state, LatticeWeight(final_graph_cost, 0.0));
41  while (!iter.Done()) {
42  LatticeArc arc;
43  iter = TraceBackBestPath(iter, &arc);
44  arc.nextstate = state;
45  StateId new_state = olat->AddState();
46  olat->AddArc(new_state, arc);
47  state = new_state;
48  }
49  olat->SetStart(state);
50  return true;
51 }
52 
53 template <typename FST>
55  bool use_final_probs,
56  BaseFloat *final_cost_out) const {
57  if (this->decoding_finalized_ && !use_final_probs)
58  KALDI_ERR << "You cannot call FinalizeDecoding() and then call "
59  << "BestPathEnd() with use_final_probs == false";
60  KALDI_ASSERT(this->NumFramesDecoded() > 0 &&
61  "You cannot call BestPathEnd if no frames were decoded.");
62 
63  unordered_map<Token*, BaseFloat> final_costs_local;
64 
65  const unordered_map<Token*, BaseFloat> &final_costs =
66  (this->decoding_finalized_ ? this->final_costs_ :final_costs_local);
67  if (!this->decoding_finalized_ && use_final_probs)
68  this->ComputeFinalCosts(&final_costs_local, NULL, NULL);
69 
70  // Singly linked list of tokens on last frame (access list through "next"
71  // pointer).
72  BaseFloat best_cost = std::numeric_limits<BaseFloat>::infinity();
73  BaseFloat best_final_cost = 0;
74  Token *best_tok = NULL;
75  for (Token *tok = this->active_toks_.back().toks;
76  tok != NULL; tok = tok->next) {
77  BaseFloat cost = tok->tot_cost, final_cost = 0.0;
78  if (use_final_probs && !final_costs.empty()) {
79  // if we are instructed to use final-probs, and any final tokens were
80  // active on final frame, include the final-prob in the cost of the token.
81  typename unordered_map<Token*, BaseFloat>::const_iterator
82  iter = final_costs.find(tok);
83  if (iter != final_costs.end()) {
84  final_cost = iter->second;
85  cost += final_cost;
86  } else {
87  cost = std::numeric_limits<BaseFloat>::infinity();
88  }
89  }
90  if (cost < best_cost) {
91  best_cost = cost;
92  best_tok = tok;
93  best_final_cost = final_cost;
94  }
95  }
96  if (best_tok == NULL) { // this should not happen, and is likely a code error or
97  // caused by infinities in likelihoods, but I'm not making
98  // it a fatal error for now.
99  KALDI_WARN << "No final token found.";
100  }
101  if (final_cost_out == NULL)
102  *final_cost_out = best_final_cost;
103  return BestPathIterator(best_tok, this->NumFramesDecoded() - 1);
104 }
105 
106 
107 template <typename FST>
109  BestPathIterator iter, LatticeArc *oarc) const {
110  KALDI_ASSERT(!iter.Done() && oarc != NULL);
111  Token *tok = static_cast<Token*>(iter.tok);
112  int32 cur_t = iter.frame, ret_t = cur_t;
113  if (tok->backpointer != NULL) {
114  ForwardLinkT *link;
115  for (link = tok->backpointer->links;
116  link != NULL; link = link->next) {
117  if (link->next_tok == tok) { // this is the link to "tok"
118  oarc->ilabel = link->ilabel;
119  oarc->olabel = link->olabel;
120  BaseFloat graph_cost = link->graph_cost,
121  acoustic_cost = link->acoustic_cost;
122  if (link->ilabel != 0) {
123  KALDI_ASSERT(static_cast<size_t>(cur_t) < this->cost_offsets_.size());
124  acoustic_cost -= this->cost_offsets_[cur_t];
125  ret_t--;
126  }
127  oarc->weight = LatticeWeight(graph_cost, acoustic_cost);
128  break;
129  }
130  }
131  if (link == NULL) { // Did not find correct link.
132  KALDI_ERR << "Error tracing best-path back (likely "
133  << "bug in token-pruning algorithm)";
134  }
135  } else {
136  oarc->ilabel = 0;
137  oarc->olabel = 0;
138  oarc->weight = LatticeWeight::One(); // zero costs.
139  }
140  return BestPathIterator(tok->backpointer, ret_t);
141 }
142 
143 // Instantiate the template for the FST types that we'll need.
148 
149 
150 } // end namespace kaldi.
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
fst::ArcTpl< LatticeWeight > LatticeArc
Definition: kaldi-lattice.h:40
static const LatticeWeightTpl One()
LatticeIncrementalOnlineDecoderTpl is as LatticeIncrementalDecoderTpl but also supports an efficient ...
kaldi::int32 int32
BestPathIterator BestPathEnd(bool use_final_probs, BaseFloat *final_cost=NULL) const
This function returns an iterator that can be used to trace back the best path.
fst::LatticeWeightTpl< BaseFloat > LatticeWeight
Definition: kaldi-lattice.h:32
fst::VectorFst< LatticeArc > Lattice
Definition: kaldi-lattice.h:44
#define KALDI_ERR
Definition: kaldi-error.h:147
#define KALDI_WARN
Definition: kaldi-error.h:150
#define KALDI_ASSERT(cond)
Definition: kaldi-error.h:185
BestPathIterator TraceBackBestPath(BestPathIterator iter, LatticeArc *arc) const
This function can be used in conjunction with BestPathEnd() to trace back the best path one link at a...
bool GetBestPath(Lattice *ofst, bool use_final_probs=true) const
Outputs an FST corresponding to the single best path through the lattice.