MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
SPPLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using MyCaffe.basecode;
6using MyCaffe.common;
7using MyCaffe.param;
8
9namespace MyCaffe.layers
10{
24 public class SPPLayer<T> : Layer<T>
25 {
26 int m_nPyramidHeight;
27 int m_nBottomH;
28 int m_nBottomW;
29 int m_nNum;
30 int m_nChannels;
31 //int m_nKernelH;
32 //int m_nKernelW;
33 //int m_nPadH;
34 //int m_nPadW;
35 bool m_bReshapedFirstTime;
39 SplitLayer<T> m_split_layer;
43 BlobCollection<T> m_colBlobSplitTopVec = new BlobCollection<T>();
47 List<BlobCollection<T>> m_rgPoolingBottomVec = new List<BlobCollection<T>>();
51 List<PoolingLayer<T>> m_rgPoolingLayers = new List<PoolingLayer<T>>();
55 List<BlobCollection<T>> m_rgPoolingTopVecs = new List<BlobCollection<T>>();
59 BlobCollection<T> m_colBlobPoolingOutputs = new BlobCollection<T>();
63 List<FlattenLayer<T>> m_rgFlattenLayers = new List<FlattenLayer<T>>();
67 List<BlobCollection<T>> m_rgFlattenLayerTopVecs = new List<BlobCollection<T>>();
71 BlobCollection<T> m_colBlobFlattenOutputs = new BlobCollection<T>();
75 BlobCollection<T> m_colBlobConcatBottomVec = new BlobCollection<T>();
79 ConcatLayer<T> m_concat_layer;
80
81
94 : base(cuda, log, p)
95 {
97 }
98
100 protected override void dispose()
101 {
102 foreach (PoolingLayer<T> layer in m_rgPoolingLayers)
103 {
104 layer.Dispose();
105 }
106
107 m_rgPoolingLayers.Clear();
108
109 if (m_colBlobSplitTopVec != null)
110 {
111 m_colBlobSplitTopVec.Dispose();
112 m_colBlobSplitTopVec = null;
113 }
114
115 if (m_split_layer != null)
116 {
117 m_split_layer.Dispose();
118 m_split_layer = null;
119 }
120
121 if (m_colBlobPoolingOutputs != null)
122 {
123 m_colBlobPoolingOutputs.Dispose();
124 m_colBlobPoolingOutputs = null;
125 }
126
127 if (m_colBlobFlattenOutputs != null)
128 {
129 m_colBlobFlattenOutputs.Dispose();
130 m_colBlobFlattenOutputs = null;
131 }
132
133 foreach (FlattenLayer<T> layer in m_rgFlattenLayers)
134 {
135 layer.Dispose();
136 }
137
138 m_rgFlattenLayers.Clear();
139
140 m_rgPoolingBottomVec.Clear();
141 m_rgPoolingTopVecs.Clear();
142 m_rgFlattenLayerTopVecs.Clear();
143
144 base.dispose();
145 }
146
150 public override int ExactNumBottomBlobs
151 {
152 get { return 1; }
153 }
154
158 public override int ExactNumTopBlobs
159 {
160 get { return 1; }
161 }
162
172 protected virtual LayerParameter getPoolingParam(int nPyramidLevel, int nBottomH, int nBottomW, SPPParameter spp_param)
173 {
174 LayerParameter pool_param = new param.LayerParameter(LayerParameter.LayerType.POOLING);
175 int nNumBins = (int)Math.Pow(2, nPyramidLevel);
176
177 // find padding and kernel size so that the pooling is
178 // performed across the entrie image
179 int nKernelH = (int)Math.Ceiling(nBottomH / (double)nNumBins);
180 int nKernelW = (int)Math.Ceiling(nBottomW / (double)nNumBins);
181 // remainder_H is the min number of pixels that need to be padded before
182 // entire image height is pooled over with the chosen kernel simension
183 int nRemainderH = nKernelH * nNumBins - nBottomH;
184 int nRemainderW = nKernelW * nNumBins - nBottomW;
185 // pooling layer pads (2 * pad_h) pixels on the top and bottom of the
186 // image.
187 int nPadH = (nRemainderH + 1) / 2;
188 int nPadW = (nRemainderW + 1) / 2;
189
190 pool_param.pooling_param.pad_h = (uint)nPadH;
191 pool_param.pooling_param.pad_w = (uint)nPadW;
192 pool_param.pooling_param.kernel_h = (uint)nKernelH;
193 pool_param.pooling_param.kernel_w = (uint)nKernelW;
194 pool_param.pooling_param.stride_h = (uint)nKernelH;
195 pool_param.pooling_param.stride_w = (uint)nKernelW;
196 pool_param.pooling_param.pool = spp_param.pool;
197
198 return pool_param;
199 }
200
206 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
207 {
208 m_nNum = colBottom[0].num;
209 m_nChannels = colBottom[0].channels;
210 m_nBottomH = colBottom[0].height;
211 m_nBottomW = colBottom[0].width;
212 m_bReshapedFirstTime = false;
213
214 m_log.CHECK_GT(m_nBottomH, 0, "Input dimensions cannot be zero.");
215 m_log.CHECK_GT(m_nBottomW, 0, "Input dimensions cannot be zero.");
216
217 m_nPyramidHeight = (int)m_param.spp_param.pyramid_height;
218
219 m_colBlobSplitTopVec = new BlobCollection<T>();
220 m_rgPoolingBottomVec = new List<BlobCollection<T>>();
221 m_rgPoolingLayers = new List<PoolingLayer<T>>();
222 m_rgPoolingTopVecs = new List<BlobCollection<T>>();
223 m_colBlobPoolingOutputs = new BlobCollection<T>();
224 m_rgFlattenLayers = new List<FlattenLayer<T>>();
225 m_rgFlattenLayerTopVecs = new List<BlobCollection<T>>();
226 m_colBlobFlattenOutputs = new BlobCollection<T>();
227 m_colBlobConcatBottomVec = new BlobCollection<T>();
228
229 if (m_nPyramidHeight == 1)
230 {
231 // pooling layer setup
232 LayerParameter pp = getPoolingParam(0, m_nBottomH, m_nBottomW, m_param.spp_param);
233 m_rgPoolingLayers.Add(new PoolingLayer<T>(m_cuda, m_log, pp));
234 m_rgPoolingLayers[0].Setup(colBottom, colTop);
235 return;
236 }
237
238 // split layer output holders setup
239 for (int i = 0; i < m_nPyramidHeight; i++)
240 {
241 m_colBlobSplitTopVec.Add(new Blob<T>(m_cuda, m_log));
242 }
243
244 // split layer setup
245 LayerParameter split_param = new param.LayerParameter(LayerParameter.LayerType.SPLIT);
246 m_split_layer = new SplitLayer<T>(m_cuda, m_log, split_param);
247 m_split_layer.Setup(colBottom, m_colBlobSplitTopVec);
248
249 for (int i = 0; i < m_nPyramidHeight; i++)
250 {
251 // pooling layer input holders setup
252 m_rgPoolingBottomVec.Add(new BlobCollection<T>());
253 m_rgPoolingBottomVec[i].Add(m_colBlobSplitTopVec[i]);
254
255 // pooling layer output holders setup
256 m_colBlobPoolingOutputs.Add(new Blob<T>(m_cuda, m_log));
257 m_rgPoolingTopVecs.Add(new BlobCollection<T>());
258 m_rgPoolingTopVecs[i].Add(m_colBlobPoolingOutputs[i]);
259
260 // pooling layer setup
261 LayerParameter pooling_param = getPoolingParam(i, m_nBottomH, m_nBottomW, m_param.spp_param);
262 m_rgPoolingLayers.Add(new PoolingLayer<T>(m_cuda, m_log, pooling_param));
263 m_rgPoolingLayers[i].Setup(m_rgPoolingBottomVec[i], m_rgPoolingTopVecs[i]);
264
265 // flatten layer output holders setup
266 m_colBlobFlattenOutputs.Add(new Blob<T>(m_cuda, m_log));
267 m_rgFlattenLayerTopVecs.Add(new BlobCollection<T>());
268 m_rgFlattenLayerTopVecs[i].Add(m_colBlobFlattenOutputs[i]);
269
270 // flatten layer setup
271 LayerParameter flatten_param = new LayerParameter(LayerParameter.LayerType.FLATTEN);
272 m_rgFlattenLayers.Add(new FlattenLayer<T>(m_cuda, m_log, flatten_param));
273 m_rgFlattenLayers[i].Setup(m_rgPoolingTopVecs[i], m_rgFlattenLayerTopVecs[i]);
274
275 // concat layer input holders setup
276 m_colBlobConcatBottomVec.Add(m_colBlobFlattenOutputs[i]);
277 }
278
279 // concat layer setup
280 LayerParameter concat_param = new LayerParameter(LayerParameter.LayerType.CONCAT);
281 m_concat_layer = new ConcatLayer<T>(m_cuda, m_log, concat_param);
282 m_concat_layer.Setup(m_colBlobConcatBottomVec, colTop);
283 }
284
290 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
291 {
292 m_log.CHECK_EQ(4, colBottom[0].num_axes, "Input must have 4 axes, corresponding to (num, channels, height, width)");
293
294 // Do nothing if bottom shape is unchanged since last Reshape.
295 if (m_nNum == colBottom[0].num &&
296 m_nChannels == colBottom[0].channels &&
297 m_nBottomH == colBottom[0].height &&
298 m_nBottomW == colBottom[0].width &&
299 m_bReshapedFirstTime)
300 return;
301
302 m_nNum = colBottom[0].num;
303 m_nChannels = colBottom[0].channels;
304 m_nBottomH = colBottom[0].height;
305 m_nBottomW = colBottom[0].width;
306 m_bReshapedFirstTime = true;
307
308 if (m_nPyramidHeight == 1)
309 {
310 LayerParameter pooling_param = getPoolingParam(0, m_nBottomH, m_nBottomW, m_param.spp_param);
311
312 if (m_rgPoolingLayers[0] != null)
313 m_rgPoolingLayers[0].Dispose();
314
315 m_rgPoolingLayers[0] = new PoolingLayer<T>(m_cuda, m_log, pooling_param);
316 m_rgPoolingLayers[0].Setup(colBottom, colTop);
317 m_rgPoolingLayers[0].Reshape(colBottom, colTop);
318 return;
319 }
320
321 m_split_layer.Reshape(colBottom, m_colBlobSplitTopVec);
322
323 for (int i = 0; i < m_nPyramidHeight; i++)
324 {
325 LayerParameter pooling_param = getPoolingParam(i, m_nBottomH, m_nBottomW, m_param.spp_param);
326
327 if (m_rgPoolingLayers[i] != null)
328 m_rgPoolingLayers[i].Dispose();
329
330 m_rgPoolingLayers[i] = new PoolingLayer<T>(m_cuda, m_log, pooling_param);
331 m_rgPoolingLayers[i].Setup(m_rgPoolingBottomVec[i], m_rgPoolingTopVecs[i]);
332 m_rgPoolingLayers[i].Reshape(m_rgPoolingBottomVec[i], m_rgPoolingTopVecs[i]);
333 m_rgFlattenLayers[i].Reshape(m_rgPoolingTopVecs[i], m_rgFlattenLayerTopVecs[i]);
334 }
335
336 m_concat_layer.Reshape(m_colBlobConcatBottomVec, colTop);
337 }
338
348 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
349 {
350 if (m_nPyramidHeight == 1)
351 {
352 m_rgPoolingLayers[0].Forward(colBottom, colTop);
353 return;
354 }
355
356 m_split_layer.Forward(colBottom, m_colBlobSplitTopVec);
357
358 for (int i = 0; i < m_nPyramidHeight; i++)
359 {
360 m_rgPoolingLayers[i].Forward(m_rgPoolingBottomVec[i], m_rgPoolingTopVecs[i]);
361 m_rgFlattenLayers[i].Forward(m_rgPoolingTopVecs[i], m_rgFlattenLayerTopVecs[i]);
362 }
363
364 m_concat_layer.Forward(m_colBlobConcatBottomVec, colTop);
365 }
366
375 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
376 {
377 if (!rgbPropagateDown[0])
378 return;
379
380 if (m_nPyramidHeight == 1)
381 {
382 m_rgPoolingLayers[0].Backward(colTop, rgbPropagateDown, colBottom);
383 return;
384 }
385
386 List<bool> rgbConcatPropagateDown = Utility.Create<bool>(m_nPyramidHeight, true);
387 m_concat_layer.Backward(colTop, rgbConcatPropagateDown, m_colBlobConcatBottomVec);
388
389 for (int i = 0; i < m_nPyramidHeight; i++)
390 {
391 m_rgFlattenLayers[i].Backward(m_rgFlattenLayerTopVecs[i], rgbPropagateDown, m_rgPoolingTopVecs[i]);
392 m_rgPoolingLayers[i].Backward(m_rgPoolingTopVecs[i], rgbPropagateDown, m_rgPoolingBottomVec[i]);
393 }
394
395 m_split_layer.Backward(m_colBlobSplitTopVec, rgbPropagateDown, colBottom);
396 }
397 }
398}
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 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 Dispose()
Release all resource used by the collection and its Blobs.
void Add(Blob< T > b)
Add a new Blob to the collection.
The Blob is the main holder of data that moves through the Layers of the Net.
Definition: Blob.cs:25
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
The ConcatLayer takes at least two Blobs and concatentates them along either the num or channel dimen...
Definition: ConcatLayer.cs:24
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: ConcatLayer.cs:72
The FlattenLayer reshapes the input Blob into flat vectors This layer is initialized with the MyCaffe...
Definition: FlattenLayer.cs:28
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
virtual void dispose()
Releases all GPU and host resources used by the Layer.
Definition: Layer.cs:188
void Backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Given the top Blob error gradients, compute the bottom Blob error gradients.
Definition: Layer.cs:815
double Forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Given the bottom (input) Blobs, this function computes the top (output) Blobs and the loss.
Definition: Layer.cs:728
void Dispose()
Releases all GPU and host resources used by the Layer.
Definition: Layer.cs:180
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
Definition: Layer.cs:39
void Setup(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Implements common Layer setup functionality.
Definition: Layer.cs:439
LayerParameter.LayerType m_type
Specifies the Layer type.
Definition: Layer.cs:35
The PoolingLayer pools the input image by taking the max, average, etc. within regions....
Definition: PoolingLayer.cs:23
The SPPLayer does spatial pyramid pooling on the input image by taking the max, average,...
Definition: SPPLayer.cs:25
SPPLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The SPPLayer constructor.
Definition: SPPLayer.cs:93
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: SPPLayer.cs:290
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Computes the forward calculation.
Definition: SPPLayer.cs:348
override int ExactNumTopBlobs
Returns the exact number of required top (output) Blobs: spp.
Definition: SPPLayer.cs:159
override void dispose()
Releases all GPU and host resources used by the Layer.
Definition: SPPLayer.cs:100
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
Definition: SPPLayer.cs:206
override int ExactNumBottomBlobs
Returns the exact number of required bottom (input) Blobs: input.
Definition: SPPLayer.cs:151
virtual LayerParameter getPoolingParam(int nPyramidLevel, int nBottomH, int nBottomW, SPPParameter spp_param)
Calculates the kernel and stride dimensions for the pooling layer, returns a correctly configured Lay...
Definition: SPPLayer.cs:172
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the error gradient w.r.t the inputs.
Definition: SPPLayer.cs:375
The SplitLayer creates a 'split' path in the network by copying the bottom blob into multiple top blo...
Definition: SplitLayer.cs:17
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Definition: SplitLayer.cs:69
uint? stride_h
The stride height (2D only)
uint? stride_w
The stride width (2D only)
uint? pad_h
The padding height (2D only)
uint? kernel_h
The kernel height (2D only)
uint? kernel_w
The kernel width (2D only)
uint? pad_w
The padding width (2D only)
Specifies the base parameter for all layers.
LayerParameter()
Constructor for the parameter.
SPPParameter spp_param
Returns the parameter set when initialized with LayerType.SPP
PoolingParameter pooling_param
Returns the parameter set when initialized with LayerType.POOLING
LayerType
Specifies the layer type.
PoolingMethod pool
Specifies the pooling method.
The SPPParameter specifies the parameters for the SPPLayer.
Definition: SPPParameter.cs:21
uint pyramid_height
Specifies the pyramid height.
Definition: SPPParameter.cs:46
PoolingParameter.PoolingMethod pool
Specifies the pooling method to use.
Definition: SPPParameter.cs:36
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.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