[exo/tflite] Support FeatureBiasAdd (#4229)
author박종현/On-Device Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Fri, 12 Jul 2019 07:57:58 +0000 (16:57 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 12 Jul 2019 07:57:58 +0000 (16:57 +0900)
T/F Lite exporter now accepts FeatureBiasAdd node.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/exo-tflite/src/OperationExporter.cpp
contrib/exo-tflite/src/TypeInference.cpp

index 301e4f1..247ca05 100644 (file)
@@ -261,6 +261,19 @@ void exportBiasAdd(loco::BiasAdd<loco::Domain::Tensor> *node, FlatBufferBuilder
   gd._operators.push_back(op_offset);
 }
 
+void exportBiasAdd(loco::FeatureBiasAdd *node, FlatBufferBuilder &builder, SerializedModelData &gd)
+{
+  uint32_t op_idx = gd.registerBuiltinOpcode(tflite::BuiltinOperator_ADD);
+  std::vector<int32_t> inputs_vec{get_tensor_index(node->value()), get_tensor_index(node->bias())};
+  std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
+  auto inputs = builder.CreateVector(inputs_vec);
+  auto outputs = builder.CreateVector(outputs_vec);
+  auto options = CreateAddOptions(builder); // dummy option
+  auto op_offset = CreateOperator(builder, op_idx, inputs, outputs,
+                                  tflite::BuiltinOptions_AddOptions, options.Union());
+  gd._operators.push_back(op_offset);
+}
+
 /// @brief Export CONCATENATION of **TWO** tensors only
 void exportConcat(loco::TensorConcat *node, FlatBufferBuilder &builder, SerializedModelData &gd)
 {
@@ -331,6 +344,10 @@ void exportNode(loco::Node *node, flatbuffers::FlatBufferBuilder &builder,
   {
     exportBiasAdd(biasadd, builder, data);
   }
+  else if (auto *biasadd = dynamic_cast<loco::FeatureBiasAdd *>(node))
+  {
+    exportBiasAdd(biasadd, builder, data);
+  }
   else
   {
     assert(false && "unsupported node found");
index 1cb3da7..fdf6034 100644 (file)
@@ -138,7 +138,8 @@ tflite::TensorType getOpResultType(loco::BiasEncode *node, TypeContext &gd)
   return gd._node_to_type[node->input()];
 }
 
-tflite::TensorType getOpResultType(loco::BiasAdd<loco::Domain::Tensor> *node, TypeContext &gd)
+template <loco::Domain D>
+tflite::TensorType getOpResultType(loco::BiasAdd<D> *node, TypeContext &gd)
 {
   tflite::TensorType value_type = gd._node_to_type[node->value()];
   tflite::TensorType bias_type = gd._node_to_type[node->bias()];
@@ -193,6 +194,7 @@ public:
   NODE(TensorConcat)
   NODE(BiasEncode)
   NODE(TensorBiasAdd)
+  NODE(FeatureBiasAdd)
 #undef NODE
 
 private:
@@ -574,6 +576,22 @@ ShapeDescription getOpResultShape(loco::BiasAdd<loco::Domain::Tensor> *node, Sha
   return value_shape;
 }
 
+// TODO Reduce code duplication
+ShapeDescription getOpResultShape(loco::FeatureBiasAdd *node, ShapeContext &gd)
+{
+  const ShapeDescription &value_shape = gd._node_to_shape[node->value()];
+  const ShapeDescription &bias_shape = gd._node_to_shape[node->bias()];
+
+  // Bias should be rank 1
+  assert(bias_shape._dims.size() == 1);
+
+  // Channel count coherency for proper broadcast
+  // Feature in T/F Lite uses NHWC layout
+  assert(bias_shape._dims[0] == value_shape._dims[3]);
+
+  return value_shape;
+}
+
 namespace
 {
 
@@ -618,6 +636,7 @@ public:
   NODE(TensorConcat)
   NODE(BiasEncode)
   NODE(TensorBiasAdd)
+  NODE(FeatureBiasAdd)
 #undef NODE
 
 private: