| 84 | |
| 85 | template <typename Dtype> |
| 86 | void EmbedLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top, |
| 87 | const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom) { |
| 88 | CHECK(!propagate_down[0]) << "Can't backpropagate to EmbedLayer input."; |
| 89 | if (this->param_propagate_down_[0]) { |
| 90 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 91 | const Dtype* bottom_data = bottom[0]->cpu_data(); |
| 92 | // Gradient with respect to weight |
| 93 | Dtype* weight_diff = this->blobs_[0]->mutable_cpu_diff(); |
| 94 | int index; |
| 95 | for (int n = 0; n < M_; ++n) { |
| 96 | index = static_cast<int>(bottom_data[n]); |
| 97 | DCHECK_GE(index, 0); |
| 98 | DCHECK_LT(index, K_); |
| 99 | DCHECK_EQ(static_cast<Dtype>(index), bottom_data[n]) |
| 100 | << "non-integer input"; |
| 101 | caffe_axpy(N_, Dtype(1), top_diff + n * N_, weight_diff + index * N_); |
| 102 | } |
| 103 | } |
| 104 | if (bias_term_ && this->param_propagate_down_[1]) { |
| 105 | const Dtype* top_diff = top[0]->cpu_diff(); |
| 106 | Dtype* bias_diff = this->blobs_[1]->mutable_cpu_diff(); |
| 107 | caffe_cpu_gemv<Dtype>(CblasTrans, M_, N_, Dtype(1), top_diff, |
| 108 | bias_multiplier_.cpu_data(), Dtype(1), bias_diff); |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | #ifdef CPU_ONLY |
| 113 | STUB_GPU(EmbedLayer); |
nothing calls this directly
no test coverage detected