MyCaffe  1.12.2.41
Deep learning software for Windows C# programmers.
UnPoolingLayer.cs
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Drawing;
6using MyCaffe.basecode;
7using MyCaffe.common;
8using MyCaffe.param;
9using MyCaffe.param.beta;
10
11namespace MyCaffe.layers.beta
12{
28 public class UnPoolingLayer<T> : Layer<T>
29 {
30 int m_nKernelH;
31 int m_nKernelW;
32 int m_nStrideH;
33 int m_nStrideW;
34 int m_nPadH;
35 int m_nPadW;
36 int m_nChannels;
37 int m_nHeight;
38 int m_nWidth;
39 int m_nUnPooledHeight = -1;
40 int m_nUnPooledWidth = -1;
41 bool m_bGlobalPooling;
42
72 : base(cuda, log, p)
73 {
75 }
76
77
79 protected override void dispose()
80 {
81 base.dispose();
82 }
83
87 public override int MinBottomBlobs
88 {
89 get { return 1; }
90 }
91
95 public override int MaxBottomBlobs
96 {
97 get { return (m_param.unpooling_param.pool == PoolingParameter.PoolingMethod.MAX) ? 2 : 1; }
98 }
99
103 public override int ExactNumTopBlobs
104 {
105 get { return 1; }
106 }
107
113 public override void LayerSetUp(BlobCollection<T> colBottom, BlobCollection<T> colTop)
114 {
116
117 if (p.global_pooling)
118 {
119 m_log.CHECK(!(p.kernel_size.Count > 0 || p.kernel_h.HasValue || p.kernel_w.HasValue), "With global pooling = true, Filter size cannot be specified.");
120 }
121 else
122 {
123 m_log.CHECK(!(p.kernel_size.Count > 0) != !(p.kernel_h.HasValue && p.kernel_w.HasValue), "Filter size is kernel_size OR kernel_h and kernel_w; not both.");
124 m_log.CHECK(p.kernel_size.Count > 0 || (p.kernel_h.HasValue && p.kernel_w.HasValue), "For non-square filters, both kernel_h and kernel_w are required.");
125 }
126
127 m_log.CHECK(((p.pad.Count > 0) && p.pad_h.HasValue && p.pad_w.HasValue) || (!p.pad_h.HasValue && !p.pad_w.HasValue), "Pad is pad or pad_h and pad_w are required.");
128 m_log.CHECK(((p.stride.Count > 0) && p.stride_h.HasValue && p.stride_w.HasValue) || (!p.stride_h.HasValue && !p.stride_w.HasValue), "Stride is stride or stride_h and stride_w are required.");
129 m_bGlobalPooling = p.global_pooling;
130
131
132 //---- Kernel Size ----
133
134 if (m_bGlobalPooling)
135 {
136 m_nKernelH = colBottom[0].height;
137 m_nKernelW = colBottom[0].width;
138 }
139 else
140 {
141 if (p.kernel_size.Count > 0)
142 {
143 m_nKernelH = (int)p.kernel_size[0];
144 m_nKernelW = (int)p.kernel_size[0];
145 }
146 else
147 {
148 m_nKernelH = (int)p.kernel_h.Value;
149 m_nKernelW = (int)p.kernel_w.Value;
150 }
151 }
152
153 m_log.CHECK_GT(m_nKernelH, 0, "Filter dimensions cannot be zero.");
154 m_log.CHECK_GT(m_nKernelW, 0, "Filter dimensions cannot be zero.");
155
156
157 //---- UnPooling Size Override ----
158
159 if (p.unpool_size.Count > 0)
160 {
161 m_nUnPooledHeight = (int)p.unpool_size[0];
162 m_nUnPooledWidth = (int)p.unpool_size[0];
163 }
164 else
165 {
166 m_nUnPooledHeight = (p.unpool_h.HasValue) ? (int)p.unpool_h.Value : -1;
167 m_nUnPooledWidth = (p.unpool_w.HasValue) ? (int)p.unpool_w.Value : -1;
168 }
169
170
171 //---- Pad ----
172
173 if (p.pad.Count > 0)
174 {
175 m_nPadH = (int)p.pad[0];
176 m_nPadW = (int)p.pad[0];
177 }
178 else
179 {
180 m_nPadH = (p.pad_h.HasValue) ? (int)p.pad_h.Value : 0;
181 m_nPadW = (p.pad_w.HasValue) ? (int)p.pad_w.Value : 0;
182 }
183
184
185 //---- Stride ----
186
187 if (p.stride.Count > 0)
188 {
189 m_nStrideH = (int)p.stride[0];
190 m_nStrideW = (int)p.stride[0];
191 }
192 else
193 {
194 m_nStrideH = (p.stride_h.HasValue) ? (int)p.stride_h.Value : 1;
195 m_nStrideW = (p.stride_w.HasValue) ? (int)p.stride_w.Value : 1;
196 }
197
198 if (m_bGlobalPooling)
199 m_log.CHECK(m_nPadH == 0 && m_nPadW == 0 && m_nStrideH == 1 && m_nStrideW == 1, "With global pooling = true, only pad = 0 and stride = 1 allowed.");
200
201 if (m_nPadH != 0 || m_nPadW != 0)
202 {
203 m_log.CHECK(m_param.unpooling_param.pool == PoolingParameter.PoolingMethod.MAX, "Padding implemented for MAX unpooling only.");
204 m_log.CHECK_LT(m_nPadH, m_nKernelH, "The pad_h must be <= kernel_h.");
205 m_log.CHECK_LT(m_nPadW, m_nKernelW, "The pad_w must be <= kernel_w.");
206 }
207 }
208
214 public override void Reshape(BlobCollection<T> colBottom, BlobCollection<T> colTop)
215 {
216 m_log.CHECK_EQ(4, colBottom[0].num_axes, "Input must have 4 axes, corresponding to (num, channels, height, width)");
217
218 m_nChannels = colBottom[0].channels;
219 m_nHeight = colBottom[0].height;
220 m_nWidth = colBottom[0].width;
221
222 if (m_bGlobalPooling)
223 {
224 m_nKernelH = colBottom[0].height;
225 m_nKernelW = colBottom[0].width;
226 }
227
228 // Given the original pooling calculation:
229 // (int)Math.Ceiling((double)((nOriginalHeight + 2 * m_nPadH - m_nKernelH) / (double)m_nStrideH)) + 1;
230 // we do not know whether or not the ceiling kicks in for at the unpooling
231 // stage, we do not know the original height. For this reason, the unpooled
232 // height will always be >= the original height.
233 // Using the sizing method from HyeonwooNoh at
234 // https://github.com/HyeonwooNoh/caffe/blob/master/src/caffe/layers/unpooling_layer.cpp
235 if (m_nUnPooledHeight < 0)
236 {
237 m_nUnPooledHeight = Math.Max((m_nHeight - 1) * m_nStrideH + m_nKernelH - 2 * m_nPadH,
238 m_nHeight * m_nStrideH - m_nPadH + 1);
239 }
240
241 if (m_nUnPooledWidth < 0)
242 {
243 m_nUnPooledWidth = Math.Max((m_nWidth - 1) * m_nStrideW + m_nKernelW - 2 * m_nPadW,
244 m_nWidth * m_nStrideW - m_nPadW + 1);
245 }
246
247 if (m_nUnPooledHeight <= 0)
248 {
249 m_nUnPooledHeight = 1;
250 m_log.WriteLine("WARNING: unpooling height was 0, setting to 1.");
251 }
252
253 if (m_nUnPooledWidth <= 0)
254 {
255 m_nUnPooledWidth = 1;
256 m_log.WriteLine("WARNING: unpooling width was 0, setting to 1.");
257 }
258
259 colTop[0].Reshape(colBottom[0].num, m_nChannels, m_nUnPooledHeight, m_nUnPooledWidth);
260 }
261
267 protected override void forward(BlobCollection<T> colBottom, BlobCollection<T> colTop)
268 {
269 int nCount = colBottom[0].count();
270 long hBottomData = colBottom[0].gpu_data;
271 long hTopData = colTop[0].mutable_gpu_data;
272 long hBottomMask = 0; // We'll get the mas from bottom[1] if its of size > 1
273
274 colTop[0].SetData(0);
275
277 {
279 if (colBottom.Count > 1)
280 hBottomMask = colBottom[1].gpu_data;
281 m_cuda.unpooling_fwd(POOLING_METHOD.MAX, nCount, hBottomData, colBottom[0].num, m_nChannels, m_nHeight, m_nWidth, m_nUnPooledHeight, m_nUnPooledWidth, m_nKernelH, m_nKernelW, m_nStrideH, m_nStrideW, m_nPadH, m_nPadW, hTopData, hBottomMask);
282 break;
283
285 m_cuda.unpooling_fwd(POOLING_METHOD.AVE, nCount, hBottomData, colBottom[0].num, m_nChannels, m_nHeight, m_nWidth, m_nUnPooledHeight, m_nUnPooledWidth, m_nKernelH, m_nKernelW, m_nStrideH, m_nStrideW, m_nPadH, m_nPadW, hTopData, 0);
286 break;
287
288 default:
289 m_log.FAIL("Unknown pooling method '" + m_param.unpooling_param.pool.ToString() + "'");
290 break;
291 }
292 }
293
300 protected override void backward(BlobCollection<T> colTop, List<bool> rgbPropagateDown, BlobCollection<T> colBottom)
301 {
302 if (!rgbPropagateDown[0])
303 return;
304
305 int nCount = colBottom[0].count();
306 long hTopDiff = colTop[0].gpu_diff;
307 long hBottomDiff = colBottom[0].mutable_gpu_diff;
308 long hBottomMask = 0; // We'll get the mas from bottom[1] if its of size > 1
309
310 colBottom[0].SetDiff(0);
311
313 {
315 if (colBottom.Count > 1)
316 hBottomMask = colBottom[1].gpu_data;
317 m_cuda.unpooling_bwd(POOLING_METHOD.MAX, nCount, hTopDiff, colTop[0].num, m_nChannels, m_nHeight, m_nWidth, m_nUnPooledHeight, m_nUnPooledWidth, m_nKernelH, m_nKernelW, m_nStrideH, m_nStrideW, m_nPadH, m_nPadW, hBottomDiff, hBottomMask);
318 break;
319
321 m_cuda.unpooling_bwd(POOLING_METHOD.AVE, nCount, hTopDiff, colTop[0].num, m_nChannels, m_nHeight, m_nWidth, m_nUnPooledHeight, m_nUnPooledWidth, m_nKernelH, m_nKernelW, m_nStrideH, m_nStrideW, m_nPadH, m_nPadW, hBottomDiff, 0);
322 break;
323
324 default:
325 m_log.FAIL("Unknown pooling method '" + m_param.unpooling_param.pool.ToString() + "'");
326 break;
327 }
328 }
329 }
330}
The Log class provides general output in text form.
Definition: Log.cs:13
void CHECK(bool b, string str)
Test a flag for true.
Definition: Log.cs:227
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 FAIL(string str)
Causes a failure which throws an exception with the desciptive text.
Definition: Log.cs:394
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
void CHECK_LT(double df1, double df2, string str)
Test whether one number is less than another.
Definition: Log.cs:275
The BlobCollection contains a list of Blobs.
void SetData(double df)
Set all blob data to the value specified.
void SetDiff(double df)
Set all blob diff to the value specified.
int Count
Returns the number of items in the collection.
void Reshape(int[] rgShape)
Reshapes all blobs in the collection to the given shape.
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
Definition: CudaDnn.cs:969
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
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
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Run the Backward computation using the Engine.CAFFE mode only.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer for use with both Engine.CAFFE and Engine.CUDNN modes.
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Run the Forward computation using the Engine.CAFFE mode only.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
override int MinBottomBlobs
Returns the minimum number of required bottom (input) Blobs: input
override void dispose()
Releases all GPU and host resources used by the Layer.
UnPoolingLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The UnPoolingLayer constructor.
override int? MaxBottomBlobs
Returns the maximum number of required bottom (input) Blobs: input, mask (only when using MAX)
override int ExactNumTopBlobs
Returns the required number of top (output) Blobs: unpool
uint? stride_h
The stride height (2D only)
List< uint > kernel_size
Kernel size is given as a single value for equal dimensions in all spatial dimensions,...
uint? stride_w
The stride width (2D only)
uint? pad_h
The padding height (2D only)
uint? kernel_h
The kernel height (2D only)
List< uint > stride
Stride is given as a single value for equal dimensions in all spatial dimensions, or once per spatial...
uint? kernel_w
The kernel width (2D only)
uint? pad_w
The padding width (2D only)
List< uint > pad
Pad is given as a single value for equal dimensions in all spatial dimensions, or once per spatial di...
Specifies the base parameter for all layers.
UnPoolingParameter unpooling_param
Returns the parameter set when initialized with LayerType.UNPOOLING
LayerType
Specifies the layer type.
Specifies the parameters for the PoolingLayer.
PoolingMethod
Defines the pooling method.
PoolingMethod pool
Specifies the pooling method.
bool global_pooling
Specifies whether or not to enable global pooling.
Specifies the parameters for the UnPoolingLayer.
List< uint > unpool_size
UnPool size is given as a single value for equal dimensions in all spatial dimensions,...
uint? unpool_h
The unpooling height override (2D only)
uint? unpool_w
The unpooling width override (2D only)
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
POOLING_METHOD
Specifies the pooling method to use when using the Caffe pooling (instead of the pooling from NVIDIA'...
Definition: CudaDnn.cs:353
The MyCaffe.layers.beta namespace contains all beta stage layers.
Definition: LayerFactory.cs:9
The MyCaffe.param.beta parameters are used by the MyCaffe.layer.beta layers.
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