1ea0626c377d2f8495e4d555914626718a2dea3d
[jacinto-ai/caffe-jacinto.git] / src / caffe / layers / loss_layer.cu
1 // Copyright 2013 Yangqing Jia
2 #include <algorithm>
3 #include <cmath>
4 #include <cfloat>
6 #include "caffe/layer.hpp"
7 #include "caffe/vision_layers.hpp"
8 #include "caffe/util/math_functions.hpp"
10 using std::max;
12 namespace caffe {
14 template <typename Dtype>
15 void MultinomialLogisticLossLayer<Dtype>::SetUp(
16     const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
17   CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
18   CHECK_EQ(top->size(), 0) << "Loss Layer takes no as output.";
19   CHECK_EQ(bottom[0]->num(), bottom[1]->num())
20       << "The data and label should have the same number.";
21   CHECK_EQ(bottom[1]->channels(), 1);
22   CHECK_EQ(bottom[1]->height(), 1);
23   CHECK_EQ(bottom[1]->width(), 1);
24 };
27 template <typename Dtype>
28 Dtype MultinomialLogisticLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
29     const bool propagate_down,
30     vector<Blob<Dtype>*>* bottom) {
31   const Dtype* bottom_data = (*bottom)[0]->cpu_data();
32   const Dtype* bottom_label = (*bottom)[1]->cpu_data();
33   Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
34   int num = (*bottom)[0]->num();
35   int dim = (*bottom)[0]->count() / (*bottom)[0]->num();
36   memset(bottom_diff, 0, sizeof(Dtype) * (*bottom)[0]->count());
37   Dtype loss = 0;
38   const Dtype kLOG_THRESHOLD = 1e-8;
39   for (int i = 0; i < num; ++i) {
40     int label = static_cast<int>(bottom_label[i]);
41     Dtype prob = max(bottom_data[i * dim + label], kLOG_THRESHOLD);
42     loss -= log(prob);
43     bottom_diff[i * dim + label] = - 1. / prob / num;
44   }
45   return loss / num;
46 }
48 // TODO: implement the GPU version for multinomial loss
50 template <typename Dtype>
51 void EuclideanLossLayer<Dtype>::SetUp(
52   const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
53   CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
54   CHECK_EQ(top->size(), 0) << "Loss Layer takes no as output.";
55   CHECK_EQ(bottom[0]->num(), bottom[1]->num())
56       << "The data and label should have the same number.";
57   CHECK_EQ(bottom[0]->channels(), bottom[1]->channels());
58   CHECK_EQ(bottom[0]->height(), bottom[1]->height());
59   CHECK_EQ(bottom[0]->width(), bottom[1]->width());
60   difference_.Reshape(bottom[0]->num(), bottom[0]->channels(),
61       bottom[0]->height(), bottom[0]->width());
62 }
64 template <typename Dtype>
65 Dtype EuclideanLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
66     const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
67   int count = (*bottom)[0]->count();
68   int num = (*bottom)[0]->num();
69   caffe_sub(count, (*bottom)[0]->cpu_data(), (*bottom)[1]->cpu_data(),
70       difference_.mutable_cpu_data());
71   Dtype loss = caffe_cpu_dot(
72       count, difference_.cpu_data(), difference_.cpu_data()) / num / Dtype(2);
73   // Compute the gradient
74   caffe_axpby(count, Dtype(1) / num, difference_.cpu_data(), Dtype(0),
75       (*bottom)[0]->mutable_cpu_diff());
76   return loss;
77 }
79 template <typename Dtype>
80 void AccuracyLayer<Dtype>::SetUp(
81   const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
82   CHECK_EQ(bottom.size(), 2) << "Accuracy Layer takes two blobs as input.";
83   CHECK_EQ(top->size(), 1) << "Accuracy Layer takes 1 output.";
84   CHECK_EQ(bottom[0]->num(), bottom[1]->num())
85       << "The data and label should have the same number.";
86   CHECK_EQ(bottom[1]->channels(), 1);
87   CHECK_EQ(bottom[1]->height(), 1);
88   CHECK_EQ(bottom[1]->width(), 1);
89   (*top)[0]->Reshape(1, 1, 1, 1);
90 }
92 template <typename Dtype>
93 void AccuracyLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
94     vector<Blob<Dtype>*>* top) {
95   Dtype accuracy = 0;
96   const Dtype* bottom_data = bottom[0]->cpu_data();
97   const Dtype* bottom_label = bottom[1]->cpu_data();
98   int num = bottom[0]->num();
99   int dim = bottom[0]->count() / bottom[0]->num();
100   for (int i = 0; i < num; ++i) {
101     Dtype maxval = -FLT_MAX;
102     int max_id = 0;
103     for (int j = 0; j < dim; ++j) {
104       if (bottom_data[i * dim + j] > maxval) {
105         maxval = bottom_data[i * dim + j];
106         max_id = j;
107       }
108     }
109     if (max_id == (int)bottom_label[i]) {
110       ++accuracy;
111     }
112   }
113   accuracy /= num;
114   // LOG(INFO) << "Accuracy: " << accuracy;
115   (*top)[0]->mutable_cpu_data()[0] = accuracy;
118 INSTANTIATE_CLASS(MultinomialLogisticLossLayer);
119 INSTANTIATE_CLASS(EuclideanLossLayer);
120 INSTANTIATE_CLASS(AccuracyLayer);
122 }  // namespace caffe