Commit 21ddd4a5 authored by Adam Rogowiec's avatar Adam Rogowiec Committed by Michał Karzyński

[ONNX] DepthToSpace operator. (#2342)

parent 10c2a7fd
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
set(ONNX_OPSET_VERSION 9 CACHE INTERNAL "Supported version of ONNX operator set") set(ONNX_OPSET_VERSION 9 CACHE INTERNAL "Supported version of ONNX operator set")
add_library(onnx_import_interface OBJECT add_library(onnx_import_interface OBJECT
onnx.cpp
onnx.hpp
core/operator_set.hpp
core/node.cpp core/node.cpp
core/node.hpp core/node.hpp
core/weight.hpp) core/operator_set.hpp
core/weight.hpp
onnx.cpp
onnx.hpp)
add_library(onnx_import STATIC add_library(onnx_import STATIC
core/attribute.cpp core/attribute.cpp
...@@ -63,6 +63,8 @@ add_library(onnx_import STATIC ...@@ -63,6 +63,8 @@ add_library(onnx_import STATIC
op/conv.hpp op/conv.hpp
op/conv_transpose.cpp op/conv_transpose.cpp
op/conv_transpose.hpp op/conv_transpose.hpp
op/depth_to_space.cpp
op/depth_to_space.hpp
op/div.hpp op/div.hpp
op/elu.cpp op/elu.cpp
op/elu.hpp op/elu.hpp
......
//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************
#include <cstddef>
#include <cstdint>
#include <memory>
#include "depth_to_space.hpp"
#include "exceptions.hpp"
#include "ngraph/node.hpp"
#include "ngraph/shape.hpp"
#include "utils/reshape.hpp"
namespace ngraph
{
namespace onnx_import
{
namespace op
{
namespace set_1
{
NodeVector depth_to_space(const Node& node)
{
auto data = node.get_ng_inputs().at(0);
const Shape& data_shape = data->get_shape();
std::int64_t block_size{node.get_attribute_value<std::int64_t>("blocksize")};
// Set default values to each dimension to be able to work with both 3D or 4D data.
std::size_t n{1}, c{1}, h{1}, w{1};
ASSERT_VALID_ARGUMENT(node, (data_shape.size() == 3 || data_shape.size() == 4))
<< "The provided tensor shape: " << data_shape << " is not supported.";
// Assume NCHW data layout
if (data_shape.size() == 4)
{
n = data_shape.at(0);
c = data_shape.at(1);
h = data_shape.at(2);
w = data_shape.at(3);
}
// Without batch.
else if (data_shape.size() == 3)
{
c = data_shape.at(0);
h = data_shape.at(1);
w = data_shape.at(2);
}
ASSERT_VALID_ARGUMENT(node,
(c % (block_size * block_size) == 0 && block_size > 0))
<< "The depth axis size must be a multiple of squared block_size attribute "
"value";
std::size_t bs = static_cast<std::size_t>(block_size);
std::size_t c_flat = c / (bs * bs);
// First we have to disperse the data from depth channel, then rearrange them
// so as appropriate chunks of data where close to their destination place.
// Finally squeeze data from respective dimensions.
std::shared_ptr<ngraph::Node> flat_node =
reshape::reshape(data, ngraph::Shape{n, bs, bs, c_flat, h, w});
flat_node = reshape::reorder_axes(flat_node, {0, 3, 4, 1, 5, 2});
return {reshape::reshape(flat_node, ngraph::Shape{n, c_flat, h * bs, w * bs})};
}
} // namespace set_1
} //namespace op
} // namespace onnx_import
} // namespace ngraph
//*****************************************************************************
// Copyright 2017-2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************
#pragma once
#include "core/node.hpp"
#include "ngraph/node_vector.hpp"
namespace ngraph
{
namespace onnx_import
{
namespace op
{
namespace set_1
{
/// \brief Permutes input tensor data from depth into blocks of spatial data.
///
/// \note Values from the depth dimension (assuming NCHW layout) are moved in
/// spatial blocks to the height and width dimensions.
///
/// \param[in] node The ONNX input node describing operation.
///
/// \return NodeVector containing Tensor with shape:
/// [N, C/(blocksize * blocksize), H * blocksize, W * blocksize]
NodeVector depth_to_space(const Node& node);
} // namespace set_1
} //namespace op
} // namespace onnx_import
} // namespace ngraph
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "op/conv.hpp" #include "op/conv.hpp"
#include "op/conv_transpose.hpp" #include "op/conv_transpose.hpp"
#include "op/cos.hpp" #include "op/cos.hpp"
#include "op/depth_to_space.hpp"
#include "op/div.hpp" #include "op/div.hpp"
#include "op/elu.hpp" #include "op/elu.hpp"
#include "op/equal.hpp" #include "op/equal.hpp"
...@@ -206,6 +207,7 @@ namespace ngraph ...@@ -206,6 +207,7 @@ namespace ngraph
REGISTER_OPERATOR("Conv", 1, conv); REGISTER_OPERATOR("Conv", 1, conv);
REGISTER_OPERATOR("ConvTranspose", 1, conv_transpose); REGISTER_OPERATOR("ConvTranspose", 1, conv_transpose);
REGISTER_OPERATOR("Cos", 1, cos); REGISTER_OPERATOR("Cos", 1, cos);
REGISTER_OPERATOR("DepthToSpace", 1, depth_to_space);
REGISTER_OPERATOR("Div", 1, div); REGISTER_OPERATOR("Div", 1, div);
REGISTER_OPERATOR("Div", 7, div); REGISTER_OPERATOR("Div", 7, div);
REGISTER_OPERATOR("Dropout", 1, identity); REGISTER_OPERATOR("Dropout", 1, identity);
......
ONNXNgraphImporter:q
&
AB" DepthToSpace*
blocksize compute_graphZ
A




b
B




B
\ No newline at end of file
ONNXNgraphImporter:q
&
AB" DepthToSpace*
blocksize compute_graphZ
A




b
B




B
\ No newline at end of file
ONNXNgraphImporter:i
&
AB" DepthToSpace*
blocksize compute_graphZ
A



b
B



B
\ No newline at end of file
ONNXNgraphImporter:_

AB" DepthToSpace compute_graphZ
A




b
B




B
\ No newline at end of file
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <iterator> #include <iterator>
#include <limits> #include <limits>
#include <sstream> #include <sstream>
#include <stdexcept>
#include <vector> #include <vector>
#include "gtest/gtest.h" #include "gtest/gtest.h"
...@@ -1713,6 +1714,55 @@ TEST(onnx_${BACKEND_NAME}, is_op_supported) ...@@ -1713,6 +1714,55 @@ TEST(onnx_${BACKEND_NAME}, is_op_supported)
EXPECT_TRUE(onnx_import::is_operator_supported("AddQ", 1, "com.intel.ai")); EXPECT_TRUE(onnx_import::is_operator_supported("AddQ", 1, "com.intel.ai"));
} }
TEST(onnx_${BACKEND_NAME}, model_depth_to_space)
{
auto function = onnx_import::import_onnx_model(
file_util::path_join(SERIALIZED_ZOO, "onnx/depth_to_space.onnx"));
Inputs inputs;
inputs.emplace_back(std::vector<float>{
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f});
Outputs expected_output{std::vector<float>{
0.f, 4.f, 1.f, 5.f, 8.f, 12.f, 9.f, 13.f, 2.f, 6.f, 3.f, 7.f, 10.f, 14.f, 11.f, 15.f}};
Outputs outputs{execute(function, inputs, "${BACKEND_NAME}")};
EXPECT_TRUE(test::all_close_f(expected_output.front(), outputs.front()));
}
TEST(onnx_${BACKEND_NAME}, model_depth_to_space_chw)
{
auto function = onnx_import::import_onnx_model(
file_util::path_join(SERIALIZED_ZOO, "onnx/depth_to_space_chw.onnx"));
Inputs inputs;
inputs.emplace_back(std::vector<float>{
0.f, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f, 13.f, 14.f, 15.f});
Outputs expected_output{std::vector<float>{
0.f, 4.f, 1.f, 5.f, 8.f, 12.f, 9.f, 13.f, 2.f, 6.f, 3.f, 7.f, 10.f, 14.f, 11.f, 15.f}};
Outputs outputs{execute(function, inputs, "${BACKEND_NAME}")};
EXPECT_TRUE(test::all_close_f(expected_output.front(), outputs.front()));
}
TEST(onnx_${BACKEND_NAME}, model_depth_to_space_bad_blocksize)
{
// This model fails to import since the depth channel length must be a multiple of the
// `blocksize` attribute value.
EXPECT_THROW(onnx_import::import_onnx_model(file_util::path_join(
SERIALIZED_ZOO, "onnx/depth_to_space_bad_blocksize.onnx")),
std::runtime_error);
}
TEST(onnx_${BACKEND_NAME}, model_depth_to_space_no_blocksize)
{
// This model fails to import since it lacks of required parameter `blocksize`.
EXPECT_THROW(onnx_import::import_onnx_model(
file_util::path_join(SERIALIZED_ZOO, "onnx/depth_to_space_no_blocksize.onnx")),
std::runtime_error);
}
TEST(onnx_${BACKEND_NAME}, model_space_to_depth) TEST(onnx_${BACKEND_NAME}, model_space_to_depth)
{ {
auto function = onnx_import::import_onnx_model( auto function = onnx_import::import_onnx_model(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment