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);