All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
compile-questions.cc
Go to the documentation of this file.
1 // bin/compile-questions.cc
2 
3 // Copyright 2009-2011 Microsoft Corporation
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 #include "base/kaldi-common.h"
21 #include "util/common-utils.h"
22 #include "hmm/hmm-topology.h"
24 
25 
26 namespace kaldi {
27 int32 ProcessTopo(const HmmTopology &topo, const std::vector<std::vector<int32> > &questions) {
28  std::vector<int32> seen_phones; // ids of phones seen in questions.
29  for (size_t i = 0; i < questions.size(); i++)
30  for (size_t j= 0; j < questions[i].size(); j++) seen_phones.push_back(questions[i][j]);
31  SortAndUniq(&seen_phones);
32  // topo_phones is also sorted and uniq; a list of phones defined in the topology.
33  const std::vector<int32> &topo_phones = topo.GetPhones();
34  if (seen_phones != topo_phones) {
35  std::ostringstream ss_seen, ss_topo;
36  WriteIntegerVector(ss_seen, false, seen_phones);
37  WriteIntegerVector(ss_topo, false, topo_phones);
38  KALDI_WARN << "ProcessTopo: phones seen in questions differ from those in topology: "
39  << ss_seen.str() << " vs. " << ss_topo.str();
40  if (seen_phones.size() > topo_phones.size()) {
41  KALDI_ERR << "ProcessTopo: phones are asked about that are undefined in the topology.";
42  } // we accept the reverse (not asking about all phones), even though it's very bad.
43  }
44 
45  int32 max_num_pdf_classes = 0;
46  for (size_t i = 0; i < topo_phones.size(); i++) {
47  int32 p = topo_phones[i];
48  int32 num_pdf_classes = topo.NumPdfClasses(p);
49  max_num_pdf_classes = std::max(num_pdf_classes, max_num_pdf_classes);
50  }
51  KALDI_LOG << "Max # pdf classes is " << max_num_pdf_classes;
52  return max_num_pdf_classes;
53 }
54 
55 } // end namespace kaldi.
56 
57 int main(int argc, char *argv[]) {
58  using namespace kaldi;
59  try {
60  using namespace kaldi;
61  typedef kaldi::int32 int32;
62 
63  const char *usage =
64  "Compile questions\n"
65  "Usage: compile-questions [options] <topo> <questions-text-file> <questions-out>\n"
66  "e.g.: \n"
67  " compile-questions questions.txt questions.qst\n";
68  bool binary = true;
69  int32 P = 1, N = 3;
70  int32 num_iters_refine = 0,
71  leftmost_questions_truncate = -1;
72 
73 
74  ParseOptions po(usage);
75  po.Register("binary", &binary,
76  "Write output in binary mode");
77  po.Register("context-width", &N,
78  "Context window size [must match acc-tree-stats].");
79  po.Register("central-position", &P,
80  "Central position in phone context window [must match acc-tree-stats]");
81  po.Register("num-iters-refine", &num_iters_refine,
82  "Number of iters of refining questions at each node. >0 --> questions "
83  "not refined");
84  po.Register("leftmost-questions-truncate", &leftmost_questions_truncate,
85  "If > 0, the questions for the left-most context position will be "
86  "truncated to the specified number.");
87 
88  po.Read(argc, argv);
89 
90  if (po.NumArgs() != 3) {
91  po.PrintUsage();
92  exit(1);
93  }
94 
95  std::string
96  topo_filename = po.GetArg(1),
97  questions_rxfilename = po.GetArg(2),
98  questions_out_filename = po.GetArg(3);
99 
100  HmmTopology topo; // just needed for checking, and to get the
101  // largest number of pdf-classes for any phone.
102  ReadKaldiObject(topo_filename, &topo);
103 
104  std::vector<std::vector<int32> > questions; // sets of phones.
105  if (!ReadIntegerVectorVectorSimple(questions_rxfilename, &questions))
106  KALDI_ERR << "Could not read questions from "
107  << PrintableRxfilename(questions_rxfilename);
108  for (size_t i = 0; i < questions.size(); i++) {
109  std::sort(questions[i].begin(), questions[i].end());
110  if (!IsSortedAndUniq(questions[i]))
111  KALDI_ERR << "Questions contain duplicate phones";
112  }
113  size_t nq = static_cast<int32>(questions.size());
114  SortAndUniq(&questions);
115  if (questions.size() != nq)
116  KALDI_WARN << (nq-questions.size())
117  << " duplicate questions present in " << questions_rxfilename;
118 
119  // ProcessTopo checks that all phones in the topo are
120  // represented in at least one questions (else warns), and
121  // returns the max # pdf classes in any given phone (normally
122  // 3).
123  int32 max_num_pdfclasses = ProcessTopo(topo, questions);
124 
125  Questions qo;
126 
127  QuestionsForKey phone_opts(num_iters_refine);
128  // the questions-options corresponding to keys 0, 1, .. N-1 which
129  // represent the phonetic context positions (including the central phone).
130  for (int32 n = 0; n < N; n++) {
131  KALDI_LOG << "Setting questions for phonetic-context position "<< n;
132  if (n == 0 && leftmost_questions_truncate > 0 &&
133  leftmost_questions_truncate < questions.size()) {
134  KALDI_LOG << "Truncating " << questions.size() << " to "
135  << leftmost_questions_truncate << " for position 0.";
136  phone_opts.initial_questions.assign(
137  questions.begin(), questions.begin() + leftmost_questions_truncate);
138  } else {
139  phone_opts.initial_questions = questions;
140  }
141  qo.SetQuestionsOf(n, phone_opts);
142  }
143 
144  QuestionsForKey pdfclass_opts(num_iters_refine);
145  std::vector<std::vector<int32> > pdfclass_questions(max_num_pdfclasses-1);
146  for (int32 i = 0; i < max_num_pdfclasses - 1; i++)
147  for (int32 j = 0; j <= i; j++)
148  pdfclass_questions[i].push_back(j);
149  // E.g. if max_num_pdfclasses == 3, pdfclass_questions is now [ [0], [0, 1] ].
150  pdfclass_opts.initial_questions = pdfclass_questions;
151  KALDI_LOG << "Setting questions for hmm-position [hmm-position ranges from 0 to "<< (max_num_pdfclasses-1) <<"]";
152  qo.SetQuestionsOf(kPdfClass, pdfclass_opts);
153 
154  WriteKaldiObject(qo, questions_out_filename, binary);
155  KALDI_LOG << "Wrote questions to "<<questions_out_filename;
156  } catch(const std::exception &e) {
157  std::cerr << e.what();
158  return -1;
159  }
160 }
Relabels neural network egs with the read pdf-id alignments.
Definition: chain.dox:20
This class defines, for each EventKeyType, a set of initial questions that it tries and also a number...
A class for storing topology information for phones.
Definition: hmm-topology.h:94
void PrintUsage(bool print_command_line=false)
Prints the usage documentation [provided in the constructor].
int32 ProcessTopo(const HmmTopology &topo, const std::vector< std::vector< int32 > > &questions)
void SetQuestionsOf(EventKeyType key, const QuestionsForKey &options_of_key)
void SortAndUniq(std::vector< T > *vec)
Sorts and uniq's (removes duplicates) from a vector.
Definition: stl-utils.h:39
std::string PrintableRxfilename(std::string rxfilename)
PrintableRxfilename turns the rxfilename into a more human-readable form for error reporting...
Definition: kaldi-io.cc:58
bool ReadIntegerVectorVectorSimple(std::string rxfilename, std::vector< std::vector< int32 > > *list)
void Register(const std::string &name, bool *ptr, const std::string &doc)
int32 NumPdfClasses(int32 phone) const
Returns the number of pdf-classes for this phone; throws exception if phone not covered by this topol...
void ReadKaldiObject(const std::string &filename, Matrix< float > *m)
Definition: kaldi-io.cc:818
static const EventKeyType kPdfClass
Definition: context-dep.h:39
The class ParseOptions is for parsing command-line options; see Parsing command-line options for more...
Definition: parse-options.h:36
const std::vector< int32 > & GetPhones() const
Returns a reference to a sorted, unique list of phones covered by the topology (these phones will be ...
Definition: hmm-topology.h:164
struct rnnlm::@11::@12 n
QuestionsForKey is a class used to define the questions for a key, and also options that allow us to ...
std::vector< std::vector< EventValueType > > initial_questions
int Read(int argc, const char *const *argv)
Parses the command line options and fills the ParseOptions-registered variables.
#define KALDI_ERR
Definition: kaldi-error.h:127
#define KALDI_WARN
Definition: kaldi-error.h:130
int NumArgs() const
Number of positional parameters (c.f. argc-1).
void WriteIntegerVector(std::ostream &os, bool binary, const std::vector< T > &v)
Function for writing STL vectors of integer types.
Definition: io-funcs-inl.h:198
void WriteKaldiObject(const C &c, const std::string &filename, bool binary)
Definition: kaldi-io.h:257
int main(int argc, char *argv[])
bool IsSortedAndUniq(const std::vector< T > &vec)
Returns true if the vector is sorted and contains each element only once.
Definition: stl-utils.h:63
#define KALDI_LOG
Definition: kaldi-error.h:133
std::string GetArg(int param) const
Returns one of the positional parameters; 1-based indexing for argc/argv compatibility.