1 // Copyright 2013 Yangqing Jia
3 #include "caffe/layer.hpp"
4 #include "caffe/vision_layers.hpp"
5 #include "caffe/util/math_functions.hpp"
13 template <typename Dtype>
14 void MultinomialLogisticLossLayer<Dtype>::SetUp(
15 const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
16 CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
17 CHECK_EQ(top->size(), 0) << "Loss Layer takes no as output.";
18 CHECK_EQ(bottom[0]->num(), bottom[1]->num())
19 << "The data and label should have the same number.";
20 CHECK_EQ(bottom[1]->channels(), 1);
21 CHECK_EQ(bottom[1]->height(), 1);
22 CHECK_EQ(bottom[1]->width(), 1);
26 template <typename Dtype>
27 Dtype MultinomialLogisticLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
28 const bool propagate_down,
29 vector<Blob<Dtype>*>* bottom) {
30 const Dtype* bottom_data = (*bottom)[0]->cpu_data();
31 const Dtype* bottom_label = (*bottom)[1]->cpu_data();
32 Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
33 int num = (*bottom)[0]->num();
34 int dim = (*bottom)[0]->count() / (*bottom)[0]->num();
35 memset(bottom_diff, 0, sizeof(Dtype) * (*bottom)[0]->count());
37 const Dtype kLOG_THRESHOLD = 1e-8;
38 for (int i = 0; i < num; ++i) {
39 int label = static_cast<int>(bottom_label[i]);
40 Dtype prob = max(bottom_data[i * dim + label], kLOG_THRESHOLD);
42 bottom_diff[i * dim + label] = - 1. / prob / num;
47 // TODO: implement the GPU version for multinomial loss
49 template <typename Dtype>
50 void EuclideanLossLayer<Dtype>::SetUp(
51 const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
52 CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
53 CHECK_EQ(top->size(), 0) << "Loss Layer takes no as output.";
54 CHECK_EQ(bottom[0]->num(), bottom[1]->num())
55 << "The data and label should have the same number.";
56 CHECK_EQ(bottom[0]->channels(), bottom[1]->channels());
57 CHECK_EQ(bottom[0]->height(), bottom[1]->height());
58 CHECK_EQ(bottom[0]->width(), bottom[1]->width());
59 difference_.Reshape(bottom[0]->num(), bottom[0]->channels(),
60 bottom[0]->height(), bottom[0]->width());
63 template <typename Dtype>
64 Dtype EuclideanLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
65 const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
66 int count = (*bottom)[0]->count();
67 int num = (*bottom)[0]->num();
68 caffe_sub(count, (*bottom)[0]->cpu_data(), (*bottom)[1]->cpu_data(),
69 difference_.mutable_cpu_data());
70 Dtype loss = caffe_cpu_dot(
71 count, difference_.cpu_data(), difference_.cpu_data()) / num / Dtype(2);
72 // Compute the gradient
73 caffe_axpby(count, Dtype(1) / num, difference_.cpu_data(), Dtype(0),
74 (*bottom)[0]->mutable_cpu_diff());
78 INSTANTIATE_CLASS(MultinomialLogisticLossLayer);
79 INSTANTIATE_CLASS(EuclideanLossLayer);