MCPcopy Create free account
hub / github.com/BVLC/caffe / Backward_cpu

Method Backward_cpu

src/caffe/layers/batch_norm_layer.cpp:169–242  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

167
168template <typename Dtype>
169void BatchNormLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
170 const vector<bool>& propagate_down,
171 const vector<Blob<Dtype>*>& bottom) {
172 const Dtype* top_diff;
173 if (bottom[0] != top[0]) {
174 top_diff = top[0]->cpu_diff();
175 } else {
176 caffe_copy(x_norm_.count(), top[0]->cpu_diff(), x_norm_.mutable_cpu_diff());
177 top_diff = x_norm_.cpu_diff();
178 }
179 Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
180 if (use_global_stats_) {
181 caffe_div(temp_.count(), top_diff, temp_.cpu_data(), bottom_diff);
182 return;
183 }
184 const Dtype* top_data = x_norm_.cpu_data();
185 int num = bottom[0]->shape()[0];
186 int spatial_dim = bottom[0]->count()/(bottom[0]->shape(0)*channels_);
187 // if Y = (X-mean(X))/(sqrt(var(X)+eps)), then
188 //
189 // dE(Y)/dX =
190 // (dE/dY - mean(dE/dY) - mean(dE/dY \cdot Y) \cdot Y)
191 // ./ sqrt(var(X) + eps)
192 //
193 // where \cdot and ./ are hadamard product and elementwise division,
194 // respectively, dE/dY is the top diff, and mean/var/sum are all computed
195 // along all dimensions except the channels dimension. In the above
196 // equation, the operations allow for expansion (i.e. broadcast) along all
197 // dimensions except the channels dimension where required.
198
199 // sum(dE/dY \cdot Y)
200 caffe_mul(temp_.count(), top_data, top_diff, bottom_diff);
201 caffe_cpu_gemv<Dtype>(CblasNoTrans, channels_ * num, spatial_dim, 1.,
202 bottom_diff, spatial_sum_multiplier_.cpu_data(), 0.,
203 num_by_chans_.mutable_cpu_data());
204 caffe_cpu_gemv<Dtype>(CblasTrans, num, channels_, 1.,
205 num_by_chans_.cpu_data(), batch_sum_multiplier_.cpu_data(), 0.,
206 mean_.mutable_cpu_data());
207
208 // reshape (broadcast) the above
209 caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, num, channels_, 1, 1,
210 batch_sum_multiplier_.cpu_data(), mean_.cpu_data(), 0.,
211 num_by_chans_.mutable_cpu_data());
212 caffe_cpu_gemm<Dtype>(CblasNoTrans, CblasNoTrans, channels_ * num,
213 spatial_dim, 1, 1., num_by_chans_.cpu_data(),
214 spatial_sum_multiplier_.cpu_data(), 0., bottom_diff);
215
216 // sum(dE/dY \cdot Y) \cdot Y
217 caffe_mul(temp_.count(), top_data, bottom_diff, bottom_diff);
218
219 // sum(dE/dY)-sum(dE/dY \cdot Y) \cdot Y
220 caffe_cpu_gemv<Dtype>(CblasNoTrans, channels_ * num, spatial_dim, 1.,
221 top_diff, spatial_sum_multiplier_.cpu_data(), 0.,
222 num_by_chans_.mutable_cpu_data());
223 caffe_cpu_gemv<Dtype>(CblasTrans, num, channels_, 1.,
224 num_by_chans_.cpu_data(), batch_sum_multiplier_.cpu_data(), 0.,
225 mean_.mutable_cpu_data());
226 // reshape (broadcast) the above to make

Callers

nothing calls this directly

Calls 7

caffe_copyFunction · 0.85
cpu_diffMethod · 0.80
countMethod · 0.80
mutable_cpu_diffMethod · 0.80
shapeMethod · 0.80
cpu_dataMethod · 0.45
mutable_cpu_dataMethod · 0.45

Tested by

no test coverage detected