1+ #include < vector>
2+
3+ #include " caffe/layers/conv_depthwise_layer.hpp"
4+
5+ namespace caffe {
6+
7+ template <typename Dtype>
8+ void ConvolutionDepthwiseLayer<Dtype>::compute_output_shape() {
9+ /* Blob<int> kernel_shape_, stride_, pad_, ...,
10+ num_spatial_axes_, ... all declared in base_conv_layer.hpp */
11+ const int * kernel_shape_data = this ->kernel_shape_ .cpu_data ();
12+ const int * stride_data = this ->stride_ .cpu_data ();
13+ const int * pad_data = this ->pad_ .cpu_data ();
14+ const int pad_type = this ->pad_type_ ; // CUSTOMIZATION
15+ const int pad_l = this ->pad_l_ ; // CUSTOMIZATION
16+ const int pad_r = this ->pad_r_ ; // CUSTOMIZATION
17+ const int pad_t = this ->pad_t_ ; // CUSTOMIZATION
18+ const int pad_b = this ->pad_b_ ; // CUSTOMIZATION
19+ const int * dilation_data = this ->dilation_ .cpu_data ();
20+ this ->output_shape_ .clear ();
21+ for (int i = 0 ; i < this ->num_spatial_axes_ ; ++i) {
22+ // i + 1 to skip channel axis
23+ const int input_dim = this ->input_shape (i + 1 );
24+ const int kernel_extent = dilation_data[i] * (kernel_shape_data[i] - 1 ) + 1 ;
25+ int output_dim;
26+ // <--CUSTOMIZATION
27+ if (pad_l!=0 || pad_r!=0 || pad_t !=0 || pad_b!=0 ){ // only support 2D
28+ if (i==0 ) {
29+ output_dim = (input_dim + pad_t + pad_b - kernel_extent) / stride_data[i] + 1 ;
30+ }
31+ if (i==1 ) {
32+ output_dim = (input_dim + pad_l + pad_r - kernel_extent) / stride_data[i] + 1 ;
33+ }
34+ }
35+ else {
36+ switch (pad_type) {
37+ case 0 :
38+ output_dim = (input_dim + 2 * pad_data[i] - kernel_extent) / stride_data[i] + 1 ;
39+ break ;
40+ case 1 :
41+ output_dim = ceil (float (input_dim) / float (stride_data[i]));
42+ break ;
43+ default :
44+ LOG (FATAL)<< " Unknown padding type." ;
45+ break ;
46+ }
47+ // CUSTOMIZATION-->
48+ }
49+ this ->output_shape_ .push_back (output_dim);
50+ }
51+ }
52+
53+ template <typename Dtype>
54+ void ConvolutionDepthwiseLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
55+ const vector<Blob<Dtype>*>& top) {
56+ const Dtype* weight = this ->blobs_ [0 ]->cpu_data ();
57+ for (int i = 0 ; i < bottom.size (); ++i) {
58+ const Dtype* bottom_data = bottom[i]->cpu_data ();
59+ Dtype* top_data = top[i]->mutable_cpu_data ();
60+ for (int n = 0 ; n < this ->num_ ; ++n) { // num_ seems to be 'batch size'
61+ this ->forward_cpu_gemm (bottom_data + n * this ->bottom_dim_ , weight,
62+ top_data + n * this ->top_dim_ );
63+ if (this ->bias_term_ ) {
64+ const Dtype* bias = this ->blobs_ [1 ]->cpu_data ();
65+ this ->forward_cpu_bias (top_data + n * this ->top_dim_ , bias);
66+ }
67+ }
68+ }
69+ }
70+
71+ template <typename Dtype>
72+ void ConvolutionDepthwiseLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
73+ const vector<bool >& propagate_down, const vector<Blob<Dtype>*>& bottom) {
74+ const Dtype* weight = this ->blobs_ [0 ]->cpu_data ();
75+ Dtype* weight_diff = this ->blobs_ [0 ]->mutable_cpu_diff ();
76+ for (int i = 0 ; i < top.size (); ++i) {
77+ const Dtype* top_diff = top[i]->cpu_diff (); // the gradient dLoss/dY
78+ const Dtype* bottom_data = bottom[i]->cpu_data ();
79+ Dtype* bottom_diff = bottom[i]->mutable_cpu_diff ();
80+ // Bias gradient, if necessary.
81+ if (this ->bias_term_ && this ->param_propagate_down_ [1 ]) {
82+ Dtype* bias_diff = this ->blobs_ [1 ]->mutable_cpu_diff ();
83+ for (int n = 0 ; n < this ->num_ ; ++n) {
84+ this ->backward_cpu_bias (bias_diff, top_diff + n * this ->top_dim_ );
85+ }
86+ }
87+ if (this ->param_propagate_down_ [0 ] || propagate_down[i]) {
88+ for (int n = 0 ; n < this ->num_ ; ++n) {
89+ // gradient w.r.t. weight. Note that we will accumulate diffs. // dLoss/dW = dLoss/dY * dY/dW
90+ if (this ->param_propagate_down_ [0 ]) {
91+ this ->weight_cpu_gemm (bottom_data + n * this ->bottom_dim_ ,
92+ top_diff + n * this ->top_dim_ , weight_diff);
93+ }
94+ // gradient w.r.t. bottom data, if necessary.
95+ if (propagate_down[i]) {
96+ this ->backward_cpu_gemm (top_diff + n * this ->top_dim_ , weight,
97+ bottom_diff + n * this ->bottom_dim_ );
98+ }
99+ }
100+ }
101+ }
102+ }
103+
104+ #ifdef CPU_ONLY
105+ STUB_GPU (ConvolutionDepthwiseLayer);
106+ #endif
107+
108+ INSTANTIATE_CLASS (ConvolutionDepthwiseLayer);
109+ REGISTER_LAYER_CLASS (ConvolutionDepthwise);
110+
111+ } // namespace caffe
0 commit comments