2using System.Collections.Generic;
41 int m_nNumSpatialAxes;
47 bool m_bForceNDIm2Col;
61 m_blobKernelShape =
new Blob<T>(cuda, log);
62 m_blobStride =
new Blob<T>(cuda, log);
63 m_blobPad =
new Blob<T>(cuda, log);
64 m_blobDilation =
new Blob<T>(cuda, log);
70 m_blobKernelShape.Dispose();
102 int nInputNumDims = colBottom[0].shape().
Count;
103 m_nChannelAxis = colBottom[0].CanonicalAxisIndex(p.
axis);
104 int nFirstSpatialDim = m_nChannelAxis + 1;
105 m_nNumSpatialAxes = nInputNumDims - nFirstSpatialDim;
107 m_log.
CHECK_GE(m_nNumSpatialAxes, 1,
"The spatial axis count must be >= 1.");
109 List<int> rgDimBlobShape =
new List<int>() { m_nNumSpatialAxes };
112 m_blobKernelShape.Reshape(rgDimBlobShape);
114 T[] rgKernelShape = m_blobKernelShape.mutable_cpu_data;
118 m_log.
CHECK_EQ(m_nNumSpatialAxes, 2,
"kernel_h & kernel_w can only be used for 2D convolution.");
120 rgKernelShape[0] = (T)Convert.ChangeType(p.
kernel_h.Value, typeof(T));
121 rgKernelShape[1] = (T)Convert.ChangeType(p.
kernel_w.Value, typeof(T));
126 m_log.
CHECK(nNumKernelDims == 1 || nNumKernelDims == m_nNumSpatialAxes,
"kernel_size must be specified once, or once per spatial dimension (kernel_size specified " + nNumKernelDims.ToString() +
" times; " + m_nNumSpatialAxes.ToString() +
" spatial dims);");
128 for (
int i = 0; i < m_nNumSpatialAxes; i++)
130 uint nKernel = p.
kernel_size[(nNumKernelDims == 1) ? 0 : i];
131 rgKernelShape[i] = (T)Convert.ChangeType(nKernel, typeof(T));
135 for (
int i = 0; i < m_nNumSpatialAxes; i++)
137 int nVal = (int)Convert.ChangeType(rgKernelShape[i], typeof(
int));
138 m_log.
CHECK_GT(nVal, 0,
"Filter dimensions must be nonzero.");
141 m_blobKernelShape.mutable_cpu_data = rgKernelShape;
145 m_blobStride.
Reshape(rgDimBlobShape);
151 m_log.
CHECK_EQ(m_nNumSpatialAxes, 2,
"stride_h & stride_w can only be used for 2D convolution.");
152 m_log.
CHECK_EQ(0, p.
stride.Count,
"Either stride or stride_h/w should be specified; not both.");
153 rgStrideData[0] = (T)Convert.ChangeType(p.
stride_h.Value, typeof(T));
154 rgStrideData[1] = (T)Convert.ChangeType(p.
stride_w.Value, typeof(T));
158 int nNumStrideDims = p.
stride.Count;
159 m_log.
CHECK(nNumStrideDims == 0 || nNumStrideDims == 1 || nNumStrideDims == m_nNumSpatialAxes,
"stride must be specified once, or once per spatial dimension (stride specified " + nNumStrideDims.ToString() +
" times; " + m_nNumSpatialAxes.ToString() +
" spatial dims);");
161 uint nDefaultStride = 1;
162 for (
int i = 0; i < m_nNumSpatialAxes; i++)
164 uint nStride = (nNumStrideDims == 0) ? nDefaultStride :
165 p.
stride[(nNumStrideDims == 1) ? 0 : i];
167 rgStrideData[i] = (T)Convert.ChangeType(nStride, typeof(T));
175 m_blobPad.
Reshape(rgDimBlobShape);
181 m_log.
CHECK_EQ(m_nNumSpatialAxes, 2,
"pad_h & pad_w can only be used for 2D convolution.");
182 m_log.
CHECK_EQ(0, p.
pad.Count,
"Either pad or pad_h/w should be specified; not both.");
183 rgPadData[0] = (T)Convert.ChangeType(p.
pad_h.Value, typeof(T));
184 rgPadData[1] = (T)Convert.ChangeType(p.
pad_w.Value, typeof(T));
188 int nNumPadDims = p.
pad.Count;
189 m_log.
CHECK(nNumPadDims == 0 || nNumPadDims == 1 || nNumPadDims == m_nNumSpatialAxes,
"pad must be specified once, or once per spatial dimension (pad specified " + nNumPadDims.ToString() +
" times; " + m_nNumSpatialAxes.ToString() +
" spatial dims);");
191 uint nDefaultPad = 0;
192 for (
int i = 0; i < m_nNumSpatialAxes; i++)
194 uint nPad = (nNumPadDims == 0) ? nDefaultPad :
195 p.
pad[(nNumPadDims == 1) ? 0 : i];
197 rgPadData[i] = (T)Convert.ChangeType(nPad, typeof(T));
205 m_blobDilation.
Reshape(rgDimBlobShape);
209 int nNumDilationDims = p.
dilation.Count;
210 m_log.
CHECK(nNumDilationDims == 0 || nNumDilationDims == 1 || nNumDilationDims == m_nNumSpatialAxes,
"dilation must be specified once, or once per spatial dimension (dilation specified " + nNumDilationDims.ToString() +
" times; " + m_nNumSpatialAxes.ToString() +
" spatial dims);");
212 uint nDefaultDilation = 1;
213 for (
int i = 0; i < m_nNumSpatialAxes; i++)
215 uint nPad = (nNumDilationDims == 0) ? nDefaultDilation :
216 p.
dilation[(nNumDilationDims == 1) ? 0 : i];
218 rgDilationData[i] = (T)Convert.ChangeType(nPad, typeof(T));
231 List<int> rgTopShape =
Utility.Clone<
int>(colBottom[0].shape());
232 T[] rgKernelShapeData = m_blobKernelShape.update_cpu_data();
237 for (
int i = 0; i < m_nNumSpatialAxes; i++)
239 int nKernel =
val_at(rgKernelShapeData, i);
240 int nStride =
val_at(rgStrideData, i);
241 int nPad =
val_at(rgPadData, i);
242 int nDilation =
val_at(rgDilationData, i);
244 rgTopShape[m_nChannelAxis] *= nKernel;
245 int nInputDim = colBottom[0].shape()[m_nChannelAxis + i + 1];
246 int nKernelExtent = nDilation * (nKernel - 1) + 1;
247 int nOutputDim = (nInputDim + 2 * nPad - nKernelExtent) / nStride + 1;
248 rgTopShape[m_nChannelAxis + i + 1] = nOutputDim;
252 m_nNum = colBottom[0].count(0, m_nChannelAxis);
253 m_nBottomDim = colBottom[0].count(m_nChannelAxis);
254 m_nTopDim = colTop[0].count(m_nChannelAxis);
255 m_nChannels = colBottom[0].shape(m_nChannelAxis);
270 long hBottomData = colBottom[0].gpu_data;
271 long hTopData = colTop[0].mutable_gpu_data;
273 if (!m_bForceNDIm2Col && m_nNumSpatialAxes == 2)
275 Size szKernel =
size_at(m_blobKernelShape);
276 Size szStride =
size_at(m_blobStride);
277 Size szPad =
size_at(m_blobPad);
278 Size szDilation =
size_at(m_blobDilation);
280 for (
int n = 0; n < m_nNum; n++)
282 m_cuda.im2col(hBottomData,
285 colBottom[0].shape(m_nChannelAxis + 1),
286 colBottom[0].shape(m_nChannelAxis + 2),
287 szKernel.Height, szKernel.Width,
288 szPad.Height, szPad.Width,
289 szStride.Height, szStride.Width,
290 szDilation.Height, szDilation.Width,
297 int nNumKernels = m_nChannels * colTop[0].count(m_nChannelAxis + 1);
298 long hKernelShape = m_blobKernelShape.gpu_data;
299 long hStride = m_blobStride.
gpu_data;
301 long hDilation = m_blobDilation.
gpu_data;
303 for (
int n = 0; n < m_nNum; n++)
305 m_cuda.im2col_nd(hBottomData,
310 colBottom[0].gpu_shape,
332 long hTopDiff = colTop[0].gpu_diff;
333 long hBottomDiff = colBottom[0].mutable_gpu_diff;
335 if (!m_bForceNDIm2Col && m_nNumSpatialAxes == 2)
337 Size szKernel =
size_at(m_blobKernelShape);
338 Size szStride =
size_at(m_blobStride);
339 Size szPad =
size_at(m_blobPad);
340 Size szDilation =
size_at(m_blobDilation);
342 for (
int n = 0; n < m_nNumSpatialAxes; n++)
347 colBottom[0].shape()[m_nChannelAxis + 1],
348 colBottom[0].shape()[m_nChannelAxis + 2],
349 szKernel.Height, szKernel.Width,
350 szPad.Height, szPad.Width,
351 szStride.Height, szStride.Width,
352 szDilation.Height, szDilation.Width,
359 long hKernelShape = m_blobKernelShape.gpu_data;
360 long hStride = m_blobStride.
gpu_data;
362 long hDilation = m_blobDilation.
gpu_data;
364 for (
int n = 0; n < m_nNumSpatialAxes; n++)
366 m_cuda.col2im_nd(hTopDiff,
371 colBottom[0].gpu_shape,
The Log class provides general output in text form.
void CHECK(bool b, string str)
Test a flag for true.
void CHECK_EQ(double df1, double df2, string str)
Test whether one number is equal to another.
void CHECK_GT(double df1, double df2, string str)
Test whether one number is greater than another.
void CHECK_GE(double df1, double df2, string str)
Test whether one number is greater than or equal to another.
The Utility class provides general utility funtions.
The BlobCollection contains a list of Blobs.
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 Blob is the main holder of data that moves through the Layers of the Net.
T[] mutable_cpu_data
Get data from the GPU and bring it over to the host, or Set data from the Host and send it over to th...
void Reshape(int nNum, int nChannels, int nHeight, int nWidth, bool? bUseHalfSize=null)
DEPRECIATED; use
T[] update_cpu_data()
Update the CPU data by transferring the GPU data over to the Host.
virtual void Dispose(bool bDisposing)
Releases all resources used by the Blob (including both GPU and Host).
long gpu_data
Returns the data GPU handle used by the CudaDnn connection.
The CudaDnn object is the main interface to the Low-Level Cuda C++ DLL.
The Im2ColLayer is a helper layer for image operations that rearranges image regions into column vect...
override void backward(BlobCollection< T > colTop, List< bool > rgbPropagateDown, BlobCollection< T > colBottom)
Computes the error gradient w.r.t. the forwarded inputs.
override void LayerSetUp(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Setup the layer.
override void Reshape(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Reshape the bottom (input) and top (output) blobs.
Im2colLayer(CudaDnn< T > cuda, Log log, LayerParameter p)
The Im2col constructor.
override void dispose()
Releases all GPU and host resources used by the Layer.
override void forward(BlobCollection< T > colBottom, BlobCollection< T > colTop)
Forward computation.
override int ExactNumTopBlobs
Returns the exact number of required top (output) Blobs: im2col.
override int ExactNumBottomBlobs
Returns the exact number of required bottom (input) Blobs: input.
An interface for the units of computation which can be composed into a Net.
Log m_log
Specifies the Log for output.
LayerParameter m_param
Specifies the LayerParameter describing the Layer.
int val_at(T[] rg, int nIdx)
Returns the integer value at a given index in a generic array.
Size size_at(Blob< T > b)
Returns the Size of a given two element Blob, such as one that stores Blob size information.
CudaDnn< T > m_cuda
Specifies the CudaDnn connection to Cuda.
LayerParameter.LayerType m_type
Specifies the Layer type.
Specifies the parameters for the ConvolutionLayer. The default weight filler is set to the XavierFill...
bool force_nd_im2col
Whether to force use of the general ND convolution, even if a specific implementation for blobs of th...
int axis
The axis to interpret as 'channels' when performing convolution. Preceding dimensions are treated as ...
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,...
List< uint > dilation
Factor used to dilate the kernel, (implicitly) zero-filling the resulting holes. (Kernel dilation is ...
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.
ConvolutionParameter convolution_param
Returns the parameter set when initialized with LayerType.CONVOLUTION
LayerType type
Specifies the type of this LayerParameter.
LayerType
Specifies the layer type.
The MyCaffe.basecode contains all generic types used throughout MyCaffe.
The MyCaffe.common namespace contains common MyCaffe classes.
The MyCaffe.layers namespace contains all layers that have a solidified code base,...
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-...