nnet-show-progress.cc
Go to the documentation of this file.
1 // nnet2bin/nnet-show-progress.cc
2 
3 // Copyright 2012-2013 Johns Hopkins University (author: Daniel Povey)
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/transition-model.h"
23 #include "nnet2/train-nnet.h"
24 #include "nnet2/am-nnet.h"
25 
26 
27 int main(int argc, char *argv[]) {
28  try {
29  using namespace kaldi;
30  using namespace kaldi::nnet2;
31  typedef kaldi::int32 int32;
32  typedef kaldi::int64 int64;
33 
34  const char *usage =
35  "Given an old and a new model and some training examples (possibly held-out),\n"
36  "show the average objective function given the mean of the two models,\n"
37  "and the breakdown by component of why this happened (computed from\n"
38  "derivative information). Also shows parameter differences per layer.\n"
39  "If training examples not provided, only shows parameter differences per\n"
40  "layer.\n"
41  "\n"
42  "Usage: nnet-show-progress [options] <old-model-in> <new-model-in> [<training-examples-in>]\n"
43  "e.g.: nnet-show-progress 1.nnet 2.nnet ark:valid.egs\n";
44 
45  ParseOptions po(usage);
46 
47  int32 num_segments = 1;
48  int32 batch_size = 1024;
49  std::string use_gpu = "optional";
50 
51  po.Register("num-segments", &num_segments,
52  "Number of line segments used for computing derivatives");
53  po.Register("use-gpu", &use_gpu,
54  "yes|no|optional|wait, only has effect if compiled with CUDA");
55 
56  po.Read(argc, argv);
57 
58  if (po.NumArgs() < 2 || po.NumArgs() > 3) {
59  po.PrintUsage();
60  exit(1);
61  }
62 
63 #if HAVE_CUDA==1
64  CuDevice::Instantiate().SelectGpuId(use_gpu);
65 #endif
66 
67  std::string nnet1_rxfilename = po.GetArg(1),
68  nnet2_rxfilename = po.GetArg(2),
69  examples_rspecifier = po.GetOptArg(3);
70 
71  TransitionModel trans_model;
72  AmNnet am_nnet1, am_nnet2;
73  {
74  bool binary_read;
75  Input ki(nnet1_rxfilename, &binary_read);
76  trans_model.Read(ki.Stream(), binary_read);
77  am_nnet1.Read(ki.Stream(), binary_read);
78  }
79  {
80  bool binary_read;
81  Input ki(nnet2_rxfilename, &binary_read);
82  trans_model.Read(ki.Stream(), binary_read);
83  am_nnet2.Read(ki.Stream(), binary_read);
84  }
85 
86  if (am_nnet1.GetNnet().GetParameterDim() !=
87  am_nnet2.GetNnet().GetParameterDim()) {
88  KALDI_WARN << "Parameter-dim mismatch, cannot show progress.";
89  exit(0);
90  }
91 
92  int32 ret = 0;
93 
94  if (!examples_rspecifier.empty()) {
95  Nnet nnet_gradient(am_nnet2.GetNnet());
96  const bool treat_as_gradient = true;
97  nnet_gradient.SetZero(treat_as_gradient);
98 
99  std::vector<NnetExample> examples;
100  SequentialNnetExampleReader example_reader(examples_rspecifier);
101  for (; !example_reader.Done(); example_reader.Next())
102  examples.push_back(example_reader.Value());
103 
104  int32 num_examples = examples.size();
105 
106  int32 num_updatable = am_nnet1.GetNnet().NumUpdatableComponents();
107  Vector<BaseFloat> diff(num_updatable);
108 
109  for (int32 s = 0; s < num_segments; s++) {
110  // start and end segments of the line between 0 and 1
111  BaseFloat start = (s + 0.0) / num_segments,
112  end = (s + 1.0) / num_segments, middle = 0.5 * (start + end);
113  Nnet interp_nnet(am_nnet2.GetNnet());
114  interp_nnet.Scale(middle);
115  interp_nnet.AddNnet(1.0 - middle, am_nnet1.GetNnet());
116 
117  Nnet nnet_gradient(am_nnet2.GetNnet());
118  const bool treat_as_gradient = true;
119  nnet_gradient.SetZero(treat_as_gradient);
120 
121  double objf_per_frame = ComputeNnetGradient(interp_nnet, examples,
122  batch_size, &nnet_gradient);
123  KALDI_LOG << "At position " << middle << ", objf per frame is " << objf_per_frame;
124 
125  Vector<BaseFloat> old_dotprod(num_updatable), new_dotprod(num_updatable);
126  nnet_gradient.ComponentDotProducts(am_nnet1.GetNnet(), &old_dotprod);
127  nnet_gradient.ComponentDotProducts(am_nnet2.GetNnet(), &new_dotprod);
128  old_dotprod.Scale(1.0 / num_examples);
129  new_dotprod.Scale(1.0 / num_examples);
130  diff.AddVec(1.0/ num_segments, new_dotprod);
131  diff.AddVec(-1.0 / num_segments, old_dotprod);
132  KALDI_VLOG(1) << "By segment " << s << ", objf change is " << diff;
133  }
134  KALDI_LOG << "Total objf change per component is " << diff;
135  if (num_examples == 0) ret = 1;
136  }
137 
138  { // Get info about magnitude of parameter change.
139  Nnet diff_nnet(am_nnet1.GetNnet());
140  diff_nnet.AddNnet(-1.0, am_nnet2.GetNnet());
141  int32 num_updatable = diff_nnet.NumUpdatableComponents();
142  Vector<BaseFloat> dot_prod(num_updatable);
143  diff_nnet.ComponentDotProducts(diff_nnet, &dot_prod);
144  dot_prod.ApplyPow(0.5); // take sqrt to get l2 norm of diff
145  KALDI_LOG << "Parameter differences per layer are "
146  << dot_prod;
147 
148  Vector<BaseFloat> baseline_prod(num_updatable);
149  am_nnet1.GetNnet().ComponentDotProducts(am_nnet1.GetNnet(),
150  &baseline_prod);
151  baseline_prod.ApplyPow(0.5);
152  dot_prod.DivElements(baseline_prod);
153  KALDI_LOG << "Relative parameter differences per layer are "
154  << dot_prod;
155  }
156 
157  return ret;
158  } catch(const std::exception &e) {
159  std::cerr << e.what() << '\n';
160  return -1;
161  }
162 }
163 
164 
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
void AddNnet(const VectorBase< BaseFloat > &scales, const Nnet &other)
For each updatatable component, adds to it the corresponding element of "other" times the appropriate...
Definition: nnet-nnet.cc:576
int32 NumUpdatableComponents() const
Returns the number of updatable components.
Definition: nnet-nnet.cc:413
double ComputeNnetGradient(const Nnet &nnet, const std::vector< NnetExample > &validation_set, int32 batch_size, Nnet *gradient)
ComputeNnetGradient is mostly used to compute gradients on validation sets; it divides the example in...
Definition: nnet-update.cc:302
void PrintUsage(bool print_command_line=false)
Prints the usage documentation [provided in the constructor].
void ComponentDotProducts(const Nnet &other, VectorBase< BaseFloat > *dot_prod) const
Definition: nnet-nnet.cc:207
void Read(std::istream &is, bool binary)
Definition: am-nnet.cc:39
int main(int argc, char *argv[])
kaldi::int32 int32
virtual int32 GetParameterDim() const
Definition: nnet-nnet.cc:657
void Scale(BaseFloat scale)
Scales all the Components with the same scale.
Definition: nnet-nnet.cc:436
void Register(const std::string &name, bool *ptr, const std::string &doc)
std::istream & Stream()
Definition: kaldi-io.cc:826
float BaseFloat
Definition: kaldi-types.h:29
void SetZero(bool treat_as_gradient)
Definition: nnet-nnet.cc:151
The class ParseOptions is for parsing command-line options; see Parsing command-line options for more...
Definition: parse-options.h:36
void Read(std::istream &is, bool binary)
A templated class for reading objects sequentially from an archive or script file; see The Table conc...
Definition: kaldi-table.h:287
int Read(int argc, const char *const *argv)
Parses the command line options and fills the ParseOptions-registered variables.
#define KALDI_WARN
Definition: kaldi-error.h:150
std::string GetArg(int param) const
Returns one of the positional parameters; 1-based indexing for argc/argv compatibility.
void Scale(Real alpha)
Multiplies all elements by this constant.
int NumArgs() const
Number of positional parameters (c.f. argc-1).
A class representing a vector.
Definition: kaldi-vector.h:406
void ApplyPow(Real power)
Take all elements of vector to a power.
Definition: kaldi-vector.h:179
#define KALDI_VLOG(v)
Definition: kaldi-error.h:156
#define KALDI_LOG
Definition: kaldi-error.h:153
void AddVec(const Real alpha, const VectorBase< OtherReal > &v)
Add vector : *this = *this + alpha * rv (with casting between floats and doubles) ...
const Nnet & GetNnet() const
Definition: am-nnet.h:61
std::string GetOptArg(int param) const