MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
ScaleLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using MyCaffe.basecode;
6using MyCaffe.common;
7using MyCaffe.param;
8using MyCaffe.fillers;
9
10namespace MyCaffe.layers
11{
26 public class ScaleLayer<T> : Layer<T>
27 {
28 BiasLayer<T> m_biasLayer = null;
29 BlobCollection<T> m_colBiasBottomVec = new BlobCollection<T>();
30 List<bool> m_rgbBiasPropagateDown = new List<bool>();
31 int m_nBiasParamId;
32 Blob<T> m_blobSumMultiplier;
33 Blob<T> m_blobSumResult;
34 Blob<T> m_blobTemp;
35 int m_nAxis;
36 int m_nOuterDim;
37 int m_nScaleDim;
38 int m_nInnerDim;
39
52 : base(cuda, log, p)
53 {
55 m_blobSumMultiplier = new Blob<T>(cuda, log);
56 m_blobSumMultiplier.Name = m_param.name + " summult";
57 m_blobSumResult = new Blob<T>(cuda, log);
58 m_blobSumResult.Name = m_param.name + " sumres";
59 m_blobTemp = new Blob<T>(cuda, log);
60 m_blobTemp.Name = m_param.name + " temp";
61 }
62
64 protected override void dispose()
65 {
66 if (m_biasLayer != null)
67 {
68 m_biasLayer.Dispose();
69 m_biasLayer = null;
70 }
71
72 if (m_blobSumMultiplier != null)
73 {
74 m_blobSumMultiplier.Dispose();
75 m_blobSumMultiplier = null;
76 }
77
78 if (m_blobSumResult != null)
79 {
80 m_blobSumResult.Dispose();
81 m_blobSumResult = null;
82 }
83
84 if (m_blobTemp != null)
85 {
86 m_blobTemp.Dispose();
87 m_blobTemp = null;
88 }
89
90 base.dispose();
91 }
92
94 protected override void setup_internal_blobs(BlobCollection<T> col)
95 {
96 if (col.Count > 0)
97 return;
98
99 col.Add(m_blobSumMultiplier);
100 col.Add(m_blobSumResult);
101 col.Add(m_blobTemp);
102 }
103
107 public override int MinBottomBlobs
108 {
109 get { return 1; }
110 }
111
115 public override int MaxBottomBlobs
116 {
117 get { return 2; }
118 }
119
123 public override int ExactNumTopBlobs
124 {
125 get { return 1; }
126 }
127
133 public override bool ReInitializeParameters(WEIGHT_TARGET target)
134 {
135 base.ReInitializeParameters(target);
136
137 if (target == WEIGHT_TARGET.BOTH || target == WEIGHT_TARGET.WEIGHTS)
138 {
140 if (fp == null)
141 fp = new FillerParameter("constant", 1.0);
142
143 Filler<T> filler = Filler<T>.Create(m_cuda, m_log, fp);
144 filler.Fill(m_colBlobs[0]);
145 }
146
148 m_biasLayer.ReInitializeParameters(target);
149
150 return true;
151 }
152
153
159 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
160 {
162
163 if (colBottom.Count == 1 && blobs.Count > 0)
164 {
165 m_log.WriteLine("Skipping parameter initialization.");
166 }
167 else if (colBottom.Count == 1)
168 {
169 // scale is a learned parameter; initialize it.
170 m_nAxis = colBottom[0].CanonicalAxisIndex(p.axis);
171 int nNumAxes = p.num_axes;
172 m_log.CHECK_GE(nNumAxes, -1, "num_axes must be non-negative, or -1 to extend to the end of bottom[0].");
173
174 if (nNumAxes >= 0)
175 m_log.CHECK_GE(colBottom[0].num_axes, m_nAxis + nNumAxes, "scale blob's shape extends past bottom[0]'s shape when applied starting with bottom[0] axis = " + m_nAxis.ToString());
176
178
179 List<int> rgShape = new List<int>();
180 int nStart = m_nAxis;
181 int nEnd = (nNumAxes == -1) ? colBottom[0].shape().Count : nStart + nNumAxes;
182
183 for (int i = nStart; i < nEnd; i++)
184 {
185 rgShape.Add(colBottom[0].shape(i));
186 }
187
188 Blob<T> blobScale = new Blob<T>(m_cuda, m_log);
189 blobScale.Name = m_param.name + " scale";
190 blobScale.type = BLOB_TYPE.INTERNAL;
191
192 if (!shareParameter(blobScale, rgShape))
193 {
194 blobScale.Reshape(rgShape);
195 FillerParameter fp = p.filler;
196
197 // Default to unit (1) filler for identity operation.
198 if (fp == null)
199 fp = new FillerParameter("constant", 1.0);
200
201 Filler<T> filler = Filler<T>.Create(m_cuda, m_log, fp);
202 filler.Fill(blobScale);
203 }
204 m_colBlobs.Add(blobScale);
205 }
206
207 if (p.bias_term)
208 {
210 pb.bias_param.axis = p.axis;
211 pb.bias_param.num_axes = (colBottom.Count > 1) ? colBottom[1].num_axes : p.num_axes;
213
214 m_colBiasBottomVec = new BlobCollection<T>();
215 m_colBiasBottomVec.Add(colBottom[0]);
216
217 m_biasLayer = new BiasLayer<T>(m_cuda, m_log, pb);
218 m_biasLayer.Setup(m_colBiasBottomVec, colTop);
219
220 shareLayerBlobs(m_biasLayer);
221
222 m_nBiasParamId = m_colBlobs.Count;
223 m_colBlobs.Add(m_biasLayer.blobs[0]);
224 m_rgbBiasPropagateDown = Utility.Create<bool>(1, false);
225 }
226
227 m_rgbParamPropagateDown = new DictionaryMap<bool>(m_colBlobs.Count(), true);
228 }
229
235 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
236 {
238 Blob<T> blobScale = (colBottom.Count > 1) ? colBottom[1] : m_colBlobs[0];
239
240 // Always set axis == 0 in special case where bias is a scalar
241 // (num_axes == 0. Mathematically eqiuvalent for any choice of axis, so the
242 // actual setting can be safely ignored; and computation is most efficient
243 // with axis == 0 and (therefore) outer_dim == 1. (Setting m_nAxis to
244 // bottom[0].num_axes - 1, giving inner_dim_ == 1, would be equally
245 // performant.)
246 m_nAxis = (blobScale.num_axes == 0) ? 0 : colBottom[0].CanonicalAxisIndex(p.axis);
247 m_log.CHECK_GE(colBottom[0].num_axes, m_nAxis + blobScale.num_true_axes, "scale blob's shape extends past bottom[0]'s shape when applied starting with bottom[0] axis = " + m_nAxis.ToString());
248
249 for (int i = 0; i < blobScale.num_true_axes; i++)
250 {
251 m_log.CHECK_EQ(colBottom[0].shape(m_nAxis + i), blobScale.shape(i), "dimension mismatch between bottom[0]->shape(" + (m_nAxis + i).ToString() + ") and scale->shape(" + i.ToString() + ")");
252 }
253
254 m_nOuterDim = colBottom[0].count(0, m_nAxis);
255 m_nScaleDim = blobScale.count();
256 m_nInnerDim = colBottom[0].count(m_nAxis + blobScale.num_true_axes);
257
258 if (colBottom[0] == colTop[0]) // in-place computation
259 m_blobTemp.ReshapeLike(colBottom[0]);
260 else
261 colTop[0].ReshapeLike(colBottom[0]);
262
263 m_blobSumResult.Reshape(new List<int>() { m_nOuterDim * m_nScaleDim });
264 int nSumMultSize = Math.Max(m_nOuterDim, m_nInnerDim);
265 m_blobSumMultiplier.Reshape(new List<int>() { nSumMultSize });
266 m_blobSumMultiplier.SetData(1.0);
267
268 if (m_biasLayer != null)
269 {
270 m_colBiasBottomVec[0] = colTop[0];
271 m_biasLayer.Reshape(m_colBiasBottomVec, colTop);
272 }
273 }
274
297 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
298 {
299 if (colBottom[0] == colTop[0])
300 {
301 // in-place computation; need to store bottom data before overwriting it.
302 // Note that this is only necessary for backward; we could skip this if not
303 // doing backward, but Caffe currently provides no way of knowing whether
304 // we'll need to do backward at the time of the forward call.
305 m_blobTemp.CopyFrom(colBottom[0]);
306 }
307
308 long hScaleData = (colBottom.Count > 1) ? colBottom[1].gpu_data : m_colBlobs[0].gpu_data;
309 long hTopData = colTop[0].mutable_gpu_data;
310 int nCount = colTop[0].count();
311 long hBottomData = colBottom[0].gpu_data;
312
313 if (m_biasLayer != null)
314 {
315 long hBiasData = m_colBlobs[m_nBiasParamId].gpu_data;
316 m_cuda.scale_fwd(nCount, hBottomData, hScaleData, m_nScaleDim, m_nInnerDim, hTopData, hBiasData);
317 }
318 else
319 {
320 m_cuda.scale_fwd(nCount, hBottomData, hScaleData, m_nScaleDim, m_nInnerDim, hTopData);
321 }
322 }
323
331 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
332 {
333 if (m_biasLayer != null && m_rgbParamPropagateDown[m_rgbParamPropagateDown.Count - 1])
334 m_biasLayer.Backward(colTop, m_rgbBiasPropagateDown, m_colBiasBottomVec);
335
336 bool bScaleParam = (colBottom.Count == 1) ? true : false;
337 Blob<T> blobScale = (bScaleParam) ? m_colBlobs[0] : colBottom[1];
338
339 if ((!bScaleParam && rgbPropagateDown[1]) || (bScaleParam && m_rgbParamPropagateDown[0]))
340 {
341 long hTopDiff = colTop[0].gpu_diff;
342 bool bInPlace = (colBottom[0] == colTop[0]) ? true : false;
343 long hBottomData = (bInPlace) ? m_blobTemp.gpu_data : colBottom[0].gpu_data;
344
345 // Hack: store big eltwise product in bottom[0].diff, except in the special
346 // case where this layer itself does the eltwise product, in which case we
347 // can store it directly in the scale diff, and we're done.
348 // If we're computing in-place (and not doing eltwise computation), this
349 // hack doesn't work and we store the product in temp_.
350 bool bIsEltwise = (colBottom[0].count() == blobScale.count()) ? true : false;
351 long hProduct = (bIsEltwise) ? blobScale.mutable_gpu_diff : ((bInPlace) ? m_blobTemp.mutable_gpu_data : colBottom[0].mutable_gpu_diff);
352 long hSumMult = m_blobSumMultiplier.gpu_data;
353
354 m_cuda.mul(colTop[0].count(), hTopDiff, hBottomData, hProduct);
355
356 if (!bIsEltwise)
357 {
358 long hSumResult = 0;
359
360 if (m_nInnerDim == 1)
361 {
362 hSumResult = hProduct;
363 }
364 else if (m_blobSumResult.count() == 1)
365 {
366 double dfScaleDiff = convertD(blobScale.GetDiff(0));
367
368 if (bScaleParam)
369 {
370 T fDot = m_cuda.dot(m_nInnerDim, hProduct, hSumMult);
371 dfScaleDiff += convertD(fDot);
372 blobScale.SetDiff(dfScaleDiff, 0);
373 }
374 else
375 {
376 T fDot = m_cuda.dot(m_nInnerDim, hProduct, hSumMult);
377 blobScale.SetDiff(convertD(fDot), 0);
378 }
379 }
380 else
381 {
382 hSumResult = (m_nOuterDim == 1) ? blobScale.mutable_gpu_diff : m_blobSumResult.mutable_gpu_data;
383 m_cuda.gemv(false, m_blobSumResult.count(), m_nInnerDim, m_tOne, hProduct, hSumMult, m_tZero, hSumResult);
384 }
385
386 if (m_nOuterDim != 1)
387 {
388 if (m_nScaleDim == 1)
389 {
390 double dfScaleDiff = convertD(blobScale.GetDiff(0));
391
392 if (bScaleParam)
393 {
394 T fDot = m_cuda.dot(m_nOuterDim, hSumMult, hSumResult);
395 dfScaleDiff += convertD(fDot);
396 blobScale.SetDiff(dfScaleDiff, 0);
397 }
398 else
399 {
400 T fDot = m_cuda.dot(m_nOuterDim, hSumMult, hSumResult);
401 blobScale.SetDiff(convertD(fDot), 0);
402 }
403 }
404 else
405 {
406 long hScaleDiff = blobScale.mutable_gpu_diff;
407 m_cuda.gemv(true, m_nOuterDim, m_nScaleDim, m_tOne, hSumResult, hSumMult, (bScaleParam) ? m_tOne : m_tZero, hScaleDiff);
408 }
409 }
410 }
411 }
412
413 if (rgbPropagateDown[0])
414 {
415 int nCount = colTop[0].count();
416 long hTopDiff = colTop[0].gpu_diff;
417 long hScaleData = blobScale.gpu_data;
418 long hBottomDiff = colBottom[0].mutable_gpu_diff;
419
420 m_cuda.scale_fwd(nCount, hTopDiff, hScaleData, m_nScaleDim, m_nInnerDim, hBottomDiff);
421 }
422 }
423 }
424}
The Log class provides general output in text form.
Definition: Log.cs:13
void WriteLine(string str, bool bOverrideEnabled=false, bool bHeader=false, bool bError=false, bool bDisable=false)
Write a line of output.
Definition: Log.cs:80
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
Definition: Log.cs:239
void CHECK_GE(double df1, double df2, string str)
Test whether one number is greater than or equal to another.
Definition: Log.cs:287
The Utility class provides general utility funtions.
Definition: Utility.cs:35
static List< int > Create(int nCount, int nStart, int nInc)
Create a new List and fill it with values starting with start and incrementing by inc.
Definition: Utility.cs:721
The BlobCollection contains a list of Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
int Count
Returns the number of items in the collection.
void ReshapeLike(BlobCollection< T > src)
Reshapes all blobs in the collection to the sizes of the source.
void Reshape(int[] rgShape)
Reshapes all blobs in the collection to the given shape.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
void SetData(T[] rgData, int nCount=-1, bool bSetCount=true)
Sets a number of items within the Blob's data.
Definition: Blob.cs:1922
int num_axes
Returns the number of axes in the Blob.
Definition: Blob.cs:705
long mutable_gpu_diff
Returns the diff GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1555
T GetDiff(int nIdx)
Returns the diff at a given flat index within the Blob.
Definition: Blob.cs:1907
long mutable_gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1487
int num_true_axes
Returns the number of true axes, ignoring the trailing ones.
Definition: Blob.cs:716
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
Definition: Blob.cs:442
BLOB_TYPE type
Returns the BLOB_TYPE of the Blob.
Definition: Blob.cs:2761
void CopyFrom(Blob< T > src, int nSrcOffset, int nDstOffset, int nCount, bool bCopyData, bool bCopyDiff)
Copy from a source Blob.
Definition: Blob.cs:903
List< int > shape()
Returns an array where each element contains the shape of an axis of the Blob.
Definition: Blob.cs:684
int count()
Returns the total number of items in the Blob.
Definition: Blob.cs:739
void ReshapeLike(Blob< T > b, bool? bUseHalfSize=null)
Reshape this Blob to have the same shape as another Blob.
Definition: Blob.cs:648
string Name
Get/set the name of the Blob.
Definition: Blob.cs:2184
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
Definition: Blob.cs:402
void SetDiff(double dfVal, int nIdx=-1)
Either sets all of the diff items in the Blob to a given value, or alternatively only sets a single i...
Definition: Blob.cs:1981
long gpu_data
Returns the data GPU handle used by the CudaDnn connection.
Definition: Blob.cs:1479
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
Abstract Filler class used to fill blobs with values.
Definition: Filler.cs:19
void Fill(Blob< T > b)
Fill the blob with values based on the actual filler used.
Definition: Filler.cs:50
static Filler< T > Create(CudaDnn< T > cuda, Log log, FillerParameter p)
Create a new Filler instance.
Definition: Filler.cs:79
The BiasLayer computes a sum of two input Blobs, with the shape of the latter Blob 'broadcast' to mat...
Definition: BiasLayer.cs:25
An interface for the units of computation which can be composed into a Net.
Definition: Layer.cs:31
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
T m_tZero
Specifies a generic type equal to 0.0.
Definition: Layer.cs:76
T m_tOne
Specifies a generic type equal to 1.0.
Definition: Layer.cs:72
bool shareParameter(Blob< T > b, List< int > rgMinShape, bool bAllowEndsWithComparison=false)
Attempts to share a parameter Blob if another parameter Blob with the same name and accpetable size i...
Definition: Layer.cs:1152
bool shareLayerBlobs(Layer< T > layer)
Attempts to share the Layer blobs and internal_blobs with matching names and sizes with those in anot...
Definition: Layer.cs:1187
double convertD(T df)
Converts a generic to a double value.
Definition: Layer.cs:1349
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
Definition: Layer.cs:39
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
BlobCollection< T > blobs
Returns the collection of learnable parameter Blobs for the Layer.
Definition: Layer.cs:875
BlobCollection< T > m_colBlobs
Specifies the learnable parameter Blobs of the Layer.
Definition: Layer.cs:55
DictionaryMap< bool > m_rgbParamPropagateDown
Specifies whether or not to compute the learnable diff of each parameter Blob.
Definition: Layer.cs:63
The ScaleLayer computes the elementwise product of two input Blobs, with the shape of the latter Blob...
Definition: ScaleLayer.cs:27
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
Definition: ScaleLayer.cs:297
ScaleLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The ScaleLayer constructor.
Definition: ScaleLayer.cs:51
override void dispose()
Releases all GPU and host resources used by the Layer.
Definition: ScaleLayer.cs:64
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the error gradient w.r.t the inputs.
Definition: ScaleLayer.cs:331
override void setup_internal_blobs(BlobCollection< T > col)
Derivative layers should add all internal blobws to the 'col' provided.
Definition: ScaleLayer.cs:94
override int MaxBottomBlobs
Returns the maximum number of required bottom (input) Blobs: firstfactor, secondfactor
Definition: ScaleLayer.cs:116
override int MinBottomBlobs
Returns the minimum number of required bottom (input) Blobs: firstfactor
Definition: ScaleLayer.cs:108
override int ExactNumTopBlobs
Returns the exact number of required top (output) Blobs: scale
Definition: ScaleLayer.cs:124
override bool ReInitializeParameters(WEIGHT_TARGET target)
Re-initialize the parameters of the layer.
Definition: ScaleLayer.cs:133
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
Definition: ScaleLayer.cs:159
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: ScaleLayer.cs:235
int axis
The first axis of bottom[0] (the first input Blob) along which to apply bottom[1] (the second input B...
int num_axes
(num_axes is ignored unless just one bottom is given and the bias is a learned parameter of the layer...
FillerParameter filler
(filler is ignored unless just one bottom is given and the bias is a learned parameter of the layer....
Specifies the filler parameters used to create each Filler.
Specifies the base parameter for all layers.
string name
Specifies the name of this LayerParameter.
ScaleParameter scale_param
Returns the parameter set when initialized with LayerType.SCALE
BiasParameter bias_param
Returns the parameter set when initialized with LayerType.BIAS
LayerType
Specifies the layer type.
Specifies the parameters for the ScaleLayer.
bool bias_term
Whether to also learn a bias (equivalent to a ScalarLayer + BiasLayer, but may be more efficient).
FillerParameter bias_filler
Filler used for bias filling.
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
BLOB_TYPE
Defines the tpe of data held by a given Blob.
Definition: Interfaces.cs:62
WEIGHT_TARGET
Defines the type of weight to target in re-initializations.
Definition: Interfaces.cs:38
The MyCaffe.fillers namespace contains all fillers including the Filler class.
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