| 90 | |
| 91 | template <typename Dtype> |
| 92 | void PReLULayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, |
| 93 | const vector<bool>& propagate_down, |
| 94 | const vector<Blob<Dtype>*>& bottom) { |
| 95 | const Dtype* bottom_data = bottom[0]->cpu_data(); |
| 96 | const Dtype* slope_data = this->blobs_[0]->cpu_data(); |
| 97 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 98 | const int count = bottom[0]->count(); |
| 99 | const int dim = bottom[0]->count(2); |
| 100 | const int channels = bottom[0]->channels(); |
| 101 | |
| 102 | // For in-place computation |
| 103 | if (top[0] == bottom[0]) { |
| 104 | bottom_data = bottom_memory_.cpu_data(); |
| 105 | } |
| 106 | |
| 107 | // if channel_shared, channel index in the following computation becomes |
| 108 | // always zero. |
| 109 | const int div_factor = channel_shared_ ? channels : 1; |
| 110 | |
| 111 | // Propagte to param |
| 112 | // Since to write bottom diff will affect top diff if top and bottom blobs |
| 113 | // are identical (in-place computaion), we first compute param backward to |
| 114 | // keep top_diff unchanged. |
| 115 | if (this->param_propagate_down_[0]) { |
| 116 | Dtype* slope_diff = this->blobs_[0]->mutable_cpu_diff(); |
| 117 | for (int i = 0; i < count; ++i) { |
| 118 | int c = (i / dim) % channels / div_factor; |
| 119 | slope_diff[c] += top_diff[i] * bottom_data[i] * (bottom_data[i] <= 0); |
| 120 | } |
| 121 | } |
| 122 | // Propagate to bottom |
| 123 | if (propagate_down[0]) { |
| 124 | Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); |
| 125 | for (int i = 0; i < count; ++i) { |
| 126 | int c = (i / dim) % channels / div_factor; |
| 127 | bottom_diff[i] = top_diff[i] * ((bottom_data[i] > 0) |
| 128 | + slope_data[c] * (bottom_data[i] <= 0)); |
| 129 | } |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | |
| 134 | #ifdef CPU_ONLY |
nothing calls this directly
no test coverage detected