Random Uniform MO implementation (#6694)

* Added RandomUniform operation.

* Conflicts fix.

* Fix conflicts.

* Fix conflicts.

* Added ONNX extractor, fixed FP16 conversion, added double implementation.

* int32, int64 types.

* Added initial type attribute.

* Added extractors for MxNet and TF for RandomUniformInt.

* Fixed ChangeRandomUniformOutputType transformation.

* Corrected ONNX, MxNetextractors.

* Fixed extender.

* Code style corrected, updated BOM file.

* Small correction.

* Code reformat.

* Fixed type check.

* Small corrections, code style.

* Added RandomUniform tests to manifest file.

* Include fixed.

* Code style.

* Small corrections.

* Tests fixed.

* Manifest file updated.

* Removed initial type attribute.

* Small correction.

* Fixed problem with Const types change.

* Update ngraph/core/include/ngraph/op/random_uniform.hpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update ngraph/core/src/op/random_uniform.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Update ngraph/core/src/op/random_uniform.cpp

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>

* Applied comments to shell implementation.

* Applied comments to shell implementation.

* Moved shell and reference to separate PR.

* Moved shell and reference to separate PR.

* Corrected comments, code refactoring.

* Fixed seed attributes.

* Corrected mxnet extractor.

* Returned RandomUniform onnx extractor.

* Small fix.

* Used generator in tests, fixed input ports count in AttributedRandomUniform.

* Temporarily added DropoutWithRandomUniformReplacer and debug output.

* Temporarily added DropoutWithRandomUniformReplacer and debug output.

* Temporarily added DropoutWithRandomUniformReplacer and debug output.

* Temporarily added DropoutWithRandomUniformReplacer and debug output.

* Moved DropoutWithRandomUniformReplacer to ngraph, removed debug output.

* Fixed wrong change.

* Fixed wrong change.

* Added check that RandomUniform is in ShapeOf subgraph.

* Added layer tests, updated supported operations list.

* Small correction.

* Fix conflicts.

* Fix conflicts.

* Small fix.

* Used const for not changing values.

* Apply suggestions from code review

Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>

* Added IR check in layer tests.

* Fixed error.

* Fixed test.

* Update inference-engine/src/transformations/include/transformations/common_optimizations/dropout_with_random_uniform_replacer.hpp

Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>

* Removed ShapeOf and Mul from DropoutWithRandomUniformReplacer.

* Replaced register_new_node with make_shared.

* Added fp16 test.

* Extended for RandomUniform->Convert case.

* Used modf().

* Removed modf().

* Update inference-engine/src/transformations/src/transformations/common_optimizations/dropout_with_random_uniform_replacer.cpp

Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>

* Added negative tests, added nullptr check for add_const_value.

Co-authored-by: Ilya Churaev <ilyachur@gmail.com>
Co-authored-by: Gleb Kazantaev <gleb.nnstu@gmail.com>
This commit is contained in:
Anastasia Popova 2021-09-14 21:26:57 +03:00 committed by GitHub
parent fda3f5d237
commit cf48792134
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 1020 additions and 154 deletions

View File

@ -67,6 +67,7 @@ Standard MXNet\* symbols:
| _minus_scalar | No |
| _mul_scalar | No |
| _plus_scalar | No |
| _random_uniform | Operation provides sequence from uniform distribution, but exact values won't match. |
| _rnn_param_concat | No |
| _arange | No |
| _contrib_AdaptiveAvgPooling2D | Converted to the Average Pooling with fixed paddings |
@ -272,6 +273,8 @@ Standard TensorFlow\* operations:
| PlaceholderWithDefault | No |
| Prod | No |
| QueueDequeueUpToV2 | Supported only when it is part of a sub-graph of the special form |
| RandomUniform | No |
| RandomUniformInt | No |
| Range | No |
| Rank | No |
| RealDiv | No |
@ -568,6 +571,7 @@ Standard ONNX\* operators:
| RNN | No |
| ROIAlign | No |
| Range | No |
| RandomUniform | Operation provides sequence from uniform distribution, but exact values won't match. |
| Reciprocal | No |
| ReduceL1 | No |
| ReduceL2 | No |

View File

@ -0,0 +1,41 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ngraph/pass/graph_rewrite.hpp>
#include <transformations_visibility.hpp>
namespace ngraph {
namespace pass {
class TRANSFORMATIONS_API DropoutWithRandomUniformReplacer;
} // namespace pass
} // namespace ngraph
/**
* @ingroup ie_transformation_common_api
* @brief This transformation replaces possible Dropout block (in inference mode) with RandomUniform
* to Broadcast of half-ones in a sub-graph.
*
* Dropout block:
* RandomUniform ----------> Add ---> Floor
* /\ /\ /\
* | | |
* Const(0) Const(1) Const(1)
* min_val max_val
*
* Resulted block:
* Broadcast -------> Add ---> Floor
* /\ /\
* | |
* Const(0.5) Const(1)
*
*/
class ngraph::pass::DropoutWithRandomUniformReplacer : public ngraph::pass::MatcherPass {
public:
NGRAPH_RTTI_DECLARATION;
DropoutWithRandomUniformReplacer();
};

View File

@ -14,6 +14,7 @@
#include "transformations/common_optimizations/fq_reshape_fusion.hpp"
#include "transformations/common_optimizations/gelu_fusion.hpp"
#include "transformations/common_optimizations/depth_to_space_fusion.hpp"
#include "transformations/common_optimizations/dropout_with_random_uniform_replacer.hpp"
#include "transformations/common_optimizations/optimize_strided_slice.hpp"
#include "transformations/common_optimizations/softplus_fusion.hpp"
#include "transformations/common_optimizations/softplus_to_mish_fusion.hpp"
@ -169,6 +170,7 @@ bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr<ngraph::
decomp->add_matcher<ngraph::pass::SimplifyCTCGreedyDecoderSeqLen>();
decomp->add_matcher<ngraph::pass::EinsumDecomposition>();
decomp->add_matcher<ngraph::pass::GatherNegativeConstIndicesNormalize>();
decomp->add_matcher<ngraph::pass::DropoutWithRandomUniformReplacer>();
decomp->set_name("ngraph::pass::CommonDecompositions");
// CF is required after all decompositions

View File

@ -0,0 +1,82 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "transformations/common_optimizations/dropout_with_random_uniform_replacer.hpp"
#include <memory>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/pattern/op/or.hpp>
#include <ngraph/pattern/op/wrap_type.hpp>
#include <ngraph/rt_info.hpp>
#include <openvino/pass/pattern/op/or.hpp>
#include "itt.hpp"
#include "transformations/utils/utils.hpp"
NGRAPH_RTTI_DEFINITION(ngraph::pass::DropoutWithRandomUniformReplacer, "DropoutWithRandomUniformReplacer", 0);
ngraph::pass::DropoutWithRandomUniformReplacer::DropoutWithRandomUniformReplacer() {
MATCHER_SCOPE(DropoutWithRandomUniformReplacer);
const auto shape_pattern = ngraph::pattern::any_input();
const auto ru_min_const_pattern = ngraph::pattern::wrap_type<opset8::Constant>();
const auto ru_max_const_pattern = ngraph::pattern::wrap_type<opset8::Constant>();
const auto random_uniform_pattern =
ngraph::pattern::wrap_type<opset8::RandomUniform>({shape_pattern, ru_min_const_pattern, ru_max_const_pattern},
pattern::consumers_count(1));
const auto convert_pattern = ngraph::pattern::wrap_type<opset8::Convert>({random_uniform_pattern});
const auto add_const_pattern = ngraph::pattern::wrap_type<opset8::Constant>();
const auto convert_or_random_uniform_pattern =
std::make_shared<pattern::op::Or>(OutputVector{convert_pattern, random_uniform_pattern});
const auto add_pattern =
ngraph::pattern::wrap_type<opset8::Add>({convert_or_random_uniform_pattern, add_const_pattern});
const auto floor_pattern = ngraph::pattern::wrap_type<opset8::Floor>({add_pattern});
ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) {
const auto& pattern_map = m.get_pattern_value_map();
const auto random_uniform = pattern_map.at(random_uniform_pattern);
const auto shape_of = pattern_map.at(shape_pattern);
const auto ru = std::dynamic_pointer_cast<opset8::RandomUniform>(random_uniform.get_node_shared_ptr());
if (!ru)
return false;
if (!ru->get_out_type().is_real())
return false;
auto min_const_value =
std::dynamic_pointer_cast<opset8::Constant>(pattern_map.at(ru_min_const_pattern).get_node_shared_ptr());
auto max_const_value =
std::dynamic_pointer_cast<opset8::Constant>(pattern_map.at(ru_max_const_pattern).get_node_shared_ptr());
auto add_const_value =
std::dynamic_pointer_cast<opset8::Constant>(pattern_map.at(add_const_pattern).get_node_shared_ptr());
bool valid_constant_values = op::util::has_constant_value<double>(min_const_value, 0.0) &&
op::util::has_constant_value<double>(max_const_value, 1.0);
if (!valid_constant_values)
return false;
if (!add_const_value)
return false;
auto add_const_vector = add_const_value->cast_vector<double>();
if (add_const_vector.size() > 1)
return false;
// Add const should have zero fractional part
if (add_const_vector[0] - std::round(add_const_vector[0]) != 0.0)
return false;
const auto broadcast_const = opset8::Constant::create(ru->get_out_type(), Shape{}, {0.5});
const auto broadcast = std::make_shared<opset8::Broadcast>(broadcast_const, shape_of);
broadcast->set_friendly_name(ru->get_friendly_name());
copy_runtime_info(ru, broadcast);
ngraph::replace_node(ru, broadcast);
return true;
};
auto m = std::make_shared<ngraph::pattern::Matcher>(floor_pattern, matcher_name);
this->register_matcher(m, callback);
}

View File

@ -0,0 +1,375 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include <memory>
#include <ngraph/function.hpp>
#include <ngraph/opsets/opset8.hpp>
#include <ngraph/pass/manager.hpp>
#include <string>
#include <transformations/common_optimizations/dropout_with_random_uniform_replacer.hpp>
#include <transformations/init_node_info.hpp>
#include "common_test_utils/ngraph_test_utils.hpp"
using namespace testing;
TEST(TransformationTests, DropoutWithRandomUniformReplacerCase1) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {30.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto broadcast_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.5});
auto broadcast = std::make_shared<ngraph::opset8::Broadcast>(broadcast_const, input);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {30.0});
auto add = std::make_shared<ngraph::opset8::Add>(broadcast, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerCase2) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f16,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto broadcast_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {0.5});
auto broadcast = std::make_shared<ngraph::opset8::Broadcast>(broadcast_const, input);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(broadcast, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerWithConvert) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto convert = std::make_shared<ngraph::opset8::Convert>(ru, ngraph::element::f16);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(convert, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto broadcast_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.5});
auto broadcast = std::make_shared<ngraph::opset8::Broadcast>(broadcast_const, input);
auto convert = std::make_shared<ngraph::opset8::Convert>(broadcast, ngraph::element::f16);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f16, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(convert, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerAddConstNegative) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.5});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.5});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerNonFloatRUNegative) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {100});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::i32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {10});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {100});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::i32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::i32, ngraph::Shape{}, {10});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerInvalidMinNegative) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-2.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {-2.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerInvalidMaxNegative) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.5});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.5});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}
TEST(TransformationTests, DropoutWithRandomUniformReplacerInvalidAddConstRankNegative) {
std::shared_ptr<ngraph::Function> f(nullptr), f_ref(nullptr);
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, {1.0, 2.0, 3.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
ngraph::pass::Manager manager;
manager.register_pass<ngraph::pass::InitNodeInfo>();
manager.register_pass<ngraph::pass::DropoutWithRandomUniformReplacer>();
manager.run_passes(f);
ASSERT_NO_THROW(check_rt_info(f));
}
{
auto input = std::make_shared<ngraph::opset8::Parameter>(ngraph::element::i32, ngraph::Shape{3});
auto min_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {0.0});
auto max_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{}, {1.0});
auto ru = std::make_shared<ngraph::opset8::RandomUniform>(input,
min_const,
max_const,
ngraph::element::f32,
100,
200);
auto add_const = ngraph::opset8::Constant::create(ngraph::element::f32, ngraph::Shape{3}, {1.0, 2.0, 3.0});
auto add = std::make_shared<ngraph::opset8::Add>(ru, add_const);
auto floor = std::make_shared<ngraph::opset8::Floor>(add);
f_ref = std::make_shared<ngraph::Function>(ngraph::NodeVector{floor}, ngraph::ParameterVector{input});
}
auto res = compare_functions(f, f_ref);
ASSERT_TRUE(res.first) << res.second;
}

View File

@ -12,6 +12,7 @@ extensions/back/AvgPool.py
extensions/back/blob_normalizer.py
extensions/back/CellNormalizer.py
extensions/back/ChangeOutputTypeAttributes.py
extensions/back/ChangeRandomUniformOutputType.py
extensions/back/ClampNormalizer.py
extensions/back/compress_quantized_weights.py
extensions/back/ConvolutionNormalizer.py
@ -67,6 +68,7 @@ extensions/front/ATenToEmbeddingBag.py
extensions/front/AttributedClampNormalizer.py
extensions/front/AttributedGatherNormalizer.py
extensions/front/AttributedPadToPad.py
extensions/front/AttributedRandomUniformToRandomUniform.py
extensions/front/AttributedRollToRoll.py
extensions/front/binary_quantize_normalization.py
extensions/front/broadcast_with_range.py
@ -125,7 +127,6 @@ extensions/front/ChangePlaceholderTypes.py
extensions/front/create_tensor_nodes.py
extensions/front/disable_weights_quantize_value_propagation.py
extensions/front/div.py
extensions/front/DropoutWithRandomUniformReplacer.py
extensions/front/eltwise_n.py
extensions/front/ExpandDimsToUnsqueeze.py
extensions/front/FillToBroadcast.py
@ -211,6 +212,7 @@ extensions/front/mxnet/pad_ext.py
extensions/front/mxnet/pooling_ext.py
extensions/front/mxnet/proposal_ext.py
extensions/front/mxnet/psroi_pooling_ext.py
extensions/front/mxnet/random_uniform_ext.py
extensions/front/mxnet/repeat_ext.py
extensions/front/mxnet/reshape_ext.py
extensions/front/mxnet/RNN_ext.py
@ -319,6 +321,7 @@ extensions/front/onnx/priorgridgenerator_ext.py
extensions/front/onnx/proposal_ext.py
extensions/front/onnx/quantize_ext.py
extensions/front/onnx/quantize_linear_ext.py
extensions/front/onnx/random_uniform_ext.py
extensions/front/onnx/range_ext.py
extensions/front/onnx/reduce_ext.py
extensions/front/onnx/reshape_ext.py
@ -460,6 +463,8 @@ extensions/front/tf/placeholder_ext.py
extensions/front/tf/placeholder_with_default_ext.py
extensions/front/tf/pooling_ext.py
extensions/front/tf/prelu.py
extensions/front/tf/random_uniform_ext.py
extensions/front/tf/random_uniform_int_ext.py
extensions/front/tf/range_ext.py
extensions/front/tf/reduce_ext.py
extensions/front/tf/reshape_related_ext.py
@ -727,6 +732,7 @@ extensions/ops/proposal_onnx.py
extensions/ops/proposal_python_example.py
extensions/ops/psroipooling.py
extensions/ops/quantize_linear.py
extensions/ops/random_uniform.py
extensions/ops/range.py
extensions/ops/rank.py
extensions/ops/ReduceOps.py
@ -829,7 +835,6 @@ mo/front/common/partial_infer/elemental.py
mo/front/common/partial_infer/eltwise.py
mo/front/common/partial_infer/multi_box_detection.py
mo/front/common/partial_infer/multi_box_prior.py
mo/front/common/partial_infer/random_uniform.py
mo/front/common/partial_infer/roipooling.py
mo/front/common/partial_infer/utils.py
mo/front/common/register_custom_ops.py
@ -912,7 +917,6 @@ mo/front/tf/extractors/fused_bn.py
mo/front/tf/extractors/identity.py
mo/front/tf/extractors/native_tf.py
mo/front/tf/extractors/pack.py
mo/front/tf/extractors/random_uniform.py
mo/front/tf/extractors/strided_slice.py
mo/front/tf/extractors/subgraph_utils.py
mo/front/tf/extractors/utils.py
@ -1049,6 +1053,7 @@ mo/utils/ir_reader/extenders/parameter_extender.py
mo/utils/ir_reader/extenders/pooling_extender.py
mo/utils/ir_reader/extenders/priorbox_clustered_extender.py
mo/utils/ir_reader/extenders/priorbox_extender.py
mo/utils/ir_reader/extenders/random_uniform_extender.py
mo/utils/ir_reader/extenders/range_extender.py
mo/utils/ir_reader/extenders/reorg_yolo_extender.py
mo/utils/ir_reader/extenders/RNNCell_extender.py

View File

@ -0,0 +1,44 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.ops.Cast import Cast
from mo.back.replacement import BackReplacementPattern
from mo.graph.graph import Graph
from mo.middle.passes.convert_data_type import data_type_str_to_np
class ChangeRandomUniformOutputType(BackReplacementPattern):
"""
This transformation adds Cast to IR data_type after RandomUniform operation
when RandomUniform output type is not equal to IR data_type and RandomUniform output type
is floating point type.
'output_type' attribute determines the generation algorithm of RandomUniform, so output numbers
generated for different values of 'output_type' may not be equal. For this reason 'output_type'
attribute shouldn't be changed for matching of inference results. So in cases when we need
to change the data type of RandomUniform we need to insert Cast node after RandomUniform.
"""
enabled = True
force_shape_inference = True
def run_after(self):
from extensions.back.MarkNodesWithShapeValues import MarkNodesWithShapeValues
return [MarkNodesWithShapeValues]
def run_before(self):
return []
def find_and_replace_pattern(self, graph: Graph):
ir_data_type = data_type_str_to_np(graph.graph['cmd_params'].data_type)
for node in graph.get_op_nodes(op='RandomUniform'):
assert node.has_valid('output_type')
if node.has_and_set('returns_shape_value'):
continue
if node.output_type != ir_data_type and np.issubdtype(node.output_type, np.floating):
node_name = node.soft_get('name', node.id)
convert_node = Cast(graph, {'name': node_name + "/cast", 'dst_type': ir_data_type}).create_node()
node.out_port(0).get_connection().insert_node(convert_node)

View File

@ -0,0 +1,56 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.ops.random_uniform import RandomUniform
from mo.front.common.replacement import FrontReplacementPattern
from mo.front.tf.graph_utils import create_op_with_const_inputs
from mo.graph.graph import Graph, rename_nodes
from mo.utils.error import Error
class AttributedRandomUniformToRandomUniform(FrontReplacementPattern):
"""
This transformation converts AttributedRandomUniform operation (output shape, min value and max value
can be specified as attribute) to RandomUniform operation (Inference Engine semantic).
"""
enabled = True
def find_and_replace_pattern(self, graph: Graph):
for attr_random_uniform in graph.get_op_nodes(op='AttributedRandomUniform'):
original_name = attr_random_uniform.soft_get('name', attr_random_uniform.id)
if not attr_random_uniform.has_valid('output_type'):
raise Error("RandomUniform should have valid ''output_type'' attribute.")
output_type = attr_random_uniform.soft_get('output_type')
if attr_random_uniform.has_valid('min_val'):
min_val = attr_random_uniform['min_val']
else:
min_val = output_type(0)
if attr_random_uniform.has_valid('max_val'):
max_val = attr_random_uniform['max_val']
else:
max_val = output_type(1)
port_value_dict = {1: min_val, 2: max_val}
if not attr_random_uniform.has_port('in', 0) or attr_random_uniform.in_port(0).disconnected():
if not attr_random_uniform.has_valid('shape'):
raise Error("RandomUniform should have valid ''shape'' attribute or input node on 0 port.")
else:
port_value_dict.update({0: attr_random_uniform.shape})
attrs = {'global_seed': attr_random_uniform.soft_get('global_seed', 0), 'op_seed': attr_random_uniform.soft_get('op_seed', 0),
'output_type': output_type}
new_random_uniform = create_op_with_const_inputs(graph, op=RandomUniform, port_value_dict=port_value_dict,
op_attrs=attrs)
rename_nodes([(attr_random_uniform, original_name + '/to_be_removed'), (new_random_uniform, original_name)])
attr_random_uniform.out_port(0).get_connection().set_source(new_random_uniform.out_port(0))
if new_random_uniform.in_port(0).disconnected():
if attr_random_uniform.in_port(0).disconnected():
raise Error('RandomUniform should have input node on 0 port.')
else:
new_random_uniform.in_port(0).connect(attr_random_uniform.in_port(0).get_connection().get_source())
graph.remove_node(attr_random_uniform.id)

View File

@ -1,73 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import logging as log
import numpy as np
from mo.front.common.replacement import FrontReplacementSubgraph
from mo.front.tf.graph_utils import create_op_with_const_inputs
from mo.graph.graph import Graph, Node, rename_nodes
from mo.middle.pattern_match import check_value
from mo.ops.broadcast import Broadcast
class DropoutWithRandomUniformReplacer(FrontReplacementSubgraph):
r"""
This transformation replaces possible Dropout block (in inference mode) with RandomUniform
to Broadcast of half-ones in a sub-graph.
WARNING: the transformation can be triggered for other block with RandomUniform by mistake,
i.e. replace the detected sub-graph to functionally non-equivalent sub-graph
Dropout block:
ShapeOf -> RandomUniform -> Mul ---> Add ---> Add -> Floor
/\
|
Const(0)
Resulted block:
ShapeOf --> Broadcast --> Mul ---> Add ---> Add -> Floor
/\ /\
| |
Const(0.5) Const(0)
"""
enabled = True
@staticmethod
def pattern(**kwargs):
return dict(
nodes=[
('shape', dict(op='ShapeOf')),
('random_uniform', dict(op='RandomUniform')),
('mul', dict(op='Mul')),
('add_const', dict(op='Const', value=lambda v: check_value(v, lambda x: np.allclose(x, 0.0, atol=0)))),
('add', dict(op='Add')),
('add2', dict(op='Add')),
('floor', dict(op='Floor')),
],
edges=[
('shape', 'random_uniform'),
('random_uniform', 'mul'),
('mul', 'add', {'in': 0}),
('add_const', 'add', {'in': 1}),
('add', 'add2'),
('add2', 'floor'),
]
)
@staticmethod
def replace_sub_graph(graph: Graph, match: dict, **kwargs):
random_uniform_node = match['random_uniform']
random_uniform_node_name = random_uniform_node.soft_get('name', random_uniform_node.id)
log.error("Possible dropout block with RandomUniform is detected. "
"Replace {} with a Broadcast with constant value of 0.5 "
"assuming that it is executed in inference mode.".format(random_uniform_node_name),
extra={'is_warning': True})
data_type = match['add_const'].data_type
broadcast_node = create_op_with_const_inputs(graph, Broadcast,
{0: np.array([0.5], dtype=data_type)},
{'mode': 'numpy',
'name': random_uniform_node_name + '/Broadcast'})
rename_nodes([(random_uniform_node, random_uniform_node_name + '/ToBeRemoved'),
(broadcast_node, random_uniform_node_name)])
random_uniform_node.in_port(0).get_connection().set_destination(broadcast_node.in_port(1))
random_uniform_node.out_port(0).get_connection().set_source(broadcast_node.out_port(0))

View File

@ -0,0 +1,24 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from extensions.ops.random_uniform import AttributedRandomUniform
from mo.front.extractor import FrontExtractorOp
from mo.front.mxnet.extractors.utils import get_mxnet_layer_attrs
class RandomUniformExtractor(FrontExtractorOp):
op = '_random_uniform'
enabled = True
@classmethod
def extract(cls, node):
attrs = get_mxnet_layer_attrs(node.symbol_dict)
shape = list(attrs.tuple("shape", int, None))
high = attrs.float("high", 1.0)
low = attrs.float("low", 0.0)
out_type = attrs.dtype("dtype", np.float32)
new_attrs = {'shape': shape, 'min_val': out_type(low), 'max_val': out_type(high), 'output_type': out_type}
AttributedRandomUniform.update_node_stat(node, new_attrs)
return cls.enabled

View File

@ -0,0 +1,27 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.ops.random_uniform import AttributedRandomUniform
from mo.front.common.partial_infer.utils import int64_array
from mo.front.extractor import FrontExtractorOp
from mo.front.onnx.extractors.utils import onnx_attr, get_onnx_datatype_as_numpy
from mo.graph.graph import Node
class RandomUniformFrontExtractor(FrontExtractorOp):
op = 'RandomUniform'
enabled = True
@classmethod
def extract(cls, node: Node):
shape = onnx_attr(node, 'shape', 'ints', default=None, dst_type=int64_array)
out_type = get_onnx_datatype_as_numpy(onnx_attr(node, 'dtype', 'i', default=1))
seed = onnx_attr(node, 'seed', 'f', default=0.0)
min_val = onnx_attr(node, 'low', 'f', default=0.0)
max_val = onnx_attr(node, 'high', 'f', default=1.0)
AttributedRandomUniform.update_node_stat(node, {'shape': shape,
'output_type': out_type,
'seed': seed,
'min_val': out_type(min_val),
'max_val': out_type(max_val)})
return cls.enabled

View File

@ -0,0 +1,21 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.ops.random_uniform import AttributedRandomUniform
from mo.front.extractor import FrontExtractorOp
from mo.front.tf.extractors.utils import tf_dtype_extractor
class RandomUniformExtractor(FrontExtractorOp):
op = 'RandomUniform'
enabled = True
@classmethod
def extract(cls, node):
attrs = {
'output_type': tf_dtype_extractor(node.pb.attr["dtype"].type),
'global_seed': node.pb.attr['seed'].i,
'op_seed': node.pb.attr['seed2'].i
}
AttributedRandomUniform.update_node_stat(node, attrs)
return cls.enabled

View File

@ -0,0 +1,21 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from extensions.ops.random_uniform import RandomUniform
from mo.front.extractor import FrontExtractorOp
from mo.front.tf.extractors.utils import tf_dtype_extractor
class RandomUniformIntExtractor(FrontExtractorOp):
op = 'RandomUniformInt'
enabled = True
@classmethod
def extract(cls, node):
attrs = {
'output_type': tf_dtype_extractor(node.pb.attr["Tout"].type),
'global_seed': node.pb.attr['seed'].i,
'op_seed': node.pb.attr['seed2'].i
}
RandomUniform.update_node_stat(node, attrs)
return cls.enabled

View File

@ -0,0 +1,75 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
from mo.graph.graph import Graph, Node
from mo.middle.passes.convert_data_type import np_data_type_to_destination_type
from mo.ops.op import Op
class RandomUniform(Op):
"""
RandomUniform operation that generates a sequence of random values from uniform distribution.
"""
op = 'RandomUniform'
enabled = False
def __init__(self, graph: Graph, attrs: dict):
super().__init__(graph, {
'type': self.op,
'op': self.op,
'version': 'opset8',
'infer': self.infer,
'in_ports_count': 3,
'out_ports_count': 1,
'type_infer': self.type_infer,
'global_seed': 0,
'op_seed': 0,
'output_type': np.float32,
}, attrs)
def backend_attrs(self):
return [('output_type', lambda node: np_data_type_to_destination_type(node.output_type)),
'global_seed',
'op_seed']
@staticmethod
def type_infer(node: Node):
node.out_port(0).set_data_type(node['output_type'])
@staticmethod
def infer(node: Node):
assert node.has_valid('output_type')
node.out_port(0).data.set_shape(node.in_port(0).data.get_value())
# We need to keep data type in data nodes corresponding to min and max values,
# as min and max value type should be the same as output_type attribute of RandomUniform
# operation. 'correct_data_type' attribute prevents changes of the data node type when
# ir data type is not equal to data node type.
node.in_node(1)['correct_data_type'] = True
node.in_node(2)['correct_data_type'] = True
class AttributedRandomUniform(Op):
""" RandomUniform operation that generates a sequence of random values from uniform distribution.
This operation uses the same semantics as RandomUniform but output shape, min value or max value
can be specified as attribute.
Shape is specified as attribute in ONNX. Min value and max value are specified as attributes
in RandomUniformInt in TF.
"""
op = 'AttributedRandomUniform'
enabled = False
def __init__(self, graph: Graph, attrs: dict):
super().__init__(graph, {
'type': None,
'op': self.op,
'infer': None,
'in_ports_count': 1,
'out_ports_count': 1,
'global_seed': 0,
'op_seed': 0,
'output_type': np.float32,
}, attrs)

View File

@ -1,6 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
def tf_random_uniform_infer(node):
node.out_port(0).data.set_shape(node.in_port(0).data.get_value())

View File

@ -5,7 +5,6 @@ from mo.front.tf.extractors.concat import tf_concat_ext
from mo.front.tf.extractors.fused_bn import tf_fused_bn_extractor
from mo.front.tf.extractors.native_tf import native_tf_node_extractor
from mo.front.tf.extractors.pack import tf_pack_ext
from mo.front.tf.extractors.random_uniform import tf_random_uniform_ext
from mo.front.tf.extractors.utils import get_tf_node_port
from mo.graph.graph import Node
@ -57,7 +56,6 @@ tf_op_extractors = {
'FusedBatchNormV3': node_pb_arg(tf_fused_bn_extractor),
'ConcatV2': node_pb_arg(tf_concat_ext),
'Pack': node_pb_arg(tf_pack_ext),
'RandomUniform': node_pb_arg(tf_random_uniform_ext),
}

View File

@ -1,10 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from mo.front.common.partial_infer.random_uniform import tf_random_uniform_infer
def tf_random_uniform_ext(pb):
return {
'infer': tf_random_uniform_infer
}

View File

@ -0,0 +1,16 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
from mo.middle.passes.convert_data_type import destination_type_to_np_data_type
from mo.utils.graph import Node
from mo.utils.ir_reader.extender import Extender
class RandomUniformExtender(Extender):
op = 'RandomUniform'
@staticmethod
def extend(op: Node):
if op.has_valid('output_type'):
op['output_type'] = destination_type_to_np_data_type(op.output_type)

View File

@ -0,0 +1,55 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
from argparse import Namespace
import numpy as np
from generator import generator, generate
from extensions.back.ChangeRandomUniformOutputType import ChangeRandomUniformOutputType
from mo.graph.graph import Node
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, result, connect, regular_op_with_shaped_data
nodes = {
**regular_op_with_shaped_data('placeholder', [3], {'type': 'Parameter'}),
**regular_op_with_shaped_data('random_uniform', [3, 4, 5], {'type': 'RandomUniform', 'op': 'RandomUniform'}),
**regular_op_with_shaped_data('convert', [3, 4, 5], {'type': 'Convert'}),
**result('result'),
# new RandomUniform node and inputs
**regular_op_with_shaped_data('min_val', [1], {'type': 'Const'}),
**regular_op_with_shaped_data('max_val', [1], {'type': 'Const'}),
**regular_op_with_shaped_data('shape', [3], {'type': 'Const'}),
}
edges = [*connect('placeholder', '0:random_uniform'), *connect('min_val', '1:random_uniform'),
*connect('max_val', '2:random_uniform'), *connect('random_uniform', 'result')]
edges_with_convert = [*connect('placeholder', '0:random_uniform'), *connect('min_val', '1:random_uniform'),
*connect('max_val', '2:random_uniform'), *connect('random_uniform', 'convert'),
*connect('convert', 'result'), ]
@generator
class ChangeRandomUniformOutputTypeTest(unittest.TestCase):
@generate(*[
("FP16", np.float32, np.float16),
("FP32", np.float16, np.float32),
("FP32", np.float32, None),
("FP32", np.int64, None)
])
def test_change_random_uniform_output_type(self, ir_type, out_type, dst_type):
graph = build_graph(nodes, edges, cli=Namespace(data_type=ir_type))
graph_ref = build_graph(nodes, edges if dst_type is None else edges_with_convert, {},
nodes_with_edges_only=True)
Node(graph, 'random_uniform')['output_type'] = out_type
ChangeRandomUniformOutputType().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
if dst_type is not None:
convert_node = Node(graph, 'random_uniform').out_port(0).get_destination().node
self.assertTrue(convert_node['dst_type'] == dst_type)

View File

@ -0,0 +1,65 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import unittest
import numpy as np
from extensions.front.AttributedRandomUniformToRandomUniform import AttributedRandomUniformToRandomUniform
from mo.front.common.partial_infer.utils import int64_array, float32_array
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, const, result, regular_op
nodes = {
**regular_op('placeholder', {'type': 'Parameter'}),
**regular_op('attr_random_uniform', {'type': 'AttributedRandomUniform', 'op': 'AttributedRandomUniform',
'output_type': np.float32,
'min_val': float32_array([-1.5]), 'max_val': float32_array([10.7]),
'shape': int64_array([5, 4, 3])}),
**result('result'),
# new RandomUniform node and inputs
**regular_op('random_uniform', {'type': 'RandomUniform'}),
**const('min_val', float32_array([-1.5])),
**const('max_val', float32_array([10.7])),
**const('shape', int64_array([5, 4, 3])),
}
class AttributedRandomUniformToRandomUniformTest(unittest.TestCase):
def test_min_max(self):
graph = build_graph(nodes,
[('placeholder', 'attr_random_uniform', {'in': 0, 'out': 0}),
('attr_random_uniform', 'result', {'in': 0, 'out': 0})], {}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes,
[('placeholder', 'random_uniform', {'in': 0, 'out': 0}),
('min_val', 'random_uniform', {'in': 1, 'out': 0}),
('max_val', 'random_uniform', {'in': 2, 'out': 0}),
('random_uniform', 'result')], {}, nodes_with_edges_only=True)
graph.stage = 'front'
AttributedRandomUniformToRandomUniform().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
self.assertTrue(
graph.node[graph.get_nodes_with_attributes(op='RandomUniform')[0]]['name'] == 'attr_random_uniform')
def test_min_max_shape(self):
graph = build_graph(nodes,
[('attr_random_uniform', 'result', {'in': 0, 'out': 0})], {}, nodes_with_edges_only=True)
graph_ref = build_graph(nodes,
[('shape', 'random_uniform', {'in': 0, 'out': 0}),
('min_val', 'random_uniform', {'in': 1, 'out': 0}),
('max_val', 'random_uniform', {'in': 2, 'out': 0}),
('random_uniform', 'result')], {}, nodes_with_edges_only=True)
graph.stage = 'front'
AttributedRandomUniformToRandomUniform().find_and_replace_pattern(graph)
(flag, resp) = compare_graphs(graph, graph_ref, 'result', check_op_attrs=True)
self.assertTrue(flag, resp)
self.assertTrue(
graph.node[graph.get_nodes_with_attributes(op='RandomUniform')[0]]['name'] == 'attr_random_uniform')

View File

@ -1,60 +0,0 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
import unittest
from extensions.front.DropoutWithRandomUniformReplacer import DropoutWithRandomUniformReplacer
from mo.utils.ir_engine.compare_graphs import compare_graphs
from unit_tests.utils.graph import build_graph, result, regular_op
class DropoutWithRandomUniformReplacerTest(unittest.TestCase):
def test(self):
nodes = {
**regular_op('input', {'type': 'Parameter'}),
**regular_op('shape', {'type': 'ShapeOf', 'kind': 'op', 'op': 'ShapeOf'}),
**regular_op('random_uniform', {'type': 'RandomUniform', 'kind': 'op', 'op': 'RandomUniform',
'name': 'dropout/RU'}),
**regular_op('mul', {'type': 'Mul', 'kind': 'op', 'op': 'Mul'}),
**regular_op('add', {'type': 'Add', 'kind': 'op', 'op': 'Add'}),
**regular_op('add2', {'type': 'Add', 'kind': 'op', 'op': 'Add'}),
**regular_op('floor', {'type': 'Floor', 'kind': 'op', 'op': 'Floor'}),
'add_const': {'kind': 'op', 'op': 'Const', 'value': np.array(0.0), 'data_type': np.float32},
**result('result'),
# new nodes to be added
'broadcast_const': {'kind': 'op', 'op': 'Const', 'value': np.array(0.5), 'data_type': np.float32},
**regular_op('broadcast', {'type': 'Broadcast', 'kind': 'op', 'op': 'Broadcast'}),
}
edges = [('input', 'shape'),
('shape', 'random_uniform'),
('random_uniform', 'mul'),
('mul', 'add'),
('add_const', 'add'),
('add', 'add2'),
('add2', 'floor'),
('floor', 'result')]
graph = build_graph(nodes, edges, nodes_with_edges_only=True)
graph.graph['layout'] = 'NCHW'
graph.stage = 'front'
DropoutWithRandomUniformReplacer().find_and_replace_pattern(graph)
edges_ref = [('input', 'shape'),
('broadcast_const', 'broadcast'),
('shape', 'broadcast'),
('broadcast', 'mul'),
('mul', 'add'),
('add_const', 'add'),
('add', 'add2'),
('add2', 'floor'),
('floor', 'result')]
graph_ref = build_graph(nodes, edges_ref, nodes_with_edges_only=True)
# check graph structure after the transformation and output name
(flag, resp) = compare_graphs(graph, graph_ref, 'result')
self.assertTrue(flag, resp)
self.assertTrue(graph.node[graph.get_nodes_with_attributes(op='Broadcast')[0]]['name'] == 'dropout/RU')

View File

@ -0,0 +1,104 @@
# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
import pytest
import tensorflow as tf
from mo.front.common.partial_infer.utils import int64_array
from unit_tests.utils.graph import build_graph, regular_op_with_shaped_data, connect, \
shaped_data, connect_front
from common.layer_test_class import check_ir_version
from common.tf_layer_test_class import CommonTFLayerTest
class TestTFRandomUniform(CommonTFLayerTest):
def create_tf_random_uniform_net(self, global_seed, op_seed, x_shape, min_val, max_val, input_type, ir_version):
tf.compat.v1.reset_default_graph()
# Create the graph and model
with tf.compat.v1.Session() as sess:
tf_x_shape = x_shape.copy()
# reshaping
if len(tf_x_shape) >= 3:
tf_x_shape.append(tf_x_shape.pop(1))
x = tf.compat.v1.placeholder(input_type, x_shape, 'Input')
if global_seed is not None:
tf.random.set_seed(global_seed)
random_uniform = tf.random.uniform(x_shape, seed=op_seed, dtype=input_type, minval=min_val,
maxval=max_val) + x
tf.compat.v1.global_variables_initializer()
tf_net = sess.graph_def
ref_net = None
if check_ir_version(10, None, ir_version):
const_for_layer_tests = lambda name, value, shape, shape1: {
**{name + '_dd': {'kind': 'data', 'value': value, 'shape': shape1}},
**{name: {'kind': 'op', 'type': 'Const'}},
**shaped_data(name + '_d', shape)}
connect_const_for_layer_tests = lambda first_tensor_name, second_tensor_name: [
*connect_front(first_tensor_name + '_dd', first_tensor_name),
*connect(first_tensor_name, second_tensor_name)]
nodes_attributes = {
**regular_op_with_shaped_data('input', x_shape, {'type': 'Parameter'}),
**const_for_layer_tests('shape', x_shape, int64_array([len(x_shape)]), int64_array([len(x_shape)])),
**const_for_layer_tests('min_val_default', 0.0, int64_array([]), int64_array([1])),
**const_for_layer_tests('max_val_default', 1.0, int64_array([]), int64_array([1])),
**const_for_layer_tests('min_val', min_val, int64_array([]), int64_array([1])),
**const_for_layer_tests('max_val', max_val, int64_array([]), int64_array([1])),
**regular_op_with_shaped_data('random_uniform', x_shape, {'type': 'RandomUniform'}),
**regular_op_with_shaped_data('random_uniform_add', x_shape, {'type': 'Add'}),
**const_for_layer_tests('random_uniform_add_const', np.array([[min_val]]),
int64_array([1, 1]) if min_val == 0.0 else int64_array([1]), int64_array([1])),
**regular_op_with_shaped_data('random_uniform_mul', x_shape, {'type': 'Multiply'}),
**const_for_layer_tests('random_uniform_mul_const', [max_val - min_val],
int64_array([1, 1]) if max_val == 1.0 else int64_array([1]), int64_array([1])),
**regular_op_with_shaped_data('add', x_shape, {'type': 'Add'}),
**regular_op_with_shaped_data('result', x_shape, {'type': 'Result'}),
}
if input_type == tf.float32:
ref_net = build_graph(nodes_attributes,
[*connect_const_for_layer_tests('shape', '0:random_uniform'),
*connect_const_for_layer_tests('min_val_default', '1:random_uniform'),
*connect_const_for_layer_tests('max_val_default', '2:random_uniform'),
*connect('random_uniform', '0:random_uniform_mul'),
*connect_const_for_layer_tests('random_uniform_mul_const',
'1:random_uniform_mul'),
*connect('random_uniform_mul', '0:random_uniform_add'),
*connect_const_for_layer_tests('random_uniform_add_const',
'1:random_uniform_add'),
*connect('random_uniform_add', '0:add'),
*connect('input', '1:add'),
*connect('add', 'result')])
else:
ref_net = build_graph(nodes_attributes,
[*connect_const_for_layer_tests('shape', '0:random_uniform'),
*connect_const_for_layer_tests('min_val', '1:random_uniform'),
*connect_const_for_layer_tests('max_val', '2:random_uniform'),
*connect('random_uniform', '0:add'),
*connect('input', '1:add'),
*connect('add', 'result')])
return tf_net, ref_net
test_data = [pytest.param(
dict(global_seed=32465, op_seed=48971, min_val=0.0, max_val=1.0, x_shape=[3, 7], input_type=tf.float32),
marks=pytest.mark.precommit),
dict(global_seed=None, op_seed=56197, min_val=-100, max_val=100, x_shape=[6], input_type=tf.float32),
dict(global_seed=78132, op_seed=None, min_val=-200, max_val=-50, x_shape=[5, 8], input_type=tf.int32),
dict(global_seed=4571, op_seed=48971, min_val=1.5, max_val=2.3, x_shape=[7], input_type=tf.float32),
dict(global_seed=32465, op_seed=12335, min_val=-150, max_val=-100, x_shape=[18], input_type=tf.int32)]
@pytest.mark.parametrize("params", test_data)
@pytest.mark.nightly
def test_tf_random_uniform(self, params, ie_device, precision, ir_version, temp_dir):
if ie_device == 'GPU':
pytest.skip("RandomUniform is not supported on GPU")
self._test(*self.create_tf_random_uniform_net(**params, ir_version=ir_version), ie_device, precision,
temp_dir=temp_dir, ir_version=ir_version, **params)