Unify L1 and L2 Hinge_Loss to follow convention
authorSergio <sguada@gmail.com>
Sat, 21 Jun 2014 01:37:34 +0000 (18:37 -0700)
committerSergio <sguada@gmail.com>
Sat, 21 Jun 2014 01:39:01 +0000 (18:39 -0700)
src/caffe/layers/hinge_loss_layer.cpp
src/caffe/layers/loss_layer.cpp

index 24329fb..f0f8521 100644 (file)
@@ -14,6 +14,7 @@ using std::max;
 
 namespace caffe {
 
+
 template <typename Dtype>
 Dtype HingeLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
     vector<Blob<Dtype>*>* top) {
@@ -33,7 +34,14 @@ Dtype HingeLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
       bottom_diff[i * dim + j] = max(Dtype(0), 1 + bottom_diff[i * dim + j]);
     }
   }
-  return caffe_cpu_asum(count, bottom_diff) / num;
+  switch (this->layer_param_.hinge_loss_param().hinge_norm()) {
+  case HingeLossParameter_Norm_L1:
+    return caffe_cpu_asum(count, bottom_diff) / num;
+  case HingeLossParameter_Norm_L2:
+    return caffe_cpu_dot(count, bottom_diff, bottom_diff) / num;
+  default:
+    LOG(FATAL) << "Unknown hinge_norm";
+  }
 }
 
 template <typename Dtype>
@@ -44,12 +52,22 @@ void HingeLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
   int num = (*bottom)[0]->num();
   int count = (*bottom)[0]->count();
   int dim = count / num;
-
-  caffe_cpu_sign(count, bottom_diff, bottom_diff);
+  
   for (int i = 0; i < num; ++i) {
     bottom_diff[i * dim + static_cast<int>(label[i])] *= -1;
   }
-  caffe_scal(count, Dtype(1. / num), bottom_diff);
+
+  switch (this->layer_param_.hinge_loss_param().hinge_norm()) {
+  case HingeLossParameter_Norm_L1:
+    caffe_cpu_sign(count, bottom_diff, bottom_diff);
+    caffe_scal(count, Dtype(C_ / num), bottom_diff);
+    break;
+  case HingeLossParameter_Norm_L2:
+    caffe_scal(count, Dtype(2 * C_ / num), bottom_diff);
+    break;
+  default:
+    LOG(FATAL) << "Unknown hinge_norm";
+  }  
 }
 
 INSTANTIATE_CLASS(HingeLossLayer);
index 33a221f..a8e63c4 100644 (file)
@@ -20,254 +20,8 @@ void LossLayer<Dtype>::SetUp(
   Layer<Dtype>::SetUp(bottom, top);
   CHECK_EQ(bottom[0]->num(), bottom[1]->num())
       << "The data and label should have the same number.";
-<<<<<<< HEAD
   FurtherSetUp(bottom, top);
 
-=======
-  CHECK_EQ(bottom[1]->channels(), 1);
-  CHECK_EQ(bottom[1]->height(), 1);
-  CHECK_EQ(bottom[1]->width(), 1);
-}
-
-template <typename Dtype>
-Dtype MultinomialLogisticLossLayer<Dtype>::Forward_cpu(
-    const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
-  const Dtype* bottom_data = bottom[0]->cpu_data();
-  const Dtype* bottom_label = bottom[1]->cpu_data();
-  int num = bottom[0]->num();
-  int dim = bottom[0]->count() / bottom[0]->num();
-  Dtype loss = 0;
-  for (int i = 0; i < num; ++i) {
-    int label = static_cast<int>(bottom_label[i]);
-    Dtype prob = max(bottom_data[i * dim + label], Dtype(kLOG_THRESHOLD));
-    loss -= log(prob);
-  }
-  return loss / num;
-}
-
-template <typename Dtype>
-void MultinomialLogisticLossLayer<Dtype>::Backward_cpu(
-    const vector<Blob<Dtype>*>& top, const bool propagate_down,
-    vector<Blob<Dtype>*>* bottom) {
-  const Dtype* bottom_data = (*bottom)[0]->cpu_data();
-  const Dtype* bottom_label = (*bottom)[1]->cpu_data();
-  Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
-  int num = (*bottom)[0]->num();
-  int dim = (*bottom)[0]->count() / (*bottom)[0]->num();
-  memset(bottom_diff, 0, sizeof(Dtype) * (*bottom)[0]->count());
-  for (int i = 0; i < num; ++i) {
-    int label = static_cast<int>(bottom_label[i]);
-    Dtype prob = max(bottom_data[i * dim + label], Dtype(kLOG_THRESHOLD));
-    bottom_diff[i * dim + label] = -1. / prob / num;
-  }
-}
-
-
-template <typename Dtype>
-void InfogainLossLayer<Dtype>::SetUp(
-    const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
-  CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
-  CHECK_EQ(top->size(), 0) << "Loss Layer takes no output.";
-  CHECK_EQ(bottom[0]->num(), bottom[1]->num())
-      << "The data and label should have the same number.";
-  CHECK_EQ(bottom[1]->channels(), 1);
-  CHECK_EQ(bottom[1]->height(), 1);
-  CHECK_EQ(bottom[1]->width(), 1);
-  BlobProto blob_proto;
-  ReadProtoFromBinaryFile(this->layer_param_.infogain_loss_param().source(),
-                          &blob_proto);
-  infogain_.FromProto(blob_proto);
-  CHECK_EQ(infogain_.num(), 1);
-  CHECK_EQ(infogain_.channels(), 1);
-  CHECK_EQ(infogain_.height(), infogain_.width());
-}
-
-
-template <typename Dtype>
-Dtype InfogainLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
-    vector<Blob<Dtype>*>* top) {
-  const Dtype* bottom_data = bottom[0]->cpu_data();
-  const Dtype* bottom_label = bottom[1]->cpu_data();
-  const Dtype* infogain_mat = infogain_.cpu_data();
-  int num = bottom[0]->num();
-  int dim = bottom[0]->count() / bottom[0]->num();
-  CHECK_EQ(infogain_.height(), dim);
-  Dtype loss = 0;
-  for (int i = 0; i < num; ++i) {
-    int label = static_cast<int>(bottom_label[i]);
-    for (int j = 0; j < dim; ++j) {
-      Dtype prob = max(bottom_data[i * dim + j], Dtype(kLOG_THRESHOLD));
-      loss -= infogain_mat[label * dim + j] * log(prob);
-    }
-  }
-  return loss / num;
-}
-
-template <typename Dtype>
-void InfogainLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
-    const bool propagate_down,
-    vector<Blob<Dtype>*>* bottom) {
-  const Dtype* bottom_data = (*bottom)[0]->cpu_data();
-  const Dtype* bottom_label = (*bottom)[1]->cpu_data();
-  const Dtype* infogain_mat = infogain_.cpu_data();
-  Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
-  int num = (*bottom)[0]->num();
-  int dim = (*bottom)[0]->count() / (*bottom)[0]->num();
-  CHECK_EQ(infogain_.height(), dim);
-  for (int i = 0; i < num; ++i) {
-    int label = static_cast<int>(bottom_label[i]);
-    for (int j = 0; j < dim; ++j) {
-      Dtype prob = max(bottom_data[i * dim + j], Dtype(kLOG_THRESHOLD));
-      bottom_diff[i * dim + j] = - infogain_mat[label * dim + j] / prob / num;
-    }
-  }
-}
-
-
-template <typename Dtype>
-void EuclideanLossLayer<Dtype>::SetUp(
-  const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
-  CHECK_EQ(bottom.size(), 2) << "Loss Layer takes two blobs as input.";
-  CHECK_EQ(top->size(), 0) << "Loss Layer takes no as output.";
-  CHECK_EQ(bottom[0]->num(), bottom[1]->num())
-      << "The data and label should have the same number.";
-  CHECK_EQ(bottom[0]->channels(), bottom[1]->channels());
-  CHECK_EQ(bottom[0]->height(), bottom[1]->height());
-  CHECK_EQ(bottom[0]->width(), bottom[1]->width());
-  difference_.Reshape(bottom[0]->num(), bottom[0]->channels(),
-      bottom[0]->height(), bottom[0]->width());
-}
-
-template <typename Dtype>
-Dtype EuclideanLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
-    vector<Blob<Dtype>*>* top) {
-  int count = bottom[0]->count();
-  int num = bottom[0]->num();
-  caffe_sub(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(),
-      difference_.mutable_cpu_data());
-  Dtype loss = caffe_cpu_dot(
-      count, difference_.cpu_data(), difference_.cpu_data()) / num / Dtype(2);
-  return loss;
-}
-
-template <typename Dtype>
-void EuclideanLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
-    const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
-  int count = (*bottom)[0]->count();
-  int num = (*bottom)[0]->num();
-  // Compute the gradient
-  caffe_cpu_axpby(count, Dtype(1) / num, difference_.cpu_data(), Dtype(0),
-      (*bottom)[0]->mutable_cpu_diff());
-}
-
-template <typename Dtype>
-void AccuracyLayer<Dtype>::SetUp(
-  const vector<Blob<Dtype>*>& bottom, vector<Blob<Dtype>*>* top) {
-  CHECK_EQ(bottom.size(), 2) << "Accuracy Layer takes two blobs as input.";
-  CHECK_EQ(top->size(), 1) << "Accuracy Layer takes 1 output.";
-  CHECK_EQ(bottom[0]->num(), bottom[1]->num())
-      << "The data and label should have the same number.";
-  CHECK_EQ(bottom[1]->channels(), 1);
-  CHECK_EQ(bottom[1]->height(), 1);
-  CHECK_EQ(bottom[1]->width(), 1);
-  (*top)[0]->Reshape(1, 2, 1, 1);
-}
-
-template <typename Dtype>
-Dtype AccuracyLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
-    vector<Blob<Dtype>*>* top) {
-  Dtype accuracy = 0;
-  Dtype logprob = 0;
-  const Dtype* bottom_data = bottom[0]->cpu_data();
-  const Dtype* bottom_label = bottom[1]->cpu_data();
-  int num = bottom[0]->num();
-  int dim = bottom[0]->count() / bottom[0]->num();
-  for (int i = 0; i < num; ++i) {
-    // Accuracy
-    Dtype maxval = -FLT_MAX;
-    int max_id = 0;
-    for (int j = 0; j < dim; ++j) {
-      if (bottom_data[i * dim + j] > maxval) {
-        maxval = bottom_data[i * dim + j];
-        max_id = j;
-      }
-    }
-    if (max_id == static_cast<int>(bottom_label[i])) {
-      ++accuracy;
-    }
-    Dtype prob = max(bottom_data[i * dim + static_cast<int>(bottom_label[i])],
-                     Dtype(kLOG_THRESHOLD));
-    logprob -= log(prob);
-  }
-  // LOG(INFO) << "Accuracy: " << accuracy;
-  (*top)[0]->mutable_cpu_data()[0] = accuracy / num;
-  (*top)[0]->mutable_cpu_data()[1] = logprob / num;
-  // Accuracy layer should not be used as a loss function.
-  return Dtype(0);
-}
-
-template <typename Dtype>
-void HingeLossLayer<Dtype>::SetUp(const vector<Blob<Dtype>*>& bottom,
-    vector<Blob<Dtype>*>* top) {
-  CHECK_EQ(bottom.size(), 2) << "Hinge Loss Layer takes two blobs as input.";
-  CHECK_EQ(top->size(), 0) << "Hinge Loss Layer takes no output.";
-  C_ =  this->layer_param_.hinge_loss_param().c_param();
-}
-
-template <typename Dtype>
-Dtype HingeLossLayer<Dtype>::Forward_cpu(const vector<Blob<Dtype>*>& bottom,
-    vector<Blob<Dtype>*>* top) {
-  const Dtype* bottom_data = bottom[0]->cpu_data();
-  Dtype* bottom_diff = bottom[0]->mutable_cpu_diff();
-  const Dtype* label = bottom[1]->cpu_data();
-  int num = bottom[0]->num();
-  int count = bottom[0]->count();
-  int dim = count / num;
-
-  caffe_copy(count, bottom_data, bottom_diff);
-  for (int i = 0; i < num; ++i) {
-    bottom_diff[i * dim + static_cast<int>(label[i])] *= -1;
-  }
-  for (int i = 0; i < num; ++i) {
-    for (int j = 0; j < dim; ++j) {
-      bottom_diff[i * dim + j] = max(Dtype(0), 1 + bottom_diff[i * dim + j]);
-    }
-  }
-  switch (this->layer_param_.hinge_loss_param().hinge_norm()) {
-  case HingeLossParameter_Norm_L1:
-    return caffe_cpu_asum(count, bottom_diff) / num * C_;
-  case HingeLossParameter_Norm_L2:
-    return caffe_cpu_dot(count, bottom_diff, bottom_diff) / num * C_;
-  default:
-    LOG(FATAL) << "Unknown hinge_norm";
-  }
-}
-
-template <typename Dtype>
-void HingeLossLayer<Dtype>::Backward_cpu(const vector<Blob<Dtype>*>& top,
-    const bool propagate_down, vector<Blob<Dtype>*>* bottom) {
-  Dtype* bottom_diff = (*bottom)[0]->mutable_cpu_diff();
-  const Dtype* label = (*bottom)[1]->cpu_data();
-  int num = (*bottom)[0]->num();
-  int count = (*bottom)[0]->count();
-  int dim = count / num;
-  
-  for (int i = 0; i < num; ++i) {
-    bottom_diff[i * dim + static_cast<int>(label[i])] *= -1;
-  }
-
-  switch (this->layer_param_.hinge_loss_param().hinge_norm()) {
-  case HingeLossParameter_Norm_L1:
-    caffe_cpu_sign(count, bottom_diff, bottom_diff);
-    caffe_scal(count, Dtype(C_ / num), bottom_diff);
-    break;
-  case HingeLossParameter_Norm_L2:
-    caffe_scal(count, Dtype(2 * C_ / num), bottom_diff);
-    break;
-  default:
-    LOG(FATAL) << "Unknown hinge_norm";
-  }  
->>>>>>> 161e7cb... Fix the loss to follow the convention
 }
 
 INSTANTIATE_CLASS(LossLayer);