[moco/tf] fix maxpool2d shape calculation (#3801)
author박세희/On-Device Lab(SR)/Principal Engineer/삼성전자 <saehie.park@samsung.com>
Mon, 17 Jun 2019 07:04:53 +0000 (16:04 +0900)
committer박종현/On-Device Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Mon, 17 Jun 2019 07:04:53 +0000 (16:04 +0900)
* [moco/tf] fix maxpool2d shape calculation

This will fix maxpool2d shape calculation as like avgpool2d
- fix also op test model
- add PaddingData annotation

Signed-off-by: SaeHie Park <saehie.park@samsung.com>
* fix formula

* fix typo

* rename

contrib/moco/lib/frontend/tf/src/Op/MaxPool2D.cpp
contrib/moco/lib/frontend/tf/src/Op/MaxPool2D.test.cpp
contrib/moco/lib/frontend/tf/src/Transforms/FixShapeTransform.cpp

index 780d6c3..65c4036 100644 (file)
@@ -18,6 +18,8 @@
 #include "GraphBuilder.h"
 #include "GraphBuilderContext.h"
 
+#include "Annotations/PaddingData.h"
+
 #include <moco/tf/Names.h>
 #include <loco.h>
 #include <loco/IR/PermutingCodec.h>
@@ -144,6 +146,11 @@ void MaxPool2DGraphBuilder::build(const tensorflow::NodeDef &node,
       stride->vertical(tf_strides.i(2));
       stride->horizontal(tf_strides.i(3));
     }
+
+    // tf paddings -> PaddingData annotation
+    auto tf_padding = get_string_attr(node, "padding");
+    auto padding_data = stdex::make_unique<PaddingData>(tf_padding);
+    maxpool2d_node->annot(std::move(padding_data));
   }
 
   // FeatureDecode
index 5aebc19..74f9173 100644 (file)
@@ -51,11 +51,17 @@ node {
         dtype: DT_FLOAT
         tensor_shape {
           dim {
+            size: 1
+          }
+          dim {
             size: 3
           }
           dim {
             size: 3
           }
+          dim {
+            size: 1
+          }
         }
         float_val: 1.1
       }
index fc287cd..f0fca60 100644 (file)
@@ -188,9 +188,76 @@ bool fix_shape(loco::Forward *node)
 
 bool fix_shape(loco::MaxPool2D *node)
 {
-  // Output shape is same as the ifm
+  auto shapedata = node->annot<ShapeInferenceData>();
+  if (shapedata != nullptr)
+  {
+    // shape inference is already done for MaxPool2D
+    return false;
+  }
   auto ifm = node->ifm();
-  return copy_shapedata(ifm, node);
+  auto ifm_shapedata = ifm->annot<ShapeInferenceData>();
+  if (ifm_shapedata == nullptr)
+  {
+    // input node shape inference is not ready
+    return false;
+  }
+
+  auto padding_data = node->annot<PaddingData>();
+  if (padding_data == nullptr)
+  {
+    // PaddingData should exist
+    assert(false && "fix_shape for MaxPool2D failed as PaddingData is missing");
+    return false;
+  }
+
+  auto ifm_feature_shape = ifm_shapedata->feature_shape();
+
+  uint32_t input_height = ifm_feature_shape.height().value();
+  uint32_t input_width = ifm_feature_shape.width().value();
+  uint32_t stride_height = node->stride()->vertical();
+  uint32_t stride_width = node->stride()->horizontal();
+  uint32_t window_height = node->window()->vertical();
+  uint32_t window_width = node->window()->horizontal();
+  uint32_t dilation_height = 1; // dilation for MaxPool2D is 1
+  uint32_t dilation_width = 1;
+  uint32_t effective_window_height = dilation_height * (window_height - 1) + 1;
+  uint32_t effective_window_width = dilation_width * (window_width - 1) + 1;
+  uint32_t output_height;
+  uint32_t output_width;
+
+  if (padding_data->padding() == "VALID")
+  {
+    output_height = (input_height + stride_height - effective_window_height) / stride_height;
+    output_width = (input_width + stride_width - effective_window_width) / stride_width;
+  }
+  else if (padding_data->padding() == "SAME")
+  {
+    output_height = (input_height + stride_height - 1) / stride_height;
+    output_width = (input_width + stride_width - 1) / stride_width;
+  }
+  else
+    throw std::runtime_error("Not supported padding type in FixShapeTransform MaxPool2D");
+
+  loco::FeatureShape ofm_feature_shape;
+  ofm_feature_shape.count() = ifm_feature_shape.count();
+  ofm_feature_shape.height() = output_height;
+  ofm_feature_shape.width() = output_width;
+  ofm_feature_shape.depth() = ifm_feature_shape.depth();
+
+  auto shape_data = stdex::make_unique<ShapeInferenceData>();
+  shape_data->feature_shape(ofm_feature_shape);
+  node->annot(std::move(shape_data));
+
+  LOGGER(fixshape_maxpool2d);
+  INFO(fixshape_maxpool2d) << "Fix MaxPool2D shape = ifm(" << ifm_feature_shape.count().value()
+                           << "," << ifm_feature_shape.height().value() << ","
+                           << ifm_feature_shape.width().value() << ","
+                           << ifm_feature_shape.depth().value() << ") --> ofm("
+                           << ofm_feature_shape.count().value() << ","
+                           << ofm_feature_shape.height().value() << ","
+                           << ofm_feature_shape.width().value() << ","
+                           << ofm_feature_shape.depth().value() << ")" << std::endl;
+  return true;
 }
 
 bool fix_shape(loco::Pull *node)