From: Павел Ильютченко/AI Tools Lab /SRR/Engineer/삼성전자
Date: Tue, 18 Dec 2018 13:57:06 +0000 (+0300)
Subject: [nnc] Support Transpose operation on TFLite importer (#2716)
X-Git-Tag: nncc_backup~1045
X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=eee47629c84320f2edddf6279ca1df8cd959d8f4;p=platform%2Fcore%2Fml%2Fnnfw.git
[nnc] Support Transpose operation on TFLite importer (#2716)
* Support TransposeOp on TFLite importer
* Add const where needed in TFLite op creator
Signed-off-by: Pavel Iliutchenko
---
diff --git a/contrib/nnc/passes/tflite_frontend/tflite_importer.cpp b/contrib/nnc/passes/tflite_frontend/tflite_importer.cpp
index de667b5..218a138 100644
--- a/contrib/nnc/passes/tflite_frontend/tflite_importer.cpp
+++ b/contrib/nnc/passes/tflite_frontend/tflite_importer.cpp
@@ -107,6 +107,7 @@ void TfliteImporter::processUnsupportedOp(const Operator* op) {
case BuiltinOperator_TANH:
case BuiltinOperator_RELU:
case BuiltinOperator_RELU6:
+ case BuiltinOperator_TRANSPOSE:
// No checks
break;
default:
@@ -186,7 +187,8 @@ void TfliteImporter::walkOperator(const Operator* op) {
op->builtin_options_as());
break;
case BuiltinOperator_RESHAPE:
- outputs = _opCreator->convertReshape(inputs, params, op->builtin_options_as());
+ outputs = _opCreator->convertReshape(
+ inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_RESIZE_NEAREST_NEIGHBOR:
outputs = _opCreator->convertResizeNN(inputs, params,
@@ -197,17 +199,19 @@ void TfliteImporter::walkOperator(const Operator* op) {
op->builtin_options_as());
break;
case BuiltinOperator_FULLY_CONNECTED:
- outputs = _opCreator->convertFullyConnected(inputs, params,
- op->builtin_options_as());
+ outputs = _opCreator->convertFullyConnected(
+ inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_SOFTMAX:
- outputs = _opCreator->createSoftmax(inputs, params, op->builtin_options_as());
+ outputs = _opCreator->createSoftmax(
+ inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_SLICE:
outputs = _opCreator->createSlice(inputs, params, op->builtin_options_as_SliceOptions());
break;
case BuiltinOperator_SQUEEZE:
- outputs = _opCreator->createSqueeze(inputs, params, op->builtin_options_as());
+ outputs = _opCreator->createSqueeze(
+ inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_LOGISTIC:
outputs = _opCreator->createLogistic(inputs, params);
@@ -225,7 +229,8 @@ void TfliteImporter::walkOperator(const Operator* op) {
outputs = _opCreator->createDiv(inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_MAXIMUM:
- outputs = _opCreator->createMax(inputs, params, op->builtin_options_as());
+ outputs = _opCreator->createMax(
+ inputs, params, op->builtin_options_as());
break;
case BuiltinOperator_TRANSPOSE_CONV:
outputs = _opCreator->createTransposeConv(
@@ -243,6 +248,10 @@ void TfliteImporter::walkOperator(const Operator* op) {
case BuiltinOperator_RELU6:
outputs = _opCreator->createActivation(inputs, params, ActivationFunctionType_RELU6);
break;
+ case BuiltinOperator_TRANSPOSE:
+ outputs = _opCreator->createTranspose(
+ inputs, params, op->builtin_options_as());
+ break;
default:
assert(false && "All unsupported types should have been found before this pass.");
}
diff --git a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp
index 488a47b..5ddf15e 100644
--- a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp
+++ b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp
@@ -31,13 +31,13 @@
#include "core/modelIR/operations/ReluOp.h"
#include "core/modelIR/operations/ReshapeOp.h"
#include "core/modelIR/operations/ResizeOp.h"
-#include "core/modelIR/operations/ScaleOp.h"
#include "core/modelIR/operations/SigmoidOp.h"
#include "core/modelIR/operations/SliceOp.h"
#include "core/modelIR/operations/SoftmaxOp.h"
#include "core/modelIR/operations/SqrtOp.h"
#include "core/modelIR/operations/SqueezeOp.h"
#include "core/modelIR/operations/TanhOp.h"
+#include "core/modelIR/operations/TransposeOp.h"
#include "pass/PassException.h"
@@ -84,8 +84,9 @@ void TFLiteOpCreator::checkConv2D(const Conv2DOptions* opts,
checkActivationType(opts->fused_activation_function(), problems_op_set);
}
-std::vector TFLiteOpCreator::convertConv2D(InputOps& inputs, InputParams& params,
- const Conv2DOptions* opts) {
+std::vector
+TFLiteOpCreator::convertConv2D(InputOps& inputs, const InputParams& params,
+ const Conv2DOptions* opts) {
const auto& input_shape = inputs[0]->getOutputShape(0);
const auto& kernel_shape = params[0].getShape();
Shape strides{opts->stride_h(), opts->stride_w()};
@@ -107,7 +108,7 @@ void TFLiteOpCreator::checkDepthwiseConv2D(const DepthwiseConv2DOptions* opts,
}
std::vector
-TFLiteOpCreator::convertDepthwiseConv2D(InputOps& inputs, InputParams& params,
+TFLiteOpCreator::convertDepthwiseConv2D(InputOps& inputs, const InputParams& params,
const DepthwiseConv2DOptions* opts) {
const auto& input_shape = inputs[0]->getOutputShape(0);
const auto& kernel_shape = params[0].getShape();
@@ -130,9 +131,9 @@ void TFLiteOpCreator::checkConcatenation(const ConcatenationOptions* opts,
checkActivationType(opts->fused_activation_function(), problems_op_set);
}
-std::vector TFLiteOpCreator::convertConcatenation(InputOps& inputs,
- InputParams& params,
- const ConcatenationOptions* opts) {
+std::vector
+TFLiteOpCreator::convertConcatenation(InputOps& inputs, const InputParams& params,
+ const ConcatenationOptions* opts) {
std::vector descriptors;
for (auto i : inputs)
descriptors.push_back(i->getOutput(0));
@@ -145,8 +146,9 @@ void TFLiteOpCreator::checkPool2D(const Pool2DOptions* opts,
checkActivationType(opts->fused_activation_function(), problems_op_set);
}
-std::vector TFLiteOpCreator::convertMaxPool2D(InputOps& inputs, InputParams& params,
- const Pool2DOptions* opts) {
+std::vector
+TFLiteOpCreator::convertMaxPool2D(InputOps& inputs, const InputParams& params,
+ const Pool2DOptions* opts) {
auto& input_shape = inputs[0]->getOutputShape(0);
Shape window_shape{opts->filter_height(), opts->filter_width()};
Shape strides{opts->stride_h(), opts->stride_w()};
@@ -163,7 +165,7 @@ std::vector TFLiteOpCreator::convertMaxPool2D(InputOps& inputs,
}
std::vector TFLiteOpCreator::convertAveragePool2D(InputOps& inputs,
- InputParams& params,
+ const InputParams& params,
const Pool2DOptions* opts) {
auto& input_shape = inputs[0]->getOutputShape(0);
Shape window_shape{opts->filter_height(), opts->filter_width()};
@@ -180,8 +182,9 @@ std::vector TFLiteOpCreator::convertAveragePool2D(InputOps& inp
ops::PoolOp::RoundMode::floor);
}
-std::vector TFLiteOpCreator::createSoftmax(InputOps& inputs, InputParams& params,
- const SoftmaxOptions* opts) {
+std::vector
+TFLiteOpCreator::createSoftmax(InputOps& inputs, const InputParams& params,
+ const SoftmaxOptions* opts) {
// Softmax in TFLite is always 2-D.
assert(inputs[0]->getOutputShape(0).rank() == 2);
int32_t axis = 1;
@@ -197,8 +200,9 @@ Shape shapeFromTensor(mir::Tensor&& t) {
return temporary_shape;
}
-std::vector TFLiteOpCreator::createSlice(InputOps& inputs, InputParams& params,
- const ::tflite::SliceOptions*) {
+std::vector
+TFLiteOpCreator::createSlice(InputOps& inputs, const InputParams& params,
+ const ::tflite::SliceOptions*) {
auto starts = shapeFromTensor(mir::Tensor(params[0]));
auto sizes = shapeFromTensor(mir::Tensor(params[1]));
assert(starts.rank() == inputs[0]->getOutputShape(0).rank() &&
@@ -207,8 +211,9 @@ std::vector TFLiteOpCreator::createSlice(InputOps& inputs, Inpu
starts, sizes);
}
-std::vector TFLiteOpCreator::convertReshape(InputOps& inputs, InputParams& params,
- const ReshapeOptions* opts) {
+std::vector
+TFLiteOpCreator::convertReshape(InputOps& inputs, const InputParams& params,
+ const ReshapeOptions* opts) {
// TODO: we should also support "-1" values in new_shape, which means that correct
// shape values must be calculated. Better do it in the shape inference module.
Shape new_shape = ShapeHelper::createShape(*opts->new_shape(), opts->new_shape()->size());
@@ -218,7 +223,7 @@ std::vector TFLiteOpCreator::convertReshape(InputOps& inputs, I
}
std::vector
-TFLiteOpCreator::createTransposeConv(InputOps& inputs, InputParams& params,
+TFLiteOpCreator::createTransposeConv(InputOps& inputs, const InputParams& params,
const ::tflite::TransposeConvOptions* opts) {
Shape strides{opts->stride_h(), opts->stride_w(), 1};
return createOp(ActivationFunctionType_NONE, inputs[0]->getOutput(0), params[1],
@@ -226,7 +231,7 @@ TFLiteOpCreator::createTransposeConv(InputOps& inputs, InputParams& params,
}
std::vector
-TFLiteOpCreator::convertResizeNN(InputOps& inputs, InputParams& params,
+TFLiteOpCreator::convertResizeNN(InputOps& inputs, const InputParams& params,
const ::tflite::ResizeNearestNeighborOptions* opts) {
// TODO support aligned corners
assert(!opts->align_corners() && "Aligned corners not currently supported");
@@ -278,7 +283,8 @@ TFLiteOpCreator::createMul(InputOps& inputs, const InputParams& params,
}
std::vector
-TFLiteOpCreator::createDiv(InputOps& inputs, InputParams&, const ::tflite::DivOptions* opts) {
+TFLiteOpCreator::createDiv(InputOps& inputs, const InputParams&,
+ const ::tflite::DivOptions* opts) {
std::vector descriptors;
for (auto i : inputs)
descriptors.push_back(i->getOutput(0));
@@ -287,7 +293,7 @@ TFLiteOpCreator::createDiv(InputOps& inputs, InputParams&, const ::tflite::DivOp
}
std::vector
-TFLiteOpCreator::createMax(InputOps& inputs, InputParams&,
+TFLiteOpCreator::createMax(InputOps& inputs, const InputParams&,
const ::tflite::MaximumMinimumOptions* opts) {
std::vector descriptors;
for (auto i : inputs)
@@ -296,9 +302,10 @@ TFLiteOpCreator::createMax(InputOps& inputs, InputParams&,
ops::ElementwiseOp::OpType::max);
}
-std::vector TFLiteOpCreator::convertReducer(InputOps& inputs, InputParams& params,
- ops::ReduceFOp::FuncType ft,
- const ::tflite::ReducerOptions* opts) {
+std::vector
+TFLiteOpCreator::convertReducer(InputOps& inputs, const InputParams& params,
+ ops::ReduceFOp::FuncType ft,
+ const ::tflite::ReducerOptions* opts) {
assert(params.at(0).getShape().rank() <= 1 && "Must be 1-dim or 0-dim tensor");
mir::Tensor tensor(params.at(0));
std::vector axes;
@@ -321,7 +328,7 @@ void TFLiteOpCreator::checkFullyConnected(const FullyConnectedOptions* opts,
std::vector
TFLiteOpCreator::convertFullyConnected(InputOps& inputs,
- InputParams& params,
+ const InputParams& params,
const FullyConnectedOptions* opts) {
// Add Reshape operation to make sure the input for FC operation has shape [1, fc_input_size]
int32_t fc_input_size = params[0].getShape().dim(0);
@@ -371,7 +378,7 @@ mir::Operation* TFLiteOpCreator::addFusedActivation(mir::Operation* input,
}
std::vector TFLiteOpCreator::createSqueeze(
- InputOps& inputs, InputParams& params, const ::tflite::SqueezeOptions* opts) {
+ InputOps& inputs, const InputParams& params, const ::tflite::SqueezeOptions* opts) {
std::vector squeeze_dims{opts->squeeze_dims()->begin(), opts->squeeze_dims()->end()};
@@ -379,8 +386,11 @@ std::vector TFLiteOpCreator::createSqueeze(
squeeze_dims);
}
-std::vector TFLiteOpCreator::createPad(InputOps& inputs, InputParams& params,
- const ::tflite::PadOptions *opts) {
+
+std::vector
+TFLiteOpCreator::createPad(InputOps& inputs, const InputParams& params,
+ const ::tflite::PadOptions *opts) {
+
assert(params.size() == 1); // support pad with one param
std::vector> paddings;
@@ -404,20 +414,38 @@ std::vector TFLiteOpCreator::createPad(InputOps& inputs, InputP
}
std::vector
-TFLiteOpCreator::createActivation(InputOps& inputs, InputParams&,
+TFLiteOpCreator::createActivation(InputOps& inputs, const InputParams&,
const ::tflite::ActivationFunctionType activationType) {
assert(inputs.size() == 1);
return {addFusedActivation(inputs[0], activationType)};
}
std::vector
-TFLiteOpCreator::createSqrt(InputOps& inputs, InputParams&) {
+TFLiteOpCreator::createSqrt(InputOps& inputs, const InputParams&) {
return createOp(ActivationFunctionType_NONE, inputs[0]->getOutput(0));
}
std::vector
-TFLiteOpCreator::createLogistic(InputOps& inputs, InputParams&) {
+TFLiteOpCreator::createLogistic(InputOps& inputs, const InputParams&) {
return createOp(ActivationFunctionType_NONE, inputs[0]->getOutput(0));
}
+std::vector
+TFLiteOpCreator::createTranspose(InputOps& inputs, const InputParams& params,
+ const ::tflite::TransposeOptions*) {
+
+ assert(params.size() == 1);
+ std::vector axis_order;
+
+ mir::Tensor permutation_tensor(params[0]);
+
+ ShapeRange range(permutation_tensor.getShape());
+ for (const auto& index : range) {
+ axis_order.push_back(permutation_tensor.at(index));
+ }
+
+ return createOp(ActivationFunctionType_NONE,
+ inputs[0]->getOutput(0), axis_order);
+}
+
} // namespace nnc
diff --git a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.h b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.h
index 3ae321a..38b4bea 100644
--- a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.h
+++ b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.h
@@ -47,62 +47,69 @@ public:
explicit TFLiteOpCreator(Graph* g) : _graph(g) {}
- std::vector convertConv2D(InputOps&, InputParams&, const ::tflite::Conv2DOptions*);
+ std::vector convertConv2D(InputOps&, const InputParams&,
+ const ::tflite::Conv2DOptions*);
- std::vector convertDepthwiseConv2D(InputOps&, InputParams&,
+ std::vector convertDepthwiseConv2D(InputOps&, const InputParams&,
const ::tflite::DepthwiseConv2DOptions*);
- std::vector convertConcatenation(InputOps&, InputParams&,
+ std::vector convertConcatenation(InputOps&, const InputParams&,
const ::tflite::ConcatenationOptions*);
- std::vector convertMaxPool2D(InputOps&, InputParams&,
+ std::vector convertMaxPool2D(InputOps&, const InputParams&,
const ::tflite::Pool2DOptions*);
- std::vector convertAveragePool2D(InputOps&, InputParams&,
+ std::vector convertAveragePool2D(InputOps&, const InputParams&,
const ::tflite::Pool2DOptions*);
- std::vector convertReducer(InputOps&, InputParams&, ops::ReduceFOp::FuncType,
- const ::tflite::ReducerOptions*);
+ std::vector convertReducer(InputOps&, const InputParams&,
+ ops::ReduceFOp::FuncType,
+ const ::tflite::ReducerOptions*);
- std::vector createSoftmax(InputOps&, InputParams&, const ::tflite::SoftmaxOptions*);
+ std::vector createSoftmax(InputOps&, const InputParams&,
+ const ::tflite::SoftmaxOptions*);
- std::vector createSlice(InputOps&, InputParams&, const ::tflite::SliceOptions*);
+ std::vector createSlice(InputOps&, const InputParams&,
+ const ::tflite::SliceOptions*);
- std::vector convertReshape(InputOps&, InputParams&,
+ std::vector convertReshape(InputOps&, const InputParams&,
const ::tflite::ReshapeOptions*);
- std::vector convertFullyConnected(InputOps&, InputParams&,
+ std::vector convertFullyConnected(InputOps&, const InputParams&,
const ::tflite::FullyConnectedOptions*);
- std::vector convertResizeNN(InputOps&, InputParams&,
+ std::vector convertResizeNN(InputOps&, const InputParams&,
const ::tflite::ResizeNearestNeighborOptions*);
- std::vector createLogistic(InputOps& inputs, InputParams& params);
+ std::vector createLogistic(InputOps& inputs, const InputParams& params);
- std::vector createSqrt(InputOps& inputs, InputParams& params);
+ std::vector createSqrt(InputOps& inputs, const InputParams& params);
- std::vector createSqueeze(InputOps& inputs, InputParams& params,
+ std::vector createSqueeze(InputOps& inputs, const InputParams& params,
const ::tflite::SqueezeOptions* opts);
/** @brief Elementwise Add */
- std::vector createAdd(InputOps&, const InputParams&, const ::tflite::AddOptions*);
+ std::vector createAdd(InputOps&, const InputParams&,
+ const ::tflite::AddOptions*);
/** @brief Elementwise product */
- std::vector createMul(InputOps&, const InputParams&, const ::tflite::MulOptions*);
+ std::vector createMul(InputOps&, const InputParams&,
+ const ::tflite::MulOptions*);
/** @brief Elementwise maximum */
- std::vector createMax(InputOps&, InputParams&, const ::tflite::MaximumMinimumOptions*);
+ std::vector createMax(InputOps&, const InputParams&,
+ const ::tflite::MaximumMinimumOptions*);
/** @brief Elementwise division */
- std::vector createDiv(InputOps&, InputParams&, const ::tflite::DivOptions*);
+ std::vector createDiv(InputOps&, const InputParams&,
+ const ::tflite::DivOptions*);
/// @brief Free-standing ( non-fused ) activation function based on tflite activation
- std::vector createActivation(InputOps&, InputParams&,
+ std::vector createActivation(InputOps&, const InputParams&,
const ::tflite::ActivationFunctionType);
/**
* @brief Creates a Transposed convolution
* @param params 0 - output shape (unused), 1 - kernel, 2- input
*/
- std::vector createTransposeConv(
- InputOps&, InputParams&,
- const ::tflite::TransposeConvOptions*);
+ std::vector createTransposeConv(InputOps&, const InputParams&,
+ const ::tflite::TransposeConvOptions*);
/**
* @brief Create a Pad operation
@@ -111,9 +118,19 @@ public:
* @param opts TFLite PadOptions
* @return Operations vector
*/
- std::vector createPad(InputOps& inputs, InputParams& params,
+ std::vector createPad(InputOps&, const InputParams&,
const ::tflite::PadOptions* opts);
+ /**
+ * @brief Create a Transpose operation
+ * @param inputs Operations vector
+ * @param params Tensor with axis order
+ * @param opts TFLite TransposeOptions
+ * @return Operations vector
+ */
+ std::vector createTranspose(InputOps&, const InputParams&,
+ const ::tflite::TransposeOptions*);
+
void checkPool2D(const ::tflite::Pool2DOptions*, std::set&);
void checkConcatenation(const ::tflite::ConcatenationOptions*, std::set&);