| 178 | |
| 179 | template <typename Dtype> |
| 180 | void LRNLayer<Dtype>::CrossChannelBackward_cpu( |
| 181 | const vector<Blob<Dtype>*>& top, const vector<bool>& propagate_down, |
| 182 | const vector<Blob<Dtype>*>& bottom) { |
| 183 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 184 | const Dtype* top_data = top[0]->cpu_data(); |
| 185 | const Dtype* bottom_data = bottom[0]->cpu_data(); |
| 186 | const Dtype* scale_data = scale_.cpu_data(); |
| 187 | Dtype* bottom_diff = bottom[0]->mutable_cpu_diff(); |
| 188 | Blob<Dtype> padded_ratio(1, channels_ + size_ - 1, height_, width_); |
| 189 | Blob<Dtype> accum_ratio(1, 1, height_, width_); |
| 190 | Dtype* padded_ratio_data = padded_ratio.mutable_cpu_data(); |
| 191 | Dtype* accum_ratio_data = accum_ratio.mutable_cpu_data(); |
| 192 | // We hack a little bit by using the diff() to store an additional result |
| 193 | Dtype* accum_ratio_times_bottom = accum_ratio.mutable_cpu_diff(); |
| 194 | caffe_set(padded_ratio.count(), Dtype(0), padded_ratio_data); |
| 195 | Dtype cache_ratio_value = 2. * alpha_ * beta_ / size_; |
| 196 | |
| 197 | caffe_powx<Dtype>(scale_.count(), scale_data, -beta_, bottom_diff); |
| 198 | caffe_mul<Dtype>(scale_.count(), top_diff, bottom_diff, bottom_diff); |
| 199 | |
| 200 | // go through individual data |
| 201 | int inverse_pre_pad = size_ - (size_ + 1) / 2; |
| 202 | for (int n = 0; n < num_; ++n) { |
| 203 | int block_offset = scale_.offset(n); |
| 204 | // first, compute diff_i * y_i / s_i |
| 205 | caffe_mul<Dtype>(channels_ * height_ * width_, |
| 206 | top_diff + block_offset, top_data + block_offset, |
| 207 | padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad)); |
| 208 | caffe_div<Dtype>(channels_ * height_ * width_, |
| 209 | padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad), |
| 210 | scale_data + block_offset, |
| 211 | padded_ratio_data + padded_ratio.offset(0, inverse_pre_pad)); |
| 212 | // Now, compute the accumulated ratios and the bottom diff |
| 213 | caffe_set(accum_ratio.count(), Dtype(0), accum_ratio_data); |
| 214 | for (int c = 0; c < size_ - 1; ++c) { |
| 215 | caffe_axpy<Dtype>(height_ * width_, 1., |
| 216 | padded_ratio_data + padded_ratio.offset(0, c), accum_ratio_data); |
| 217 | } |
| 218 | for (int c = 0; c < channels_; ++c) { |
| 219 | caffe_axpy<Dtype>(height_ * width_, 1., |
| 220 | padded_ratio_data + padded_ratio.offset(0, c + size_ - 1), |
| 221 | accum_ratio_data); |
| 222 | // compute bottom diff |
| 223 | caffe_mul<Dtype>(height_ * width_, |
| 224 | bottom_data + top[0]->offset(n, c), |
| 225 | accum_ratio_data, accum_ratio_times_bottom); |
| 226 | caffe_axpy<Dtype>(height_ * width_, -cache_ratio_value, |
| 227 | accum_ratio_times_bottom, bottom_diff + top[0]->offset(n, c)); |
| 228 | caffe_axpy<Dtype>(height_ * width_, -1., |
| 229 | padded_ratio_data + padded_ratio.offset(0, c), accum_ratio_data); |
| 230 | } |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | template <typename Dtype> |
| 235 | void LRNLayer<Dtype>::WithinChannelBackward( |
nothing calls this directly
no test coverage detected