test case fix for Clip layer gradient
authorNoiredd <snowball91b@gmail.com>
Fri, 30 Mar 2018 09:43:44 +0000 (11:43 +0200)
committerWook Song <wook16.song@samsung.com>
Thu, 23 Jan 2020 13:50:48 +0000 (22:50 +0900)
minor lint fixes

src/caffe/layers/clip_layer.cpp
src/caffe/layers/clip_layer.cu
src/caffe/test/test_neuron_layer.cpp

index 7638701..9d9a596 100644 (file)
@@ -1,5 +1,6 @@
 #include <algorithm>
 #include <vector>
+
 #include "caffe/layers/clip_layer.hpp"
 
 namespace caffe {
index f780447..56f3be3 100644 (file)
@@ -1,4 +1,5 @@
 #include <vector>
+
 #include "caffe/layers/clip_layer.hpp"
 #include "caffe/util/math_functions.hpp"
 
index 5865e08..d1ecc37 100644 (file)
@@ -234,9 +234,37 @@ TYPED_TEST(NeuronLayerTest, TestClipGradient) {
   CHECK(google::protobuf::TextFormat::ParseFromString(
       "clip_param { min: -1, max: 2 }", &layer_param));
   ClipLayer<Dtype> layer(layer_param);
-  GradientChecker<Dtype> checker(1e-2, 1e-3);
-  checker.CheckGradientEltwise(&layer, this->blob_bottom_vec_,
-      this->blob_top_vec_);
+  // Unfortunately, it might happen that an input value lands exactly within
+  // the discontinuity region of the Clip function. In this case the numeric
+  // gradient is likely to differ significantly (i.e. by a value larger than
+  // checker tolerance) from the computed gradient. To handle such cases, we
+  // eliminate such values from the input blob before the gradient check.
+  const Dtype epsilon = 1e-2;
+  const Dtype min_range_start = layer_param.clip_param().min() - epsilon;
+  const Dtype min_range_end   = layer_param.clip_param().min() + epsilon;
+  const Dtype max_range_start = layer_param.clip_param().max() - epsilon;
+  const Dtype max_range_end   = layer_param.clip_param().max() + epsilon;
+  // The input blob is owned by the NeuronLayerTest object, so we begin with
+  // creating a temporary blob and copying the input data there.
+  Blob<Dtype> temp_bottom;
+  temp_bottom.ReshapeLike(*this->blob_bottom_);
+  const Dtype* bottom_data = this->blob_bottom_->cpu_data();
+  Dtype* temp_data_mutable = temp_bottom.mutable_cpu_data();
+  for (int i = 0; i < this->blob_bottom_->count(); ++i) {
+    if (bottom_data[i] >= min_range_start &&
+        bottom_data[i] <= min_range_end) {
+      temp_data_mutable[i] = bottom_data[i] - epsilon;
+    } else if (bottom_data[i] >= max_range_start &&
+               bottom_data[i] <= max_range_end) {
+      temp_data_mutable[i] = bottom_data[i] + epsilon;
+    } else {
+      temp_data_mutable[i] = bottom_data[i];
+    }
+  }
+  vector<Blob<Dtype>*> temp_bottom_vec;
+  temp_bottom_vec.push_back(&temp_bottom);
+  GradientChecker<Dtype> checker(epsilon, 1e-3);
+  checker.CheckGradientEltwise(&layer, temp_bottom_vec, this->blob_top_vec_);
 }
 
 TYPED_TEST(NeuronLayerTest, TestReLU) {