0c09a5dbe29f79d4d26cd5cbba0b2e939ff225a7
[platform/upstream/caffeonacl.git] / src / caffe / layers / loss_layer.cu
1 // Copyright 2013 Yangqing Jia
2
3 #include "caffe/layer.hpp"
4 #include "caffe/vision_layers.hpp"
5 #include "caffe/util/math_functions.hpp"
6 #include <algorithm>
7 #include <cmath>
8
9 using std::max;
10
11 namespace caffe {
12
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);
23 };
24
25
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());
36   Dtype loss = 0;
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);
41     loss -= log(prob);
42     bottom_diff[i * dim + label] = - 1. / prob / num;
43   }
44   return loss / num;
45 }
46
47 // TODO: implement the GPU version for multinomial loss
48
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());
61 }
62
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());
75   return loss;
76 }
77
78 INSTANTIATE_CLASS(MultinomialLogisticLossLayer);
79 INSTANTIATE_CLASS(EuclideanLossLayer);
80
81
82 }  // namespace caffe