[enco/frontend] Add AvgPool2DGraphBuilder for tflite frontend (#2249)
author윤현식/동작제어Lab(SR)/Principal Engineer/삼성전자 <hyunsik.yoon@samsung.com>
Tue, 13 Nov 2018 10:14:37 +0000 (19:14 +0900)
committer박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Tue, 13 Nov 2018 10:14:37 +0000 (19:14 +0900)
* [enco/frontend] Add AvgPool2DGraphBuilder for tflite frontend

AvgPool2DGraphBuilder was added for tflite frontend.

Signed-off-by: Hyun Sik Yoon <hyunsik.yoon@samsung.com>
* Divisor , assert for fused activation

* tensorflow -> tensorflow lite

contrib/enco/frontend/tflite/src/Frontend.cpp

index 8e77697..0f74f14 100644 (file)
@@ -554,6 +554,89 @@ void Conv2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContext *
 }
 
 /**
+ * @brief GraphBuilder for AvgPool2D operator
+ */
+class AvgPool2DGraphBuilder : public GraphBuilder
+{
+public:
+  void build(const tflite::Operator *op, GraphBuilderContext *) const override;
+};
+
+void AvgPool2DGraphBuilder::build(const tflite::Operator *op, GraphBuilderContext *_context) const
+{
+  assert(_context != nullptr); // check if init(..) is called
+
+  coco::Module *m = _context->m();
+  coco::Block *blk = _context->block();
+  TensorContext &tensor_context = _context->tensor();
+  TensorBags &bags = _context->bags();
+
+  tflimport::IndexVector opinputs = tflimport::as_index_vector(op->inputs());
+  tflimport::IndexVector opoutputs = tflimport::as_index_vector(op->outputs());
+
+  // these are fixed in tflite
+  // input index 0 : input feature
+  // ouout index 0 : output feature
+  assert(opinputs.size() == 1);
+  assert(opoutputs.size() == 1);
+
+  int ifm_idx = opinputs.at(0);
+  int ofm_idx = opoutputs.at(0);
+
+  const tensor::Shape &ifm_shape = tensor_context.shape(ifm_idx);
+  const tensor::Shape &ofm_shape = tensor_context.shape(ofm_idx);
+
+  // Create an object for an input feature map
+  coco::FeatureObject *ifm_obj = m->entity()->object()->create<coco::FeatureObject>();
+  coco::Bag *ifm_bag = bags.bag(ifm_idx);
+  ifm_obj->bag(ifm_bag);
+  ifm_obj->layout(coco::FeatureLayouts::BHWC::create(as_feature_shape(ifm_shape)));
+
+  // Create an object for an output feature map
+  coco::FeatureObject *ofm_obj = m->entity()->object()->create<coco::FeatureObject>();
+  coco::Bag *ofm_bag = bags.bag(ofm_idx);
+  ofm_obj->bag(ofm_bag);
+  ofm_obj->layout(coco::FeatureLayouts::BHWC::create(as_feature_shape(ofm_shape)));
+
+  // Create a Load op
+  auto coco_load = op_builder(m).load(ifm_obj).pop();
+
+  // Create a AvgPool2D
+  auto coco_avgpool2d = m->entity()->op()->create<coco::AvgPool2D>();
+  auto *params = op->builtin_options_as_Pool2DOptions();
+
+  // NOTE For Tensorflow lite, PaddingExcluded is needed
+  coco_avgpool2d->divisor(coco::AvgPool2D::Divisor::PaddingExcluded);
+
+  coco_avgpool2d->window()->height(params->filter_height());
+  coco_avgpool2d->window()->width(params->filter_width());
+
+  coco_avgpool2d->stride()->vertical(params->stride_h());
+  coco_avgpool2d->stride()->horizontal(params->stride_w());
+
+  coco::Padding2D padding =
+      pool2D_padding(params, ifm_shape, params->filter_width(), params->filter_height());
+
+  coco_avgpool2d->pad()->top(padding.top());
+  coco_avgpool2d->pad()->bottom(padding.bottom());
+  coco_avgpool2d->pad()->left(padding.left());
+  coco_avgpool2d->pad()->right(padding.right());
+
+  // Link ops
+  coco_avgpool2d->arg(coco_load);
+
+  // Create an Eval instruction
+  auto ins = instr_builder(m).eval(ofm_obj, coco_avgpool2d);
+
+  // Append the instruction to the block
+  blk->instr()->append(ins);
+
+  // TODO activation, e.g., relu
+  assert(params->fused_activation_function() ==
+         tflite::ActivationFunctionType::ActivationFunctionType_NONE);
+}
+
+/**
  * @brief Class to return graph builder for passed tflite::builtinOperator
  */
 class GraphBuilderRegistry