nnet-compile.h
Go to the documentation of this file.
1 // nnet3/nnet-compile.h
2 
3 // Copyright 2015-2016 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 #ifndef KALDI_NNET3_NNET_COMPILE_H_
21 #define KALDI_NNET3_NNET_COMPILE_H_
22 
24 #include "nnet3/nnet-nnet.h"
25 #include "nnet3/nnet-parse.h"
26 #include "nnet3/nnet-computation.h"
28 
29 #include <iostream>
30 
31 namespace kaldi {
32 namespace nnet3 {
33 
36 
37  CompilerOptions(): output_debug_info(true) { }
38 };
39 
44 class Compiler {
45  public:
46  // Constructor that takes one computation request (this is the normal case).
47  Compiler(const ComputationRequest &request,
48  const Nnet &nnet);
49 
50  // Constructor with a sequence of computation requests, for multiple
51  // computation segments (used when creating online computations).
52  Compiler(const std::vector<const ComputationRequest*> &request,
53  const Nnet &nnet);
54 
55  void CreateComputation(const CompilerOptions &opts,
56  NnetComputation *computation);
57 
58  private:
59  // requests_ is the sequence of computation requests, one for each segment; it
60  // will contain just one element in the normal case, but more when we're
61  // compiling a multi-segment / 'online' computation.
62  std::vector<const ComputationRequest*> requests_;
63  const Nnet &nnet_;
65 
66  // Some generic information about each step of the computation... a step is an
67  // instance of a NetworkNode, but a NetworkNode may in general have multiple
68  // steps. A single step may turn into no commands (for input nodes), or
69  // multiple commands. The StepInfo also contains info about the backprop
70  // corresponding to its forward command.
71  struct StepInfo {
72  int32 node_index; // network-node index
73  int32 value; // sub-matrix index of value that this step outputs.
74  int32 deriv; // sub-matrix index of derivative at the output of this step; zero
75  // if not used (note: index zero is reserved for the empty
76  // matrix).
77 
78  int32 segment; // normally 0 except for online/multi-segment computations,
79  // identifies the segment of which this step is a part (each
80  // segment in the sequence has a different
81  // ComputationRequest).
82 
83  // precomputed_indexes_index is the index into the
84  // component_precomputed_indexes array in the NnetComputation, or zero if
85  // none needed.
87 
88  std::vector<Index> output_indexes; // Indexes that this step outputs.
89  std::vector<int32> output_cindex_ids; // cindex_ids corresponding to each
90  // of the output indexes.
91 
92  // If this component is of type kDescriptor (and note that the top-level
93  // Descriptor is a concatenation over >= 1 parts), then we set value_parts
94  // to a list of submatrix-indexes, each for the corresponding part of the
95  // value. If there is only one part, it will have one element which will be
96  // the same as "value".
97  std::vector<int32> value_parts;
98  // deriv_parts is as "value_parts", but for parts of the derivative (if
99  // we're doing backprop).
100  std::vector<int32> deriv_parts;
101 
102  // for nodes corresponding to descriptors, input_locations_list will contain
103  // information about the inputs to this descriptor, telling us for each row
104  // of the matrix what other matrix rows it is a summation over. this is a
105  // quantity indexed[part-index][row-index], then a list of pairs (step,
106  // row-index), representing source Cindexes present in a summation, that we
107  // store here to avoid computing it twice in forward and backprop.
108  std::vector<std::vector<std::vector<std::pair<int32,int32> > > > input_locations_list;
109 
110  StepInfo(): node_index(-1), value(0), deriv(0), segment(0),
111  precomputed_indexes_index(0) { }
112  };
113 
114  // Computes the set of step-indexes of preceding steps that this step depends
115  // on. Assumes CreateLocationInfo() has already been called. Requires
116  // 'step_index' only to handle a special case, that if 'this_step' is a
117  // component step, then the only step it depends on is the preceding step
118  // (which is the component-input step).
119  void ComputeStepDependencies(const std::vector<int32> &this_step,
120  int32 step_index,
121  unordered_set<int32> *dep_steps);
122 
123  // This function outputs to each element of "deriv_needed" a bool saying
124  // whether, for that step, we need to allocate the matrix of derivatives
125  // (interpret this as being at the output of that step). This variable
126  // also tells us whether we need to execute the backprop code for that step.
127  // 'steps' is a vector of steps; each step is a list of cindexes.
128  // 'step_to_segment', which should have the same dimension as 'steps',
129  // maps from step index to the segment it occurs in (only interesting
130  // for multi-segment/online computations).
131  // 'deriv_needed' will be given the same length as 'steps'.
132  void ComputeDerivNeeded(const std::vector<std::vector<int32> > &steps,
133  const std::vector<int32> &step_to_segment,
134  std::vector<bool> *deriv_needed);
135 
136  // this sets up steps_, destroying the input "by_step" in the process. It
137  // also sets various matrix and sub-matrix sizes in "computation". The input
138  // 'by_step' is elsewhere referred to as just 'step'; it is a vector of steps,
139  // and each step is a vector of cindex_ids that are computed by that step.
140  void CreateStepInfo(const std::vector<bool> &deriv_needed,
141  const std::vector<int32> &step_to_segment,
142  std::vector<std::vector<int32> > *by_step,
143  NnetComputation *computation);
144 
145  // Gets the stride type, kDefaultStride or kStrideEqualNumCols,
146  // at the output of this node: interrogates component flags
147  // looking for kInputContiguous or kOutputContiguous.
148  MatrixStrideType GetStrideType(int32 node_index) const;
149 
150 
151  // Miscellaneous info pertaining to various steps of the computation. Indexed
152  // by step-index.
153  std::vector<StepInfo> steps_;
154 
161  std::vector<std::pair<int32, int32> > cindex_id_to_location_;
162 
163 
164  // Adds to the computation object the information about the matrix sizes
165  void DefineMatrices(NnetComputation *computation) const;
166 
167  // Sets up sub-matrix indexes for nodes of type Descriptor (needed mainly
168  // because Descriptors in general have many parts corresponding to
169  // feature-dimension ranges, and they live in sub-matrices.
170  void DefineSubmatrices(NnetComputation *computation);
171 
172  // Adds to the computation object the commands to allocate the matrices.
173  // 'whole_submatrices' is as created by computation->GetWholeSubmatrices(), it
174  // gives us the index of a submatrix containing the whole of each matrix.
175  void AllocateMatrices(const std::vector<int32> &whole_submatrices,
176  NnetComputation *computation) const;
177 
178  // Sets up the precomputed indexes for each component, and sets the
179  // precomputed_indexes_index value for each step.
180  void SetUpPrecomputedIndexes(const std::vector<int32> &step_to_segment,
181  NnetComputation *computation);
182 
183  // Adds to "computation" the command(s) for the forward computation
184  // for this step.
185  void CompileForward(int32 step, NnetComputation *computation) const;
186 
187  // Called from CompileForward, handles the case where the step corresponds
188  // to a Component.
189  void AddForwardStepComponent(int32 step, NnetComputation *computation) const;
190 
191  // Called from CompileForward, handles the case where the step corresponds
192  // to an input node.
193  void AddForwardStepInput(int32 step, NnetComputation *computation) const;
194 
195  // Returns true if step 'step' is an input step. If step >= steps_.size(),
196  // returns false.
197  bool IsInputStep(int32 step) const;
198 
199 
200  // Called from CompileForward, handles the case where the step
201  // corresponds to type kDescriptor
202  void CompileForwardDescriptor(
203  int32 step, NnetComputation *computation) const;
204 
205  void CompileForwardSumDescriptor(
206  int32 step, int32 part_index, NnetComputation *computation) const;
207 
208 
209  // For the "part_index"'th part of the Descriptor for step "step" (which
210  // must correspond to a Descriptor and not an Input or Component), this
211  // function computes a vector of lists of submatrix locations of the inputs.
212  // It is indexed by the number of rows in the output of this descriptor,
213  // and the i'th element of the output is a list of pairs (step-index,
214  // row-index-of-matrix). The output of this row of this row of this part
215  // of the computation will be a sum over those pairs.
216  void ComputeInputLocationsList(
217  int32 step, int32 part_index,
218  std::vector<std::vector<std::pair<int32, int32> > > *input_locations)
219  const;
220 
273  BaseFloat SplitByScale(const SumDescriptor &descriptor,
274  const std::vector<std::vector<std::pair<int32,int32> > > &input_locations_list,
275  std::vector<std::pair<BaseFloat,
276  std::vector<std::vector<std::pair<int32,int32> > > > >
277  *split_locations_lists) const;
278 
279  // Changes the format of the location-list produced by ComputeInputLocationsList,
280  // to have pairs (sub-matrix, row) instead of (step, row), by replacing each step
281  // (i.e. the first of each pair) with steps_[step].value.
282  void ComputeValueSubmatLocationsList(
283  const std::vector<std::vector<std::pair<int32, int32> > > &input_locations_list,
284  std::vector<std::vector<std::pair<int32, int32> > > *submat_locations_list)
285  const;
286 
287 
288  // Changes the format of the location-list produced by
289  // ComputeInputLocationsList, to have pairs (sub-matrix, row) instead of
290  // (step, row), but with locations of derivatives not values (for use in
291  // backprop). It does this by replacing each step (i.e. the first of each
292  // pair) with steps_[step].deriv, but if this value is zero (i.e. no such
293  // derivative exists) it removes the pair. This could occur in situations
294  // where we only need to propagate the derivative selectively to some inputs.
295  void ComputeDerivSubmatLocationsList(
296  const std::vector<std::vector<std::pair<int32, int32> > > &input_locations_list,
297  std::vector<std::vector<std::pair<int32, int32> > > *submat_locations_list)
298  const;
299 
300 
301 
317  void CompileForwardFromSubmatLocationsList(
318  int32 value_submatrix_index,
319  BaseFloat alpha,
320  const std::vector<std::vector<std::pair<int32, int32> > > &submat_locations,
321  NnetComputation *computation) const;
322 
341  void CompileForwardFromSubmatLocations(
342  int32 value_submatrix_index,
343  BaseFloat alpha,
344  const std::vector<std::pair<int32, int32> > &submat_locations,
345  NnetComputation *computation) const;
346 
347 
353  void CompileForwardFromIndexes(
354  int32 value_submatrix_index,
355  int32 input_submatrix_index,
356  BaseFloat alpha,
357  const std::vector<int32> &indexes,
358  NnetComputation *computation) const;
359 
360 
361  // Adds to "computation" the command(s) for the backward computation (if any) for
362  // this step. (non-const only because we clear the cached submat_locations).
363  void CompileBackward(int32 step, NnetComputation *computation);
364 
365  // Called from CompileBackward, handles the case where the step corresponds
366  // to a Component.
367  void AddBackwardStepComponent(int32 step, NnetComputation *computation) const;
368 
369  // Called from CompileBackward, handles the case where the step
370  // corresponds to an input. If applicable, this generates a command for the
371  // network to provide the derivative w.r.t. the input, to the user.
372  void AddBackwardStepInput(int32 step, NnetComputation *computation) const;
373 
374  // Called from CompileBackward, handles the case where the step
375  // corresponds to type kDescriptor.
376  void CompileBackwardDescriptor(
377  int32 step, NnetComputation *computation);
378 
379  // Called from CompileBackwardSumDescriptor.
380  void CompileBackwardSumDescriptor(
381  int32 step, int32 part_index,
382  NnetComputation *computation) const;
383 
384  // Called from CompileBackwardForwardingDescriptor.
385  void CompileBackwardFromSubmatLocationsList(
386  int32 deriv_submatrix_index,
387  BaseFloat alpha,
388  const std::vector<std::vector<std::pair<int32, int32> > >&submat_locations,
389  NnetComputation *computation) const;
390 
391 
392  void CompileBackwardFromSubmatLocations(
393  int32 deriv_submatrix_index,
394  BaseFloat alpha,
395  const std::vector<std::pair<int32, int32> > &submat_locations,
396  NnetComputation *computation) const;
397 
398  // Called from CompileBackwardFromSubmatLocations - special case where
399  // input is from just one matrix.
400  void CompileBackwardFromIndexes(
401  int32 deriv_submatrix_index,
402  int32 input_deriv_submatrix_index,
403  BaseFloat alpha,
404  const std::vector<int32> &indexes,
405  NnetComputation *computation) const;
406 
407 
408  // [to be called after steps_ is set up and all the forward and backprop
409  // commands have been added]. Adds to the computation the commands that
410  // deinitialize all the matrices, except those that may be requested by
411  // the user after the computation is done (i.e. outputs of the network,
412  // and input derivatives).
413  // 'whole_submatrices' is as created by computation->GetWholeSubmatrices(), it
414  // gives us the index of a submatrix containing the whole of each matrix.
415  void DeallocateMatrices(const std::vector<int32> &whole_submatrices,
416  const std::vector<int32> &step_to_segment,
417  NnetComputation *computation);
418 
419  // sets up the debug_info member of "computation".
420  void OutputDebugInfo(NnetComputation *computation) const;
421 
422  void AddCommands(const std::vector<bool> &deriv_needed,
423  const std::vector<int32> &step_to_segment,
424  NnetComputation *computation);
425 
426 };
427 
428 
429 
430 
431 } // namespace nnet3
432 } // namespace kaldi
433 
434 
435 #endif
This code computes Goodness of Pronunciation (GOP) and extracts phone-level pronunciation feature for...
Definition: chain.dox:20
std::vector< Index > output_indexes
Definition: nnet-compile.h:88
std::vector< std::vector< std::vector< std::pair< int32, int32 > > > > input_locations_list
Definition: nnet-compile.h:108
kaldi::int32 int32
The two main classes defined in this header are struct ComputationRequest, which basically defines a ...
ComputationGraph graph_
Definition: nnet-compile.h:64
This is an abstract base-class.
MatrixStrideType
Definition: matrix-common.h:44
std::vector< int32 > value_parts
Definition: nnet-compile.h:97
std::vector< int32 > output_cindex_ids
Definition: nnet-compile.h:89
std::vector< int32 > deriv_parts
Definition: nnet-compile.h:100
std::vector< StepInfo > steps_
Definition: nnet-compile.h:153
std::vector< const ComputationRequest * > requests_
Definition: nnet-compile.h:62
This class creates an initial version of the NnetComputation, without any optimization or sharing of ...
Definition: nnet-compile.h:44
std::vector< std::pair< int32, int32 > > cindex_id_to_location_
This maps each cindex_id to its location.
Definition: nnet-compile.h:161
The first step in compilation is to turn the ComputationSpecification into a ComputationGraph, where for each Cindex we have a list of other Cindexes that it depends on.