From 9c539dcf1d31f5d2e4a06698377b5a8618591b97 Mon Sep 17 00:00:00 2001 From: Evan Shelhamer Date: Wed, 21 May 2014 19:31:47 -0700 Subject: [PATCH] Elementwise layer learns summation --- src/caffe/layers/eltwise_layer.cpp | 9 ++++++ src/caffe/layers/eltwise_layer.cu | 9 ++++++ src/caffe/proto/caffe.proto | 1 + src/caffe/test/test_eltwise_layer.cpp | 59 ++++++++++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/caffe/layers/eltwise_layer.cpp b/src/caffe/layers/eltwise_layer.cpp index dd46618..769d015 100644 --- a/src/caffe/layers/eltwise_layer.cpp +++ b/src/caffe/layers/eltwise_layer.cpp @@ -41,6 +41,12 @@ Dtype EltwiseLayer::Forward_cpu( caffe_mul(count, top_data, bottom[i]->cpu_data(), top_data); } break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_add(count, bottom[0]->cpu_data(), bottom[1]->cpu_data(), top_data); + for (int i = 2; i < bottom.size(); ++i) { + caffe_add(count, top_data, bottom[i]->cpu_data(), top_data); + } + break; default: LOG(FATAL) << "Unknown elementwise operation."; } @@ -62,6 +68,9 @@ void EltwiseLayer::Backward_cpu(const vector*>& top, caffe_div(count, top_data, bottom_data, bottom_diff); caffe_mul(count, bottom_diff, top_diff, bottom_diff); break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_copy(count, top_diff, bottom_diff); + break; default: LOG(FATAL) << "Unknown elementwise operation."; } diff --git a/src/caffe/layers/eltwise_layer.cu b/src/caffe/layers/eltwise_layer.cu index 9072f88..8bdb6a3 100644 --- a/src/caffe/layers/eltwise_layer.cu +++ b/src/caffe/layers/eltwise_layer.cu @@ -20,6 +20,12 @@ Dtype EltwiseLayer::Forward_gpu( caffe_gpu_mul(count, top_data, bottom[i]->gpu_data(), top_data); } break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_gpu_add(count, bottom[0]->gpu_data(), bottom[1]->gpu_data(), top_data); + for (int i = 2; i < bottom.size(); ++i) { + caffe_gpu_add(count, top_data, bottom[i]->gpu_data(), top_data); + } + break; default: LOG(FATAL) << "Unknown elementwise operation."; } @@ -41,6 +47,9 @@ void EltwiseLayer::Backward_gpu(const vector*>& top, caffe_gpu_div(count, top_data, bottom_data, bottom_diff); caffe_gpu_mul(count, bottom_diff, top_diff, bottom_diff); break; + case EltwiseParameter_EltwiseOp_SUM: + caffe_gpu_copy(count, top_diff, bottom_diff); + break; default: LOG(FATAL) << "Unknown elementwise operation."; } diff --git a/src/caffe/proto/caffe.proto b/src/caffe/proto/caffe.proto index a0a855e..a7fb37b 100644 --- a/src/caffe/proto/caffe.proto +++ b/src/caffe/proto/caffe.proto @@ -255,6 +255,7 @@ message DropoutParameter { message EltwiseParameter { enum EltwiseOp { PROD = 0; + SUM = 1; } optional EltwiseOp operation = 1; // element-wise operation to compute } diff --git a/src/caffe/test/test_eltwise_layer.cpp b/src/caffe/test/test_eltwise_layer.cpp index 86e4751..dbb77fc 100644 --- a/src/caffe/test/test_eltwise_layer.cpp +++ b/src/caffe/test/test_eltwise_layer.cpp @@ -65,7 +65,7 @@ TYPED_TEST(EltwiseLayerTest, TestSetUp) { EXPECT_EQ(this->blob_top_->width(), 5); } -TYPED_TEST(EltwiseLayerTest, TestCPU) { +TYPED_TEST(EltwiseLayerTest, TestProdCPU) { Caffe::set_mode(Caffe::CPU); LayerParameter layer_param; EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); @@ -84,7 +84,26 @@ TYPED_TEST(EltwiseLayerTest, TestCPU) { } } -TYPED_TEST(EltwiseLayerTest, TestGPU) { +TYPED_TEST(EltwiseLayerTest, TestSumCPU) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] + in_data_b[i] + in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestProdGPU) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); @@ -103,7 +122,26 @@ TYPED_TEST(EltwiseLayerTest, TestGPU) { } } -TYPED_TEST(EltwiseLayerTest, TestCPUGradient) { +TYPED_TEST(EltwiseLayerTest, TestSumGPU) { + Caffe::set_mode(Caffe::GPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + shared_ptr > layer( + new EltwiseLayer(layer_param)); + layer->SetUp(this->blob_bottom_vec_, &(this->blob_top_vec_)); + layer->Forward(this->blob_bottom_vec_, &(this->blob_top_vec_)); + const TypeParam* data = this->blob_top_->cpu_data(); + const int count = this->blob_top_->count(); + const TypeParam* in_data_a = this->blob_bottom_a_->cpu_data(); + const TypeParam* in_data_b = this->blob_bottom_b_->cpu_data(); + const TypeParam* in_data_c = this->blob_bottom_c_->cpu_data(); + for (int i = 0; i < count; ++i) { + EXPECT_EQ(data[i], in_data_a[i] + in_data_b[i] + in_data_c[i]); + } +} + +TYPED_TEST(EltwiseLayerTest, TestProdCPUGradient) { Caffe::set_mode(Caffe::CPU); LayerParameter layer_param; EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); @@ -114,11 +152,22 @@ TYPED_TEST(EltwiseLayerTest, TestCPUGradient) { &(this->blob_top_vec_)); } -TYPED_TEST(EltwiseLayerTest, TestGPUGradient) { +TYPED_TEST(EltwiseLayerTest, TestSumCPUGradient) { + Caffe::set_mode(Caffe::CPU); + LayerParameter layer_param; + EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); + EltwiseLayer layer(layer_param); + GradientChecker checker(1e-2, 1e-3); + checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), + &(this->blob_top_vec_)); +} + +TYPED_TEST(EltwiseLayerTest, TestSumGPUGradient) { Caffe::set_mode(Caffe::GPU); LayerParameter layer_param; EltwiseParameter* eltwise_param = layer_param.mutable_eltwise_param(); - eltwise_param->set_operation(EltwiseParameter_EltwiseOp_PROD); + eltwise_param->set_operation(EltwiseParameter_EltwiseOp_SUM); EltwiseLayer layer(layer_param); GradientChecker checker(1e-2, 1e-2); checker.CheckGradientEltwise(&layer, &(this->blob_bottom_vec_), -- 2.7.4