| 41 | |
| 42 | template <typename Dtype> |
| 43 | void ConvolutionLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, |
| 44 | const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { |
| 45 | const Dtype* weight = this->blobs_[0]->cpu_data(); |
| 46 | Dtype* weight_diff = this->blobs_[0]->mutable_cpu_diff(); |
| 47 | for (int i = 0; i < top.size(); ++i) { |
| 48 | const Dtype* top_diff = top[i]->cpu_diff(); |
| 49 | const Dtype* bottom_data = bottom[i]->cpu_data(); |
| 50 | Dtype* bottom_diff = bottom[i]->mutable_cpu_diff(); |
| 51 | // Bias gradient, if necessary. |
| 52 | if (this->bias_term_ && this->param_propagate_down_[1]) { |
| 53 | Dtype* bias_diff = this->blobs_[1]->mutable_cpu_diff(); |
| 54 | for (int n = 0; n < this->num_; ++n) { |
| 55 | this->backward_cpu_bias(bias_diff, top_diff + n * this->top_dim_); |
| 56 | } |
| 57 | } |
| 58 | if (this->param_propagate_down_[0] || propagate_down[i]) { |
| 59 | for (int n = 0; n < this->num_; ++n) { |
| 60 | // gradient w.r.t. weight. Note that we will accumulate diffs. |
| 61 | if (this->param_propagate_down_[0]) { |
| 62 | this->weight_cpu_gemm(bottom_data + n * this->bottom_dim_, |
| 63 | top_diff + n * this->top_dim_, weight_diff); |
| 64 | } |
| 65 | // gradient w.r.t. bottom data, if necessary. |
| 66 | if (propagate_down[i]) { |
| 67 | this->backward_cpu_gemm(top_diff + n * this->top_dim_, weight, |
| 68 | bottom_diff + n * this->bottom_dim_); |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | } |
| 73 | } |
| 74 | |
| 75 | #ifdef CPU_ONLY |
| 76 | STUB_GPU(ConvolutionLayer); |
nothing calls this directly
no test coverage detected