2929namespace kaldi {
3030namespace nnet3 {
3131
32- // Options class for the process of turning a ComputationSpecification into a
33- // NnetComputation.
34- struct NnetCompileConfig {
35-
36- void Register (OptionsItf *po) {
37- }
38- };
39-
4032// The first step in compilation is to turn the ComputationSpecification
4133// into a ConcreteComputationGraph, where for each Cindex we have a list of
42- // other Cindexes that it depends on.
34+ // other Cindexes that it depends on, and compute the shortest distance to
35+ // the input.
4336struct ConcreteComputationGraph {
4437
4538 // Maps each Cindex to an integer (call this cindex_id) that uniquely
@@ -56,70 +49,149 @@ struct ConcreteComputationGraph {
5649 // calling GetInputIndexes on the relevant Component (with the relevant
5750 // Index), and then calling MapToInput on its InputDescriptor.
5851 std::vector<std::vector<int32> > dependencies;
59-
60-
61- };
62-
6352
53+ // a vector of node type indexed by node-index (as used in the Nnet);
54+ // this is just worked out from the Nnet. This information is needed
55+ // in some computations relating to ConcreteComputationGraph.
56+ std::vector<NetworkNode::NodeType> node_type;
6457
58+
59+ };
6560
66- } // namespace nnet2
67- } // namespace kaldi
6861
62+ void ComputeComputationGraph (const ComputationRequest &computation_request,
63+ const Nnet &nnet,
64+ ConcreteComputationGraph *computation_graph);
6965
70- #endif
7166
72- /*
73- Compilation model...
7467
75- list of objects to learn and have stats for (e.g. SoftmaxComponent, AffineComponent, FixedAffineComponent)
7668
77- Then a compilation method to go from either a training or test setup, to an
78- NnetComputation.
79- An NnetComputation is:
80-
81- A number of declarations of matrices, with sizes, each being the input or output of a
82- particular layer (may be both the input of one layer and the output of
83- another). Also declarations of sub-matrices.
84- A number of commands, such as:
85- Initialize matrix; zero matrix; deinitialize matrix; do Propagate or Backprop;
86- do forward or backward of AddMatrix or CopyMatrix.
69+ // This class creates an initial version of the NnetComputation, without any
70+ // optimization or sharing of matrices.
71+ void ComputationCreator {
72+ public:
73+ ComputationCreator (const ComputationRequest &request,
74+ const Nnet &nnet,
75+ const ConcreteComputationGraph &computation_graph);
8776
88- Get rid of all this complexity and just accept redundant copy?? I.e. do it all in C++?
89- -- Linear list of components, each with list of inputs, if needed? Sharing of parameters
90- between components? [ComponentInstance vs. Component]
91- [?
92-
93- Given required output indexes, and maybe some background info,
77+ void CreateComputation (NnetComputation *computation);
78+
79+ private:
80+ const ComputationRequest &request_;
81+ const ConcreteComputationGraph &computation_graph_;
82+ // / shortest_distance_ is shortest distance from inputs (distance 0) to each
83+ // / cindex_id in the computation graph.
84+ std::vector<int32> shortest_distance_;
85+ // / steps_[i] lists the cindex_ids at the output of the i'th component computation.
86+ std::vector<std::vector<int32> > steps_;
87+
88+ // This maps each cindex_id to the location
89+ std::vector<std::pair<int32, int32> > cindex_id_to_location_;
90+
91+ // Some generic information about each step of the computation... a step
92+ // is an instance of a NetworkNode, but a NetworkNode may in unrolled computations
93+ // have multiple steps.
94+ struct StepInfo {
95+ int32 node_id; // network-node id.
96+ Network::NodeType node_type; // the type of the node: {kComponent,kInput,kOutput}.
97+ int32 input_matrix; // matrix index of input matrix.
98+ int32 output; // matrix index of output matrix.
99+ int32 output_deriv; // matrix index of output derivative
100+ int32 input_deriv; // matrix index of input derivative.
101+ std::vector<Index> input_indexes;
102+ LocationInfo (): input(-1 ), output(-1 ), output_deriv(-1 ), input_deriv(-1 ) { }
103+ };
104+
105+ // This
106+ std::vector<StepInfo> step_info_;
107+
108+ // / Indexed by the same index as steps_, gives us the input matrix index for
109+ // / this step.
110+ std::vector<int32> input_matrices_;
111+ // / Indexed by the same index as steps_, gives us the list of indexes at the
112+ // / input location for each step.
113+ std::vector<std::vector<Index> > input_indexes_;
114+
115+
116+ // Computes, for each cindex_id, the shortest distance to the input (0 for input
117+ // components). It is an error if some cindex_ids are not reachable from the
118+ // input.
119+ static void ComputeShortestDistances (
120+ const ConcreteComputationGraph &computation_graph,
121+ std::vector<int32> *shortest_distance);
122+
123+
124+ // This works out the steps of the computation and their order. Once you have
125+ // the shortest-distances from the input to the Cindexes, this function orders
126+ // the Cindexes from closest to furthest the input, and then within each
127+ // category that has the same distance to the input, orders the Cindexes by the
128+ // component index. This gives us categories with the same component index and
129+ // the same distance to the input, and those categories are the steps of the
130+ // computation. As special cases, all the accessed input nodes are listed first
131+ // and all the output nodes are listed last, with each input/output node
132+ // as a single step; and it makes sure that the order of the Cindexes at
133+ // the input and output steps is the same as the order specified in the
134+ // ComputationRequest.
135+ static void ComputeComputationOrder (
136+ const ComputationRequest &request,
137+ const ConcreteComputationGraph &computation_graph,
138+ const std::vector<int32> &shortest_distance,
139+ std::vector<std::vector<int32> > *steps);
140+
141+ // This function computes a vector that maps each cindex_id to the
142+ // corresponding two indices into "steps"; this also gives us
143+ // the location as (matrix-index, row-index) of each Cindex.
144+ static void ComputeLocationInfo (
145+ const std::vector<std::vector<int32> > &steps,
146+ std::vector<std::pair<int32, int32> > *cindex_id_to_location);
147+
148+
149+ // Assign some basic information about the steps of the computation, chiefly
150+ // the locations of the input and output matrices and the corresponding
151+ // derivatives; and index information about the input of each
152+ // step (only for real Components[?]).
153+ // Note, matrix-index zero is at this stage reserved for the empty matrix.
154+ // In the "computation" object, we store the sizes of these matrices.
155+ static void GetStepInfo (const ComputationRequest &request,
156+ const Nnet &nnet,
157+ std::vector<StepInfo> *step_info,
158+ NnetComputation *computation);
159+
160+ // [to be called after step_info_ is set up]. Adds to the computation the
161+ // commands that initialize all the matrices. Also defines sub-matrices
162+ // corresponding to each matrix, with the same index.
163+ void SetUpForwardMatrices (NnetComputation *computation);
164+
165+ // Adds to "computation" the commands to set up the input matrix for a step
166+ // ("step" must correspond to a Component or an output node). This
167+ // involves processing the InputDescriptor.
168+ void SetUpInputForward (int32 step, NnetComputation *computation);
169+
170+ // Adds to "computation" the command for the forward computation for this step
171+ // (which must correspond to a real component).
172+ void DoForwardComputation (int32 step, NnetComputation *computation);
173+
174+ // Adds to "computation" the commands to do backprop from the input
175+ // matrix for a step ("step" must correspond to a Component or an output
176+ // node). This involves processing the InputDescriptor.
177+ void BackpropFromInputBackward (int32 step, NnetComputation *computation);
94178
95-
179+ // Adds to "computation" the command for the backward computation for this step
180+ // (which must correspond to a real component).
181+ void DoBackwardComputation (int32 step, NnetComputation *computation);
182+
183+ // [to be called after step_info_ is set up and all the forward and backprop
184+ // commands have been added]. Adds to the computation the commands that
185+ // deinitialize all the matrices.
186+ void DestroyMatrices (NnetComputation *computation);
96187
97- need e.g. out[1]
188+ };
98189
99- out_obj=SoftmaxObject
100190
101- out(t,n,x) = SoftmaxComponent(dim=1000), input=layer10(t,n,x)
102- layer10(t,n,x) = AffineComponent(input-dim=1000, output-dim=1000), input=layer9(t,n,x)
103- layer9(t,n,x) = RectifiedLinearComponent(dim=1000), input=Append(layer8(t-4,n,x), layer8(t+4,n,x))
104- layer8(.....) =
105- ... below, input is a matrix! ...
106- layer5(0,n,x) = AggregateComponent(dim=1000, sub-dim=5000), input=layer4(*, n, x) <--- The * could be, say, [100,200,300]
107- <--- layer4 would have to have indexes declared.
108- ... this is many-to-one, so input would have to have a set of
109191
110- layer1[t-5],layer1[t+5]
192+ } // namespace nnet2
193+ } // namespace kaldi
111194
112- ---
113- At some point we generate a program.
114- Training program example:
115195
116- Declare matrices and sub-matrices (m), and "real components" (c),
117- and backprop quantities n.
118-
119- Assume input provided as m[0], output will be given as various
120- parts of the matrices, including the output itself]. (e.g. DeclareOutput(...), meaning
121- we can't delete it.)
122-
123-
124-
125- */
196+ #endif
197+
0 commit comments