[tensor/tensor_dim] Added equal comparison operation
authorParichay Kapoor <pk.kapoor@samsung.com>
Tue, 23 Jun 2020 05:08:56 +0000 (14:08 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Wed, 24 Jun 2020 05:03:06 +0000 (14:03 +0900)
Added equal comparison operation
Currently its based on fixed epsilon
Needs updation to use variable number of bits based on exponentiation as done in gtest

Signed-off-by: Parichay Kapoor <pk.kapoor@samsung.com>
nntrainer/include/tensor.h
nntrainer/include/tensor_dim.h
nntrainer/src/tensor.cpp
nntrainer/src/tensor_dim.cpp
test/include/nntrainer_test_util.h
test/nntrainer_test_util.cpp
test/unittest/unittest_nntrainer_layers.cpp
test/unittest/unittest_nntrainer_lazy_tensor.cpp

index a9e6e5b..2e1e4b8 100644 (file)
@@ -102,6 +102,18 @@ public:
   Tensor(std::vector<std::vector<std::vector<std::vector<float>>>> const &d);
 
   /**
+   * @brief     Comparison operator overload
+   * @param[in] rhs Tensor to be compared with
+   */
+  bool operator== (const Tensor &rhs) const;
+
+  /**
+   * @brief     Comparison operator overload
+   * @param[in] rhs Tensor to be compared with
+   */
+  bool operator!= (const Tensor &rhs) const { return !(*this == rhs); }
+
+  /**
    * @brief     return value at specific location
    * @param[in] batch batch location
    * @param[in] c channel location
@@ -474,6 +486,7 @@ private:
   static constexpr float min_limits = std::numeric_limits<float>::min();
   static constexpr float max_limits = std::numeric_limits<float>::max();
   template <typename T> void setDist(T dist);
+  static constexpr float epsilon = 1e-5;
 };
 
 /**
index 635d0d2..b77d73c 100644 (file)
@@ -54,6 +54,8 @@ public:
   int setTensorDim(std::string input_shape);
 
   void operator=(const TensorDim &from);
+  bool operator==(const TensorDim &rhs) const;
+  bool operator!=(const TensorDim &rhs) const { return !(*this == rhs); }
 
 private:
   unsigned int dim[MAXDIM];
index 3b119e8..6b649b3 100644 (file)
@@ -91,6 +91,22 @@ Tensor::Tensor(int batch, int channel, int height, int width) {
   setZero();
 }
 
+bool Tensor::operator== (const Tensor &rhs) const {
+  if (this->dim != rhs.dim)
+    return false;
+
+  if (data.size() != rhs.data.size())
+    return false;
+
+  for (size_t i = 0; i < data.size(); ++i) {
+    if (std::isnan(data[i]) || std::isnan(rhs.data[i]) ||
+        std::fabs(data[i] - rhs.data[i]) > epsilon)
+      return false;
+  }
+
+  return true;
+}
+
 float Tensor::getValue(unsigned int batch, unsigned int c, unsigned int h,
                        unsigned int w) const {
   return this->data[batch * dim.channel() * dim.height() * dim.width() +
index 72bf8b5..2920ee6 100644 (file)
@@ -63,7 +63,17 @@ void TensorDim::operator=(const TensorDim &from) {
   }
   len = from.len;
   feature_len = from.feature_len;
-};
+}
+
+bool TensorDim::operator==(const TensorDim &rhs) const {
+  for (int i = 0; i < MAXDIM; ++i) {
+    if (this->dim[i] != rhs.dim[i]) {
+      return false;
+    }
+  }
+
+  return true;
+}
 
 std::ostream &operator<<(std::ostream &out, TensorDim const &d) {
   out << "Shape : " << d.batch() << ":" << d.channel() << ":" << d.height()
index e5c6714..0006985 100644 (file)
@@ -213,14 +213,6 @@ const std::string config_str2 = "[Network]"
     }                                                        \
   } while (0)
 
-
-/**
- * @brief test tensor is equal
- * @param[in] Tensor A, tensor to be compared
- * @param[in] Tensor B, tensor to be compared
- */
-void test_tensor_eq(nntrainer::Tensor const &A, nntrainer::Tensor const &B);
-
 /**
  * @brief return a tensor filled with contant value with dimension
  */
index 5ce6a77..e0cfe40 100644 (file)
@@ -252,24 +252,6 @@ nntrainer::Tensor constant(float value, unsigned int batch, unsigned channel,
                            unsigned height, unsigned width) {
   nntrainer::Tensor t(batch, channel, height, width);
   t.setValue(value);
-  
-  return t;
-}
-
-
-void test_tensor_eq(nntrainer::Tensor const &A, nntrainer::Tensor const &B) {
-  EXPECT_EQ(A.getBatch(), B.getBatch());
-  EXPECT_EQ(A.getChannel(), B.getChannel());
-  EXPECT_EQ(A.getHeight(), B.getHeight());
-  EXPECT_EQ(A.getWidth(), B.getWidth());
 
-  int len = A.getDim().getDataLen();
-  const float *aData = A.getData();
-  ASSERT_NE(aData, (float *)NULL);
-  const float *bData = B.getData();
-  ASSERT_NE(bData, (float *)NULL);
-
-  for (int i = 0; i < len; ++i) {
-    EXPECT_FLOAT_EQ(aData[i], bData[i]);
-  }
+  return t;
 }
index d7ae670..8c0ad02 100644 (file)
@@ -994,7 +994,7 @@ TEST(nntrainer_ActivationLayer, forward_backward_01_p) {
   int channel = 1;
   int height = 1;
   int width = 10;
-  
+
   nntrainer::ActivationLayer layer;
   layer.setActivation(nntrainer::ACT_RELU);
 
@@ -1004,12 +1004,12 @@ TEST(nntrainer_ActivationLayer, forward_backward_01_p) {
   GEN_TEST_INPUT(expected, nntrainer::relu((l - 4) * 0.1 * (i + 1)));
   nntrainer::Tensor result = layer.forwarding(input, status);
   EXPECT_EQ(status, ML_ERROR_NONE);
-  test_tensor_eq(result, expected);
+  EXPECT_TRUE(result == expected);
 
   expected.copy(input);
   result = layer.backwarding(constant(1.0, 3, 1, 1, 10), 1);
   GEN_TEST_INPUT(expected, nntrainer::reluPrime(nntrainer::relu((l - 4) * 0.1 * (i + 1))));;
-  test_tensor_eq(result, expected);
+  EXPECT_TRUE(result == expected);
 }
 
 /**
index e728ea7..88a68bc 100644 (file)
@@ -76,49 +76,49 @@ TEST(nntrainer_LazyTensor, LazyTensor_01_p) {
 
 // Simple chain and run
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_01_p) {
-  test_tensor_eq(target.chain().run(), original);
+  EXPECT_TRUE(target.chain().run() == original);
 }
 
 // Simple chain and add_i(float)
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_02_p) {
   expected = original.add(2.1);
-  test_tensor_eq(target.chain().add_i(2.1).run(), expected);
+  EXPECT_TRUE(target.chain().add_i(2.1).run() == expected);
 }
 
 // chain and add_i(float) add_i(float)
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_03_p) {
   expected = original.add(4.2);
-  test_tensor_eq(target.chain().add_i(2.1).add_i(2.1).run(), expected);
+  EXPECT_TRUE(target.chain().add_i(2.1).add_i(2.1).run() == expected);
 }
 
 // chain and add_i(float) add_i(float)
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_04_p) {
   expected = original.add(4.2);
-  test_tensor_eq(target.chain().add_i(2.1).add_i(2.1).run(), expected);
+  EXPECT_TRUE(target.chain().add_i(2.1).add_i(2.1).run() == expected);
 }
 
 // chain and add_i(float) add_i(Tensor)
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_05_p) {
   expected = original.add(6.1);
-  test_tensor_eq(target.chain().add_i(2.1).add_i(constant_(2.0), 2).run(), expected);
+  EXPECT_TRUE(target.chain().add_i(2.1).add_i(constant_(2.0), 2).run() == expected);
 }
 
 // chain and add_i(float) subtract(float)
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_06_p) {
-  test_tensor_eq(target.chain().add_i(2.1).subtract_i(2.1).run(), original);
+  EXPECT_TRUE(target.chain().add_i(2.1).subtract_i(2.1).run() == original);
 }
 
 // other basic operations (positive)...
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_07_p) {
   target = constant_(1.0);
   expected = constant_(2.0);
-  test_tensor_eq(target.chain().multiply_i(2.0).run(), expected);
-  test_tensor_eq(target.chain().multiply_i(constant_(2.0)).run(), expected);
+  EXPECT_TRUE(target.chain().multiply_i(2.0).run() == expected);
+  EXPECT_TRUE(target.chain().multiply_i(constant_(2.0)).run() == expected);
 
   target = constant_(1.0);
   expected = constant_(0.5);
-  test_tensor_eq(target.chain().divide_i(2.0).run(), expected);
-  test_tensor_eq(target.chain().divide_i(constant_(2.0)).run(), expected);
+  EXPECT_TRUE(target.chain().divide_i(2.0).run() == expected);
+  EXPECT_TRUE(target.chain().divide_i(constant_(2.0)).run() == expected);
 }
 
 // other basic operations (negative)...
@@ -140,32 +140,32 @@ TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_07_n) {
 TEST_F(nntrainer_LazyTensorOpsTest, LazyTensorOps_08_p) {
   target = constant(1.0, 4, 4, 4, 4);
   expected = constant(64.0, 4, 1, 1, 1);
-  test_tensor_eq(target.chain().sum_by_batch().run(), expected);
+  EXPECT_TRUE(target.chain().sum_by_batch().run() == expected);
 
   expected = constant(4.0, 1, 4, 4, 4);
-  test_tensor_eq(target.chain().sum(0).run(), expected);
+  EXPECT_TRUE(target.chain().sum(0).run() == expected);
 
   expected = constant(4.0, 4, 1, 4, 4);
-  test_tensor_eq(target.chain().sum(1).run(), expected);
+  EXPECT_TRUE(target.chain().sum(1).run() == expected);
 
   expected = constant(4.0, 4, 4, 1, 4);
-  test_tensor_eq(target.chain().sum(2).run(), expected);
+  EXPECT_TRUE(target.chain().sum(2).run() == expected);
 
   expected = constant(4.0, 4, 4, 4, 1);
-  test_tensor_eq(target.chain().sum(3).run(), expected);
+  EXPECT_TRUE(target.chain().sum(3).run() == expected);
 }
 
 TEST_F(nntrainer_LazyTensorOpsTest, ApplyIf_01_p) {
 
-  test_tensor_eq(target.chain().applyIf(true, _LIFT(add_i), constant_(4.0), 0.5).run(),
+  EXPECT_TRUE(target.chain().applyIf(true, _LIFT(add_i), constant_(4.0), 0.5).run() ==
           original.add(2.0));
 
-  test_tensor_eq(target.chain().applyIf(true, _LIFT(add_i), 2.0f).run(),
+  EXPECT_TRUE(target.chain().applyIf(true, _LIFT(add_i), 2.0f).run() ==
           original.add(2.0));
 
-  test_tensor_eq(target.chain().applyIf(true, _LIFT(add_i), 2.0).run(),
+  EXPECT_TRUE(target.chain().applyIf(true, _LIFT(add_i), 2.0).run() ==
           original.add(2.0));
-          
+
 }
 
 TEST_F(nntrainer_LazyTensorOpsTest, ApplyIf_01_n) {