1 #include "caffe2/operators/conv_op.h" 2 #include "caffe2/operators/conv_op_impl.h" 3 #include "caffe2/operators/conv_pool_op_base.h" 7 const char kConvDoc[] = R
"DOC( 8 The Conv2D operator computes a 2D convolution operation over an input blob $(X)$, with a filter blob $(filter)$ and a bias blob $(bias)$, and outputs a single output blob $(Y)$. Although there are several options for order, the convention is that the input $(X)$ is a blob of shape $(N,C_{in},H_{in},W_{in})$ and the output $(Y)$ is a blob of shape $(N,C_{out},H_{out},W_{out})$. Here, $N$ is the batch size, $C$ is the number of channels, $H$ is the spatial height, and $W$ is the spatial width. For example, if your input data was a batch of five, 100x120pixel RGB images, $X$ would have shape $(5,3,120,100)$. 10 The $filter$ input blob may contain multiple filters and has shape $(M, C_{in}, K_H, K_W)$. Here, $M$ is the number of individual filters contained in the blob, $C_{in}$ is the number of channels of each filter (by convention in 2D convolution it is the same as the number of channels in the input), $K_H$ is the spatial height of the kernel, and $K_W$ is the spatial width of the kernel. The $bias$ blob is a vector of length $M$, where there is one bias for each filter in the $filter$ blob. 12 Given the shape of the input blob and the filter blob, we can calculate the shape of the output blob as follows. The number of items in the batch $N$ will stay the same. The number of channels in the output will equal the number of kernels in the filter blob, so $C_{out} = M.$ With stride and pad defined below, the spatial height and width of the output ($H_{out}$ and $W_{out}$) are calculated as 14 $$H_{out} = \left \lfloor{\frac{H_{in} - K_H + 2*pad}{stride}+1}\right \rfloor$$ 17 $$W_{out} = \left \lfloor{\frac{W_{in} - K_W + 2*pad}{stride}+1}\right \rfloor$$ 22 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.h 23 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_op.cc 24 - https://github.com/pytorch/pytorch/blob/master/caffe2/operators/conv_pool_op_base.h 28 <summary> <b>Example</b> </summary> 34 workspace.ResetWorkspace() 36 op = core.CreateOperator( 38 ["X", "filter", "bias"], 45 // Create X: (N,C,H,W) 46 data = np.random.randn(1,1,8,8).astype(np.float32) 47 print("Data shape: ",data.shape) 49 // Create W: (M,C,Kh,Kw) 50 filters = np.random.randn(3,1,5,5).astype(np.float32) 51 print("Filter shape: ",filters.shape) 54 bias = np.array([1.,1.,1.]).astype(np.float32) 55 print("Bias shape: ",bias.shape) 57 // Put the inputs into the workspace 58 workspace.FeedBlob("X", data) 59 workspace.FeedBlob("filter", filters) 60 workspace.FeedBlob("bias", bias) 63 workspace.RunOperatorOnce(op) 64 print("Y:\n", workspace.FetchBlob("Y")) 72 Data shape: (1, 1, 8, 8) 73 Filter shape: (3, 1, 5, 5) 76 [[[[ 0.6406407 0.8620521 0.56461596] 77 [ -1.5042953 -0.79549205 -10.683343 ] 78 [ -0.5240259 3.4538248 -3.9564204 ]] 80 [[ 0.6876496 4.8328524 -1.9525816 ] 81 [ 1.2995434 -2.3895378 7.2670045 ] 82 [ 3.9929862 1.8126237 5.4699917 ]] 84 [[ 3.55949 4.7934155 0.76086235] 85 [ 3.9588015 -1.3251319 4.413117 ] 86 [ -1.5296054 -1.4924102 -3.2552304 ]]]] 95 std::function<void(OpSchema&)> ConvDocGenerator(const char* dim) {
96 return [=](OpSchema& schema) {
98 The convolution operator consumes an input vector, a {dim}filter blob 99 and a bias blob and computes the output. {conv_doc})DOC"; 100 c10::ReplaceAll(doc, "{dim}", dim);
101 c10::ReplaceAll(doc,
"{conv_doc}", kConvDoc);
106 "Input data blob, of shape $(N, C_{in}, H_{in}, W_{in})$, to be convolved with the kernels in the filter blob." 111 "The filter blob, of shape $(M, C_{in}, K_H, K_W)$, containing the filters to be convolved with the data." 116 "The bias blob, of length $M$, containing the biases for the convolution, one bias per filter." 121 "Output data blob, of shape $(N, C_{out}, H_{out}, W_{out})$, that contains the result of the convolution." 167 REGISTER_CPU_OPERATOR(
Conv, ConvOp<float, CPUContext>);
169 OPERATOR_SCHEMA(
Conv)
172 .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForConv)
174 ConvPoolOpBase<CPUContext>::CostInferenceForConv))
175 .FillUsing(ConvDocGenerator(
""))
176 .InheritOnnxSchema();
178 REGISTER_CPU_OPERATOR(Conv1D, ConvOp<float, CPUContext>);
180 OPERATOR_SCHEMA(Conv1D)
183 .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForConv)
184 .FillUsing(ConvDocGenerator(
"1D "))
185 .InheritOnnxSchema(
"Conv");
187 REGISTER_CPU_OPERATOR(Conv2D, ConvOp<float, CPUContext>);
189 OPERATOR_SCHEMA(Conv2D)
193 ConvPoolOpBase<CPUContext>::CostInferenceForConv))
194 .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForConv)
195 .FillUsing(ConvDocGenerator(
"2D "))
196 .InheritOnnxSchema(
"Conv");
198 REGISTER_CPU_OPERATOR(Conv3D, ConvOp<float, CPUContext>);
200 OPERATOR_SCHEMA(Conv3D)
204 ConvPoolOpBase<CPUContext>::CostInferenceForConv))
205 .TensorInferenceFunction(ConvPoolOpBase<CPUContext>::TensorInferenceForConv)
206 .FillUsing(ConvDocGenerator(
"3D "))
207 .InheritOnnxSchema(
"Conv");
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
std::function< struct Cost(const OperatorDef &, const vector< TensorShape > &)> CostInferenceFunctionType
Registers a function that takes in an OperatorDef and a series of input shapes and returns the total ...