From 6f1bd27c75f0b7b6f3ae5d7dc4e17c3abe3a35ad Mon Sep 17 00:00:00 2001 From: max argus Date: Sun, 22 Feb 2015 21:00:38 +0000 Subject: [PATCH] fixed accuracy layer. With ND Blobs. --- include/caffe/loss_layers.hpp | 6 +++ src/caffe/layers/accuracy_layer.cpp | 67 +++++++++++++++++++---------- src/caffe/proto/caffe.proto | 13 ++++++ 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/include/caffe/loss_layers.hpp b/include/caffe/loss_layers.hpp index 36413ccd176..d3989e788f7 100644 --- a/include/caffe/loss_layers.hpp +++ b/include/caffe/loss_layers.hpp @@ -78,7 +78,13 @@ class AccuracyLayer : public Layer { } } + int top_k_; + + /// Whether to ignore instances with a certain label. + bool has_ignore_label_; + /// The label indicating that an instance should be ignored. + int ignore_label_; }; /** diff --git a/src/caffe/layers/accuracy_layer.cpp b/src/caffe/layers/accuracy_layer.cpp index 3e8df34c0d6..48d44f52d01 100644 --- a/src/caffe/layers/accuracy_layer.cpp +++ b/src/caffe/layers/accuracy_layer.cpp @@ -14,6 +14,12 @@ template void AccuracyLayer::LayerSetUp( const vector*>& bottom, const vector*>& top) { top_k_ = this->layer_param_.accuracy_param().top_k(); + + has_ignore_label_ = + this->layer_param_.accuracy_param().has_ignore_label(); + if (has_ignore_label_) { + ignore_label_ = this->layer_param_.accuracy_param().ignore_label(); + } } template @@ -24,8 +30,9 @@ void AccuracyLayer::Reshape( CHECK_LE(top_k_, bottom[0]->count() / bottom[0]->num()) << "top_k must be less than or equal to the number of classes."; CHECK_EQ(bottom[1]->channels(), 1); - CHECK_EQ(bottom[1]->height(), 1); - CHECK_EQ(bottom[1]->width(), 1); + CHECK_EQ(bottom[0]->height(), bottom[1]->height()); + CHECK_EQ(bottom[0]->width(), bottom[1]->width()); + top[0]->Reshape(1, 1, 1, 1); } @@ -34,32 +41,48 @@ 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); - for (int i = 0; i < num; ++i) { - // Top-k accuracy - std::vector > bottom_data_vector; - for (int j = 0; j < dim; ++j) { - bottom_data_vector.push_back( - std::make_pair(bottom_data[i * dim + j], j)); - } - std::partial_sort( - bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_, - 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])) { - ++accuracy; - break; + int channels = bottom[0]->channels(); + int spatial_dim = bottom[0]->height() * bottom[0]->width(); + const Dtype* bottom_label = bottom[1]->cpu_data(); + unsigned int count = 0; + + for (int n = 0; n < num; ++n) { + for (int j = 0; j< spatial_dim; ++j) { + const int label_value = + static_cast(bottom_label[n * spatial_dim + j]); + if (has_ignore_label_ && label_value == ignore_label_) { + continue; + } + DCHECK_GE(label_value, 0); + DCHECK_LT(label_value, bottom[0]->channels()); + + + // Top-k accuracy + std::vector > bottom_data_vector; + + for (int c = 0; c < channels; ++c) { + int bottom_index = (n * channels + c) * spatial_dim + j; + bottom_data_vector.push_back( + std::make_pair(bottom_data[bottom_index], c)); + } + + std::partial_sort( + bottom_data_vector.begin(), bottom_data_vector.begin() + top_k_, + 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(label_value)) { + ++accuracy; + break; + } } + count++; } } // LOG(INFO) << "Accuracy: " << accuracy; - top[0]->mutable_cpu_data()[0] = accuracy / num; + top[0]->mutable_cpu_data()[0] = accuracy / count; // Accuracy layer should not be used as a loss function. } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index 84b475ce3cd..39242cfb821 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -320,6 +320,8 @@ message LayerParameter { optional WindowDataParameter window_data_param = 129; } + + // Message that stores parameters used to apply transformation // to the data layer's data message TransformationParameter { @@ -354,6 +356,17 @@ message AccuracyParameter { // the top k scoring classes. By default, only compare to the top scoring // class (i.e. argmax). optional uint32 top_k = 1 [default = 1]; + + // The "label" axis of the prediction blob, whose argmax corresponds to the + // predicted label -- may be negative to index from the end (e.g., -1 for the + // last axis). For example, if axis == 1 and the predictions are + // (N x C x H x W), the label blob is expected to contain N*H*W ground truth + // labels with integer values in {0, 1, ..., C-1}. + optional int32 axis = 2 [default = 1]; + + // If specified, ignore instances with the given label. + optional int32 ignore_label = 3; + } // Message that stores parameters used by ArgMaxLayer