[ONNX] Add support for standard ONNX GroupNormalization (#20694)

* Add support for ONNX GroupNormalization

* Enable onnx compliance tests

* Add f to the test values to avoid cast warning

* Use tolerance as fp instead of bits
This commit is contained in:
Katarzyna Mitrus 2023-10-27 07:24:07 +02:00 committed by GitHub
parent b06a0010ea
commit 14d51de93c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 427 additions and 4 deletions

View File

@ -565,9 +565,7 @@ tests_expected_to_fail = [
),
(
xfail_issue_99955,
"OnnxBackendNodeModelTest.test_group_normalization_epsilon_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_epsilon_expanded_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_example_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_example_expanded_cpu",
),
(

View File

@ -0,0 +1,46 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "op/group_normalization.hpp"
#include "default_opset.hpp"
OPENVINO_SUPPRESS_DEPRECATED_START
namespace ngraph {
namespace onnx_import {
namespace op {
namespace set_1 {
OutputVector group_normalization(const Node& node) {
const auto data = node.get_ng_inputs().at(0); // Shape [N, C, ...]
auto scale = node.get_ng_inputs().at(1); // Shape [num_groups]
auto bias = node.get_ng_inputs().at(2); // Shape [num_groups]
auto eps = node.get_attribute_value<float>("epsilon", 1e-05f);
auto num_groups = node.get_attribute_value<int64_t>("num_groups");
auto zero = default_opset::Constant::create(element::i64, Shape{1}, {0});
auto one = default_opset::Constant::create(element::i64, Shape{1}, {1});
auto c_dim = std::make_shared<default_opset::Gather>(std::make_shared<default_opset::ShapeOf>(data), one, zero);
auto g_dim = default_opset::Constant::create(element::i64, Shape{1}, {num_groups});
auto c_g_div = std::make_shared<default_opset::Divide>(c_dim, g_dim);
// Adjust scale and bias shape, [G] -> [G, C/G] -> [C]
scale = std::make_shared<default_opset::Unsqueeze>(scale, one);
auto broadcast_scale =
std::make_shared<default_opset::Broadcast>(scale, c_g_div, ov::op::BroadcastType::BIDIRECTIONAL);
auto c_scale = std::make_shared<default_opset::Reshape>(broadcast_scale, c_dim, false);
bias = std::make_shared<default_opset::Unsqueeze>(bias, one);
auto broadcast_bias =
std::make_shared<default_opset::Broadcast>(bias, c_g_div, ov::op::BroadcastType::BIDIRECTIONAL);
auto c_bias = std::make_shared<default_opset::Reshape>(broadcast_bias, c_dim, false);
return {std::make_shared<default_opset::GroupNormalization>(data, c_scale, c_bias, num_groups, eps)};
}
} // namespace set_1
} // namespace op
} // namespace onnx_import
} // namespace ngraph
OPENVINO_SUPPRESS_DEPRECATED_END

View File

@ -0,0 +1,23 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/core/deprecated.hpp"
OPENVINO_SUPPRESS_DEPRECATED_START
#include "ngraph/node.hpp"
#include "onnx_import/core/node.hpp"
namespace ngraph {
namespace onnx_import {
namespace op {
namespace set_1 {
OutputVector group_normalization(const Node& node);
} // namespace set_1
} // namespace op
} // namespace onnx_import
} // namespace ngraph
OPENVINO_SUPPRESS_DEPRECATED_END

View File

@ -75,6 +75,7 @@
#include "op/global_max_pool.hpp"
#include "op/greater.hpp"
#include "op/grid_sample.hpp"
#include "op/group_normalization.hpp"
#include "op/gru.hpp"
#include "op/hammingwindow.hpp"
#include "op/hannwindow.hpp"
@ -395,6 +396,7 @@ OperatorsBridge::OperatorsBridge() {
REGISTER_OPERATOR("GlobalMaxPool", 1, global_max_pool);
REGISTER_OPERATOR("Greater", 1, greater);
REGISTER_OPERATOR("GridSample", 1, grid_sample);
REGISTER_OPERATOR("GroupNormalization", 1, group_normalization);
REGISTER_OPERATOR("GRU", 1, gru);
REGISTER_OPERATOR("HannWindow", 1, hannwindow);
REGISTER_OPERATOR("HammingWindow", 1, hammingwindow);

View File

@ -0,0 +1,91 @@
ir_version: 8
producer_name: "onnx-frontend-test"
graph {
node {
input: "x"
input: "scale"
input: "bias"
output: "Y"
op_type: "GroupNormalization"
attribute {
name: "num_groups"
i: 2
type: INT
}
}
name: "test-model-group-normalization"
input {
name: "x"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 4
}
dim {
dim_value: 2
}
dim {
dim_value: 3
}
}
}
}
}
input {
name: "scale"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
}
}
}
}
input {
name: "bias"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
}
}
}
}
output {
name: "Y"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 1
}
dim {
dim_value: 4
}
dim {
dim_value: 2
}
dim {
dim_value: 3
}
}
}
}
}
}
opset_import {
domain: ""
version: 18
}

View File

@ -0,0 +1,91 @@
ir_version: 9
opset_import {
domain: ""
version: 18
}
producer_name: "onnx-frontend-test"
graph {
node {
input: "x"
input: "scale"
input: "bias"
output: "Y"
op_type: "GroupNormalization"
attribute {
name: "num_groups"
type: INT
i: 3
}
}
name: "test-model-group-normalization"
input {
name: "x"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 6
}
dim {
dim_value: 2
}
dim {
dim_value: 2
}
}
}
}
}
input {
name: "scale"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
}
}
}
}
input {
name: "bias"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
}
}
}
}
output {
name: "Y"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 6
}
dim {
dim_value: 2
}
dim {
dim_value: 2
}
}
}
}
}
}

View File

@ -0,0 +1,96 @@
ir_version: 9
opset_import {
domain: ""
version: 18
}
producer_name: "onnx-frontend-test"
graph {
node {
input: "x"
input: "scale"
input: "bias"
output: "Y"
op_type: "GroupNormalization"
attribute {
name: "epsilon"
type: FLOAT
f: 0.0001
}
attribute {
name: "num_groups"
type: INT
i: 3
}
}
name: "test-model-group-normalization"
input {
name: "x"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 6
}
dim {
dim_value: 2
}
dim {
dim_value: 2
}
}
}
}
}
input {
name: "scale"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
}
}
}
}
input {
name: "bias"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 3
}
}
}
}
}
output {
name: "Y"
type {
tensor_type {
elem_type: 1
shape {
dim {
dim_value: 2
}
dim {
dim_value: 6
}
dim {
dim_value: 2
}
dim {
dim_value: 2
}
}
}
}
}
}

View File

@ -6884,3 +6884,81 @@ OPENVINO_TEST(${BACKEND_NAME}, onnx_model_hannwindow_symmetric) {
test_case.run_with_tolerance_as_fp(0.01f);
}
}
OPENVINO_TEST(${BACKEND_NAME}, onnx_group_normalization_3grp_default_eps) {
auto function = onnx_import::import_onnx_model(file_util::path_join(ov::test::utils::getExecutableDirectory(),
SERIALIZED_ZOO,
"onnx/group_normalization_3grp.onnx"));
auto test_case = ov::test::TestCase(function, s_device);
test_case.add_input<float>(
{-0.2261407f, -1.8793484f, -0.37692875f, 0.8860143f, 0.05993791f, -0.7634332f, 0.61080337f, 0.09776749f,
0.5835062f, -0.32338685f, -0.23485906f, -0.04752525f, 2.4905143f, -0.11199934f, -0.20539412f, -2.4455426f,
-0.5437323f, 0.51794696f, -0.44127423f, 0.09666952f, -0.09539367f, -1.962784f, 0.25065672f, 1.5909688f,
0.927671f, -0.46812922f, 0.2925484f, -1.1766007f, 0.7675745f, -0.94145614f, 1.1552521f, 1.6375796f,
0.0198675f, -0.45938072f, 0.43037328f, 0.37999842f, -0.45021877f, -0.84925014f, 1.6790043f, -1.0172538f,
0.0493111f, -0.53391f, -0.08101435f, 0.14738432f, -0.58910686f, 0.51673824f, -1.7001126f, -1.888597f});
test_case.add_input<float>({2.4556813f, 0.12371606f, 1.5681714f});
test_case.add_input<float>({0.79260737f, -0.74518913f, 1.370796f});
test_case.add_expected_output<float>(
Shape{2, 6, 2, 2},
{0.70938545f, -4.3442307f, 0.24844825f, 4.109082f, 1.5838864f, -0.93303996f, 3.267802f, 1.6995258f,
-0.6843487f, -0.7732928f, -0.76461035f, -0.7462375f, -0.49731785f, -0.75256085f, -0.7617206f, -0.9814244f,
0.5922366f, 2.3495553f, 0.76182777f, 1.652246f, 1.3343381f, -1.7566144f, 1.9071295f, 4.1256485f,
2.4563973f, -1.0979934f, 0.8390641f, -2.9021082f, 2.0487132f, -2.3033152f, 3.03593f, 4.2641716f,
-0.73710674f, -0.80988204f, -0.6747702f, -0.6824198f, -0.8084908f, -0.86908495f, -0.48516175f, -0.8945968f,
2.4475086f, 1.3245938f, 2.1965842f, 2.6363354f, 1.2183195f, 3.3474774f, -0.92077446f, -1.2836761f});
test_case.run_with_tolerance_as_fp(0.000001f);
}
OPENVINO_TEST(${BACKEND_NAME}, onnx_group_normalization_3grp_custom_eps) {
auto function = onnx_import::import_onnx_model(file_util::path_join(ov::test::utils::getExecutableDirectory(),
SERIALIZED_ZOO,
"onnx/group_normalization_custom_eps.onnx"));
auto test_case = ov::test::TestCase(function, s_device);
test_case.add_input<float>(
{1.8079232f, -0.2892469f, 2.0915377f, -1.8837914f, 0.25869793f, 0.80542284f, 2.9528935f, 0.16081251f,
0.10507602f, -1.7271832f, -1.0217364f, -1.1528395f, -0.69146425f, -2.4292548f, -0.4232518f, 0.33357796f,
-1.4946569f, -0.08947915f, -0.7962127f, 1.3765403f, -0.1947846f, 0.30173305f, 0.08576944f, 0.8134404f,
0.62960416f, -1.0745901f, -0.27037576f, -0.3607608f, 0.14347585f, 1.4590056f, -1.1309915f, 0.88850766f,
0.5367185f, -0.7771955f, 0.81048864f, 0.45839247f, 1.0398412f, -0.21019235f, -1.037122f, -0.36852306f,
2.7608335f, 0.3126114f, 0.336343f, 0.76919895f, 0.58595645f, 0.71894723f, -1.2922621f, -0.542859f});
test_case.add_input<float>({-0.05215209f, -0.5643389f, -0.6959881f});
test_case.add_input<float>({1.4327786f, 0.01641126f, -1.471873f});
test_case.add_expected_output<float>(
Shape{2, 6, 2, 2},
{1.3937842f, 1.4702199f, 1.3834473f, 1.5283363f, 1.4502488f, 1.4303224f, 1.3520534f, 1.4538165f,
-0.628196f, 0.5758153f, 0.11225323f, 0.19840352f, -0.10477467f, 1.0371594f, -0.281022f, -0.77834874f,
-0.22489226f, -1.3969909f, -0.8074844f, -2.6198394f, -1.3091526f, -1.7233121f, -1.5431708f, -2.1501417f,
1.3968898f, 1.4998344f, 1.4512546f, 1.4567144f, 1.4262552f, 1.3467885f, 1.5032414f, 1.3812504f,
-0.36344206f, 0.6759755f, -0.58001745f, -0.30147952f, -0.7614548f, 0.22742787f, 0.8815994f, 0.35268092f,
-2.9372354f, -1.3806448f, -1.3957335f, -1.6709452f, -1.5544388f, -1.6389949f, -0.36025894f, -0.83673286f});
test_case.run_with_tolerance_as_fp(0.000001f);
}
OPENVINO_TEST(${BACKEND_NAME}, onnx_group_normalization_2grp_custom_eps) {
auto function = onnx_import::import_onnx_model(file_util::path_join(ov::test::utils::getExecutableDirectory(),
SERIALIZED_ZOO,
"onnx/group_normalization_2grp.onnx"));
auto test_case = ov::test::TestCase(function, s_device);
test_case.add_input<float>({-0.424049f, 1.7215315f, 1.429421f, 0.52730036f, 2.0628972f, -0.15856522f,
2.274094f, -1.9989003f, -1.7827071f, -0.87104136f, -1.2995626f, 0.16800839f,
0.5934625f, 1.553442f, -0.5482905f, 0.6079124f, 0.3598974f, -0.15221423f,
1.1135519f, -1.2533926f, -1.019778f, -1.9142767f, -1.2984604f, 0.5587884f});
test_case.add_input<float>({-1.4678609f, -1.8223071f});
test_case.add_input<float>({1.1155374f, -0.6101201f});
test_case.add_expected_output<float>(
Shape{1, 4, 2, 3},
{1.694167f, -0.51719165f, -0.21612573f, 0.71365166f, -0.86902285f, 1.4205441f, -1.0866947f, 3.3172996f,
3.0944781f, 2.154863f, 2.5965219f, 1.0839586f, -1.8562672f, -3.540983f, 0.14745194f, -1.8816261f,
-1.4463723f, -0.547642f, -2.768998f, 1.3848708f, 0.97488886f, 2.5446892f, 1.4639623f, -1.7954159f});
test_case.run_with_tolerance_as_fp(0.000001f);
}

View File

@ -437,9 +437,7 @@ tests_expected_to_fail = [
),
(
xfail_issue_99955,
"OnnxBackendNodeModelTest.test_group_normalization_epsilon_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_epsilon_expanded_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_example_cpu",
"OnnxBackendNodeModelTest.test_group_normalization_example_expanded_cpu",
),
(