| 88 | |
| 89 | template <typename Dtype> |
| 90 | void BiasLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, |
| 91 | const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { |
| 92 | if (propagate_down[0] && bottom[0] != top[0]) { |
| 93 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 94 | Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); |
| 95 | caffe_copy(bottom[0]->count(), top_diff, bottom_diff); |
| 96 | } |
| 97 | // in-place, we don't need to do anything with the data diff |
| 98 | const bool bias_param = (bottom.size() == 1); |
| 99 | if ((!bias_param && propagate_down[1]) || |
| 100 | (bias_param && this->param_propagate_down_[0])) { |
| 101 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 102 | Dtype* bias_diff = (bias_param ? this->blobs_[0].get() : bottom[1]) |
| 103 | ->mutable_cpu_diff(); |
| 104 | bool accum = bias_param; |
| 105 | for (int n = 0; n < outer_dim_; ++n) { |
| 106 | caffe_cpu_gemv(CblasNoTrans, bias_dim_, inner_dim_, Dtype(1), |
| 107 | top_diff, bias_multiplier_.cpu_data(), Dtype(accum), bias_diff); |
| 108 | top_diff += dim_; |
| 109 | accum = true; |
| 110 | } |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | #ifdef CPU_ONLY |
| 115 | STUB_GPU(BiasLayer); |
nothing calls this directly
no test coverage detected