From 647f91e8b0cdc2ee5c348c039ee3e268e94d2f1a Mon Sep 17 00:00:00 2001 From: Jack Culpepper Date: Sat, 18 Oct 2014 15:14:23 -0700 Subject: [PATCH 1/2] compute same label from label pair --- include/caffe/loss_layers.hpp | 10 ++++++++++ src/caffe/layers/hinge_loss_layer.cpp | 24 ++++++++++++++++++++---- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 9fe58cd97bc..7be24fd56e2 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -355,6 +355,13 @@ class HingeLossLayer : public LossLayer { return LayerParameter_LayerType_HINGE_LOSS; } + // HingeLossLayer takes 2-3 bottom Blobs; if there are 3 the second and third + // are compared to compute a 0/1 label. (Otherwise the label comes directly + // from the second.) + virtual inline int ExactNumBottomBlobs() const { return -1; } + virtual inline int MinBottomBlobs() const { return 2; } + virtual inline int MaxBottomBlobs() const { return 3; } + protected: /// @copydoc HingeLossLayer virtual void Forward_cpu(const vector*>& bottom, @@ -389,6 +396,9 @@ class HingeLossLayer : public LossLayer { */ virtual void Backward_cpu(const vector*>& top, const vector& propagate_down, const vector*>& bottom); + + private: + int ComputeLabel(const vector*>& bottom, int i); }; /** diff --git a/src/caffe/layers/hinge_loss_layer.cpp b/src/caffe/layers/hinge_loss_layer.cpp index f09916e2556..e7a3d5387c5 100644 --- a/src/caffe/layers/hinge_loss_layer.cpp +++ b/src/caffe/layers/hinge_loss_layer.cpp @@ -10,19 +10,34 @@ namespace caffe { +template +int HingeLossLayer::ComputeLabel(const vector*>& bottom, int i) { + int label; + if (bottom.size() == 2) { + label = static_cast(bottom[1]->cpu_data()[i]); + } else { // bottom.size() == 3 + // label == 1 if bottom[1] == bottom[2] (same) + // label == 0 if bottom[1] != bottom[2] (not same) + label = (bottom[1]->cpu_data()[i] == + bottom[2]->cpu_data()[i]) ? 1 : 0; + } + return label; +} + template void HingeLossLayer::Forward_cpu(const vector*>& bottom, const vector*>& 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; + int label; caffe_copy(count, bottom_data, bottom_diff); for (int i = 0; i < num; ++i) { - bottom_diff[i * dim + static_cast(label[i])] *= -1; + label = ComputeLabel(bottom, i); + bottom_diff[i * dim + label] *= -1; } for (int i = 0; i < num; ++i) { for (int j = 0; j < dim; ++j) { @@ -52,13 +67,14 @@ void HingeLossLayer::Backward_cpu(const vector*>& top, } if (propagate_down[0]) { 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; + int label; for (int i = 0; i < num; ++i) { - bottom_diff[i * dim + static_cast(label[i])] *= -1; + label = ComputeLabel(bottom, i); + bottom_diff[i * dim + label] *= -1; } const Dtype loss_weight = top[0]->cpu_diff()[0]; From a85197470d62a23b31368ffa60524e1e2cb7973e Mon Sep 17 00:00:00 2001 From: Jack Culpepper Date: Sun, 19 Oct 2014 01:00:47 -0700 Subject: [PATCH 2/2] modify accuracy layer to take 1 or 2 label blobs; if 2, compute same/not same --- include/caffe/loss_layers.hpp | 11 +++++++++-- src/caffe/layers/accuracy_layer.cpp | 22 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 7be24fd56e2..13bbf2301d2 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -41,8 +41,15 @@ class AccuracyLayer : public Layer { return LayerParameter_LayerType_ACCURACY; } - virtual inline int ExactNumBottomBlobs() const { return 2; } - virtual inline int ExactNumTopBlobs() const { return 1; } + // AccuracyLayer takes 2-3 bottom Blobs; if there are 3 the second and third + // are compared to compute a 0/1 label. (Otherwise the label comes directly + // from the second.) + virtual inline int ExactNumBottomBlobs() const { return -1; } + virtual inline int MinBottomBlobs() const { return 2; } + virtual inline int MaxBottomBlobs() const { return 3; } + + private: + int ComputeLabel(const vector*>& bottom, int i); protected: /** diff --git a/src/caffe/layers/accuracy_layer.cpp b/src/caffe/layers/accuracy_layer.cpp index 399cf2a3585..ce6d50be670 100644 --- a/src/caffe/layers/accuracy_layer.cpp +++ b/src/caffe/layers/accuracy_layer.cpp @@ -10,6 +10,23 @@ namespace caffe { +template +int AccuracyLayer::ComputeLabel(const vector*>& bottom, int i) { + int label; + if (bottom.size() == 2) { + label = static_cast(bottom[1]->cpu_data()[i]); + } else { // bottom.size() == 3 + // label == 1 if bottom[1] == bottom[2] (same) + // label == 0 if bottom[1] != bottom[2] (not same) + label = (bottom[1]->cpu_data()[i] == + bottom[2]->cpu_data()[i]) ? 1 : 0; + + if (i == 0) { + } + } + return label; +} + template void AccuracyLayer::LayerSetUp( const vector*>& bottom, const vector*>& top) { @@ -34,12 +51,13 @@ void AccuracyLayer::Forward_cpu(const vector*>& bottom, const vector*>& top) { Dtype accuracy = 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(); vector maxval(top_k_+1); vector max_id(top_k_+1); + int label; for (int i = 0; i < num; ++i) { + label = ComputeLabel(bottom, i); // Top-k accuracy std::vector > bottom_data_vector; for (int j = 0; j < dim; ++j) { @@ -51,7 +69,7 @@ void AccuracyLayer::Forward_cpu(const vector*>& bottom, bottom_data_vector.end(), std::greater >()); // check if true label is in top k predictions for (int k = 0; k < top_k_; k++) { - if (bottom_data_vector[k].second == static_cast(bottom_label[i])) { + if (bottom_data_vector[k].second == label) { ++accuracy; break; }