MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
RNNLayer.cs
1 using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Threading.Tasks;
6using MyCaffe.basecode;
7using MyCaffe.db.image;
8using MyCaffe.common;
9using MyCaffe.param;
10
11namespace MyCaffe.layers
12{
34 public class RNNLayer<T> : RecurrentLayer<T>
35 {
56 public RNNLayer(CudaDnn<T> cuda, Log log, LayerParameter p, CancelEvent evtCancel)
57 : base(cuda, log, p, evtCancel)
58 {
60 }
61
66 protected override void RecurrentInputBlobNames(List<string> rgNames)
67 {
68 rgNames.Clear();
69 rgNames.Add("h_0");
70 }
71
76 protected override void RecurrentOutputBlobNames(List<string> rgNames)
77 {
78 rgNames.Clear();
79 rgNames.Add("h_" + m_nT.ToString());
80 }
81
86 protected override void RecurrentInputShapes(List<BlobShape> rgShapes)
87 {
88 rgShapes.Clear();
89
90 BlobShape s = new param.BlobShape();
91 s.dim.Add(1); // a single timestep
92 s.dim.Add(m_nN);
94 rgShapes.Add(s);
95 }
96
102 protected override void OutputBlobNames(List<string> rgNames)
103 {
104 rgNames.Clear();
105 rgNames.Add("o");
106 }
107
112 protected override void FillUnrolledNet(NetParameter net_param)
113 {
114 uint nNumOutput = m_param.recurrent_param.num_output;
115 m_log.CHECK_GT(nNumOutput, 0, "num_output must be positive.");
118
119 // Add generic LayerParameter's (without bottoms/tops) of layer types we'll
120 // use to save redundant code.
121 LayerParameter hidden_param = new param.LayerParameter(LayerParameter.LayerType.INNERPRODUCT);
122 hidden_param.inner_product_param.num_output = nNumOutput;
123 hidden_param.inner_product_param.bias_term = false;
124 hidden_param.inner_product_param.axis = 2;
125 hidden_param.inner_product_param.weight_filler = weight_filler.Clone();
126
127 LayerParameter biased_hidden_param = hidden_param.Clone(false);
128 biased_hidden_param.inner_product_param.bias_term = true;
129 biased_hidden_param.inner_product_param.bias_filler = bias_filler.Clone();
130
131 LayerParameter sum_param = new param.LayerParameter(LayerParameter.LayerType.ELTWISE);
133
135
136 LayerParameter scale_param = new LayerParameter(LayerParameter.LayerType.SCALE);
137 scale_param.scale_param.axis = 0;
138
139 LayerParameter slice_param = new LayerParameter(LayerParameter.LayerType.SLICE);
140 slice_param.slice_param.axis = 0;
141
142 List<BlobShape> rgInputShapes = new List<BlobShape>();
143 RecurrentInputShapes(rgInputShapes);
144 m_log.CHECK_EQ(1, rgInputShapes.Count, "There should only be one input shape.");
145
146
147 //--- Add the layers ---
148
149 LayerParameter input_layer_param = new LayerParameter(LayerParameter.LayerType.INPUT);
150 input_layer_param.top.Add("h_0");
151 input_layer_param.input_param.shape.Add(rgInputShapes[0]);
152 net_param.layer.Add(input_layer_param);
153
154 LayerParameter cont_slice_param = slice_param.Clone(false);
155 cont_slice_param.name = "cont_slice";
156 cont_slice_param.bottom.Add("cont");
157 cont_slice_param.slice_param.axis = 0;
158 net_param.layer.Add(cont_slice_param);
159
160 // Add layer to transform all timesteps of x to the hidden state dimension.
161 // W_xh_x = W_xh * x + b_h
162 {
163 LayerParameter x_transform_param = biased_hidden_param.Clone(false);
164 x_transform_param.name = "x_transform";
165 x_transform_param.parameters.Add(new ParamSpec("W_xh"));
166 x_transform_param.parameters.Add(new ParamSpec("b_h"));
167 x_transform_param.bottom.Add("x");
168 x_transform_param.top.Add("W_xh_x");
169 x_transform_param.propagate_down.Add(true);
170 net_param.layer.Add(x_transform_param);
171 }
172
173 if (m_bStaticInput)
174 {
175 // Add layer to transform x_static to the hidden state dimension.
176 // W_xh_x_static = W_xh_static * x_static
177 LayerParameter x_static_transform_param = hidden_param.Clone(false);
178 x_static_transform_param.inner_product_param.axis = 1;
179 x_static_transform_param.name = "W_xh_x_static";
180 x_static_transform_param.parameters.Add(new ParamSpec("W_xh_static"));
181 x_static_transform_param.bottom.Add("x_static");
182 x_static_transform_param.top.Add("W_xh_x_static_preshape");
183 x_static_transform_param.propagate_down.Add(true);
184 net_param.layer.Add(x_static_transform_param);
185
186 LayerParameter reshape_param = new LayerParameter(LayerParameter.LayerType.RESHAPE);
187 BlobShape new_shape = reshape_param.reshape_param.shape;
188 new_shape.dim.Add(1); // One timestep.
189 new_shape.dim.Add(-1); // Should infer m_nN as the dimension so we can reshape on batch size.
190 new_shape.dim.Add((int)x_static_transform_param.inner_product_param.num_output);
191 reshape_param.name = "W_xh_x_static_reshape";
192 reshape_param.bottom.Add("W_xh_x_static_preshape");
193 reshape_param.top.Add("W_xh_x_static");
194 net_param.layer.Add(reshape_param);
195 }
196
197 LayerParameter x_slice_param = slice_param.Clone(false);
198 x_slice_param.name = "W_xh_x_slice";
199 x_slice_param.bottom.Add("W_xh_x");
200 net_param.layer.Add(x_slice_param);
201
202 LayerParameter output_concat_layer = new LayerParameter(LayerParameter.LayerType.CONCAT);
203 output_concat_layer.name = "o_concat";
204 output_concat_layer.top.Add("o");
205 output_concat_layer.concat_param.axis = 0;
206
207 for (int t = 1; t <= m_nT; t++)
208 {
209 string tm1s = (t - 1).ToString();
210 string ts = t.ToString();
211
212 cont_slice_param.top.Add("cont_" + ts);
213 x_slice_param.top.Add("W_xh_x_" + ts);
214
215
216 // Add layer to flush the hidden state when beginning a new sequence,
217 // as indicated by cont_t.
218 // h_conted_{t-1} := cont_t * h_{t-1}
219 //
220 // Normally, cont_t is binary (i.e., 0 or 1), so:
221 // h_conted_{t-1} := h_{t-1} if cont_t == 1
222 // 0 otherwise.
223 {
224 LayerParameter cont_h_param = scale_param.Clone(false);
225 cont_h_param.name = "h_conted_" + tm1s;
226 cont_h_param.bottom.Add("h_" + tm1s);
227 cont_h_param.bottom.Add("cont_" + ts);
228 cont_h_param.top.Add("h_conted_" + tm1s);
229 net_param.layer.Add(cont_h_param);
230 }
231
232 // Add layer to compute
233 // W_hh_h_{t-1} := W_hh * h_conted_{t-1}
234 {
235 LayerParameter w_param = hidden_param.Clone(false);
236 w_param.name = "W_hh_h_" + tm1s;
237 w_param.parameters.Add(new ParamSpec("W_hh"));
238 w_param.bottom.Add("h_conted_" + tm1s);
239 w_param.top.Add("W_hh_h_" + tm1s);
240 w_param.inner_product_param.axis = 2;
241 net_param.layer.Add(w_param);
242 }
243
244 // Add layers to compute
245 // h_t := \tanh( W_hh * h_conted_t{t-1} + W_xh * x_t + b_h )
246 // = \tanh( W_hh_h_{t-1} + W_xh_t )
247 {
248 LayerParameter h_input_sum_param = sum_param.Clone(false);
249 h_input_sum_param.name = "h_input_sum_" + ts;
250 h_input_sum_param.bottom.Add("W_hh_h_" + tm1s);
251 h_input_sum_param.bottom.Add("W_xh_x_" + ts);
252
253 if (m_bStaticInput)
254 h_input_sum_param.bottom.Add("W_xh_x_static");
255
256 h_input_sum_param.top.Add("h_neuron_input_" + ts);
257 net_param.layer.Add(h_input_sum_param);
258 }
259 {
260 LayerParameter h_neuron_param = tanh_param.Clone(false);
261 h_neuron_param.name = "h_neuron_input_" + ts;
262 h_neuron_param.bottom.Add("h_neuron_input_" + ts);
263 h_neuron_param.top.Add("h_" + ts);
264 net_param.layer.Add(h_neuron_param);
265 }
266
267 // Add layer to compute
268 // W_ho_h_t := W_ho * h_t + b_o
269 {
270 LayerParameter w_param = biased_hidden_param.Clone(false);
271 w_param.name = "W_ho_h_" + ts;
272 w_param.parameters.Add(new ParamSpec("W_ho"));
273 w_param.parameters.Add(new ParamSpec("b_o"));
274 w_param.bottom.Add("h_" + ts);
275 w_param.top.Add("W_ho_h_" + ts);
276 w_param.inner_product_param.axis = 2;
277 net_param.layer.Add(w_param);
278 }
279
280 // Add layer to compute
281 // o_t := \tanh( W_ho * h_t + b_o
282 // = \tanh( W_ho_h_t )
283 {
284 LayerParameter o_neuron_param = tanh_param.Clone(false);
285 o_neuron_param.name = "o_neuron_" + ts;
286 o_neuron_param.bottom.Add("W_ho_h_" + ts);
287 o_neuron_param.top.Add("o_" + ts);
288 net_param.layer.Add(o_neuron_param);
289 }
290
291 output_concat_layer.bottom.Add("o_" + ts);
292 }
293
294 net_param.layer.Add(output_concat_layer.Clone(false));
295 }
296 }
297}
The CancelEvent provides an extension to the manual cancel event that allows for overriding the manua...
Definition: CancelEvent.cs:17
The Log class provides general output in text form.
Definition: Log.cs:13
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
Definition: Log.cs:239
void CHECK_GT(double df1, double df2, string str)
Test whether one number is greater than another.
Definition: Log.cs:299
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
Log m_log
Specifies the Log for output.
Definition: Layer.cs:43
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
Definition: Layer.cs:47
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
The RNNLayer processes time-varying inputs using a simple recurrent neural network (RNN)....
Definition: RNNLayer.cs:35
override void RecurrentOutputBlobNames(List< string > rgNames)
Fills the rgNames array with names of the Tth timestep recurrent output Blobs.
Definition: RNNLayer.cs:76
override void FillUnrolledNet(NetParameter net_param)
Fills the NetParameter with the RNN network architecture.
Definition: RNNLayer.cs:112
override void RecurrentInputShapes(List< BlobShape > rgShapes)
Fill the rgShapes array with the shapes of the recurrent input Blobs.
Definition: RNNLayer.cs:86
override void OutputBlobNames(List< string > rgNames)
Fills the rgNames array with the names of the output Blobs, concatenated across all timesteps.
Definition: RNNLayer.cs:102
RNNLayer(CudaDnn< T > cuda, Log log, LayerParameter p, CancelEvent evtCancel)
The RNNLayer constructor.
Definition: RNNLayer.cs:56
override void RecurrentInputBlobNames(List< string > rgNames)
Fills the rgNames array with the names of the 0th timestep recurrent input Blobs.
Definition: RNNLayer.cs:66
The RecurrentLayer is an abstract class for implementing recurrent behavior inside of an unrolled new...
int m_nN
The number of independent streams to process simultaneously.
int m_nT
The number of timesteps in the layer's input, and the number of timesteps over which to backpropagate...
bool m_bStaticInput
Whether the layer has a 'static' input copies across all timesteps.
int axis
The first axis of bottom[0] (the first input Blob) along which to apply bottom[1] (the second input B...
Specifies the shape of a Blob.
Definition: BlobShape.cs:15
BlobShape()
The BlobShape constructor.
Definition: BlobShape.cs:21
List< int > dim
The blob shape dimensions.
Definition: BlobShape.cs:93
int axis
The axis along which to concatenate – may be negative to index from the end (e.g.,...
Specifies the parameters for the EltwiseLayer.
EltwiseOp
Defines the operation to perform.
EltwiseOp operation
Specifies the element-wise operation.
Specifies the filler parameters used to create each Filler.
FillerParameter Clone()
Creates a new copy of this instance of the parameter.
FillerParameter weight_filler
The filler for the weights.
int axis
Specifies the first axis to be lumped into a single inner product computation; all preceding axes are...
FillerParameter bias_filler
The filler for the bias.
uint num_output
The number of outputs for the layer.
bool bias_term
Whether to have bias terms or not.
List< BlobShape > shape
Define N shapes to set a shape for each top. Define 1 shape to set the same shape for every top....
Specifies the base parameter for all layers.
LayerParameter()
Constructor for the parameter.
List< ParamSpec > parameters
Specifies the ParamSpec parameters of the LayerParameter.
SliceParameter slice_param
Returns the parameter set when initialized with LayerType.SLICE
string name
Specifies the name of this LayerParameter.
List< bool > propagate_down
Specifies whether or not the LayerParameter (or protions of) should be backpropagated.
ScaleParameter scale_param
Returns the parameter set when initialized with LayerType.SCALE
EltwiseParameter eltwise_param
Returns the parameter set when initialized with LayerType.ELTWISE
InputParameter input_param
Returns the parameter set when initialized with LayerType.INPUT
List< string > top
Specifies the active top connections (in the bottom, out the top)
ReshapeParameter reshape_param
Returns the parameter set when initialized with LayerType.RESHAPE
InnerProductParameter inner_product_param
Returns the parameter set when initialized with LayerType.INNERPRODUCT
ConcatParameter concat_param
Returns the parameter set when initialized with LayerType.CONCAT
RecurrentParameter recurrent_param
Returns the parameter set when initialized with LayerType.RECURRENT
List< string > bottom
Specifies the active bottom connections (in the bottom, out the top).
LayerType
Specifies the layer type.
virtual LayerParameter Clone(bool bCloneBlobs)
Creates a new copy of this instance of the parameter.
Specifies the parameters use to create a Net
Definition: NetParameter.cs:18
List< LayerParameter > layer
The layers that make up the net. Each of their configurations, including connectivity and behavior,...
Specifies training parameters (multipliers on global learning constants, and the name of other settin...
Definition: ParamSpec.cs:19
uint num_output
The dimension of the output (and usually hidden state) representation – must be explicitly set to non...
FillerParameter weight_filler
The filler for the weights.
FillerParameter bias_filler
The filler for the bias.
BlobShape shape
Specifies the output dimensions.
int axis
Specifies the axis along wich to slice – may be negative to index from the end (e....
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
Definition: Annotation.cs:12
The MyCaffe.common namespace contains common MyCaffe classes.
Definition: BatchInput.cs:8
The MyCaffe.db.image namespace contains all image database related classes.
Definition: Database.cs:18
The MyCaffe.layers namespace contains all layers that have a solidified code base,...
Definition: LayerFactory.cs:15
The MyCaffe.param namespace contains parameters used to create models.
The MyCaffe namespace contains the main body of MyCaffe code that closesly tracks the C++ Caffe open-...
Definition: Annotation.cs:12