From 5b974e05f28a4950fdf5aa6f7604ff207fe7684e Mon Sep 17 00:00:00 2001 From: Jeff Donahue Date: Tue, 15 Jul 2014 13:15:36 -0700 Subject: Add Net Test to verify correct param_propagate_down behavior. --- src/caffe/test/test_net.cpp | 119 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 8 deletions(-) diff --git a/src/caffe/test/test_net.cpp b/src/caffe/test/test_net.cpp index 129d4447..cd6daeb6 100644 --- a/src/caffe/test/test_net.cpp +++ b/src/caffe/test/test_net.cpp @@ -14,6 +14,8 @@ #include "caffe/test/test_caffe_main.hpp" +using std::ostringstream; + namespace caffe { template @@ -216,8 +218,11 @@ class NetTest : public ::testing::Test { InitNetFromProtoString(proto); } - virtual void InitUnsharedWeightsNet() { - const string& proto = + virtual void InitUnsharedWeightsNet(const bool bias_term = false, + const Dtype blobs_lr_w1 = 1, const Dtype blobs_lr_b1 = 2, + const Dtype blobs_lr_w2 = 1, const Dtype blobs_lr_b2 = 2) { + ostringstream proto; + proto << "name: 'UnsharedWeightsNetwork' " "layers: { " " name: 'data' " @@ -236,16 +241,25 @@ class NetTest : public ::testing::Test { "} " "layers: { " " name: 'innerproduct1' " - " type: INNER_PRODUCT " + " type: INNER_PRODUCT " " inner_product_param { " " num_output: 10 " - " bias_term: false " + " bias_term: " << bias_term << " weight_filler { " " type: 'gaussian' " " std: 10 " " } " " } " - " param: 'unsharedweights1' " + " param: 'unsharedweights1' "; + if (bias_term) { + proto << " param: '' "; + } + proto << + " blobs_lr: " << blobs_lr_w1; + if (bias_term) { + proto << " blobs_lr: " << blobs_lr_b1; + } + proto << " bottom: 'data' " " top: 'innerproduct1' " "} " @@ -254,14 +268,23 @@ class NetTest : public ::testing::Test { " type: INNER_PRODUCT " " inner_product_param { " " num_output: 10 " - " bias_term: false " + " bias_term: " << bias_term << " weight_filler { " " type: 'gaussian' " " std: 10 " " } " " } " - " param: 'unsharedweights2' " + " param: 'unsharedweights2' "; + if (bias_term) { + proto << " param: '' "; + } + proto << " bottom: 'data' " + " blobs_lr: " << blobs_lr_w2; + if (bias_term) { + proto << " blobs_lr: " << blobs_lr_b2; + } + proto << " top: 'innerproduct2' " "} " "layers: { " @@ -270,7 +293,7 @@ class NetTest : public ::testing::Test { " bottom: 'innerproduct1' " " bottom: 'innerproduct2' " "} "; - InitNetFromProtoString(proto); + InitNetFromProtoString(proto.str()); } virtual void InitSharedWeightsNet() { @@ -698,4 +721,84 @@ TYPED_TEST(NetTest, TestSharedWeightsUpdate) { } } +TYPED_TEST(NetTest, TestParamPropagateDown) { + typedef typename TypeParam::Dtype Dtype; + vector*> bottom; + const bool kBiasTerm = true; + + // Run the net with all params learned; check that gradients are non-zero. + Caffe::set_random_seed(this->seed_); + Dtype blobs_lr_w1 = 1, blobs_lr_w2 = 1, blobs_lr_b1 = 2, blobs_lr_b2 = 2; + this->InitUnsharedWeightsNet(kBiasTerm, blobs_lr_w1, blobs_lr_w2, + blobs_lr_b1, blobs_lr_b2); + this->net_->Forward(bottom); + this->net_->Backward(); + const vector > >& params = this->net_->params(); + const int num_params = params.size(); + ASSERT_EQ(4, num_params); + const Dtype kNonZeroTestMin = 1e-3; + vector param_asums(params.size()); + for (int i = 0; i < num_params; ++i) { + const Dtype param_asum = + caffe_cpu_asum(params[i]->count(), params[i]->cpu_diff()); + param_asums[i] = param_asum; + EXPECT_GT(param_asum, kNonZeroTestMin); + } + + // Change the learning rates to different non-zero values; should see same + // gradients. + Caffe::set_random_seed(this->seed_); + blobs_lr_w1 *= 2, blobs_lr_w2 *= 2, blobs_lr_b1 *= 2, blobs_lr_b2 *= 2; + this->InitUnsharedWeightsNet(kBiasTerm, blobs_lr_w1, blobs_lr_w2, + blobs_lr_b1, blobs_lr_b2); + this->net_->Forward(bottom); + this->net_->Backward(); + const vector > >& params2 = this->net_->params(); + ASSERT_EQ(num_params, params2.size()); + for (int i = 0; i < num_params; ++i) { + const Dtype param_asum = + caffe_cpu_asum(params2[i]->count(), params2[i]->cpu_diff()); + EXPECT_EQ(param_asum, param_asums[i]); + } + + // Change a subset of the learning rates to zero; check that we see zero + // gradients for those. + Caffe::set_random_seed(this->seed_); + blobs_lr_w1 = 1, blobs_lr_w2 = 0, blobs_lr_b1 = 0, blobs_lr_b2 = 1; + this->InitUnsharedWeightsNet(kBiasTerm, blobs_lr_w1, blobs_lr_w2, + blobs_lr_b1, blobs_lr_b2); + this->net_->Forward(bottom); + this->net_->Backward(); + const vector > >& params3 = this->net_->params(); + ASSERT_EQ(num_params, params3.size()); + for (int i = 0; i < num_params; ++i) { + const Dtype param_asum = + caffe_cpu_asum(params3[i]->count(), params3[i]->cpu_diff()); + if (i == 1 || i == 2) { + EXPECT_EQ(0, param_asum); + } else { + EXPECT_EQ(param_asum, param_asums[i]); + } + } + + // Change the opposite subset of the learning rates to zero. + Caffe::set_random_seed(this->seed_); + blobs_lr_w1 = 0, blobs_lr_w2 = 1, blobs_lr_b1 = 1, blobs_lr_b2 = 0; + this->InitUnsharedWeightsNet(kBiasTerm, blobs_lr_w1, blobs_lr_w2, + blobs_lr_b1, blobs_lr_b2); + this->net_->Forward(bottom); + this->net_->Backward(); + const vector > >& params4 = this->net_->params(); + ASSERT_EQ(num_params, params4.size()); + for (int i = 0; i < num_params; ++i) { + const Dtype param_asum = + caffe_cpu_asum(params4[i]->count(), params4[i]->cpu_diff()); + if (i == 0 || i == 3) { + EXPECT_EQ(0, param_asum); + } else { + EXPECT_EQ(param_asum, param_asums[i]); + } + } +} + } // namespace caffe -- cgit v1.2.3