LSTMCell/Sequence v1, reference implementations and decompose transformations for LSTM/GRU/RNN Cells (#2000)

* validate_and_infer_types() implementation

* input parameter validation for LSTM, GRU and RNN

* style-check applied

* Add LSTMSequence dynamic shape validation and test props for RNNCell, GRUCell, LSTMCell and LSTMSequence.

* recurrent_sequence.hpp moved to ngraph/core/include/ngraph/op/util/

* style check applied

* removed unused variable from LSTMSequence::validate_and_infer_types

* Add missing newline mark at the end of file.

* Add supression macro for FusedOp deprecation.

* Add element type initialization

* transpose,rnn cell reference implementations

* Apply PR review remarks

* reference implementations for cells op, single layer tests, align lstm cell/sequence according to the spec

* lstm/gru/rnn cell decompostion transformations

* ngraph codestyle

* clean up

* ngraph code style

* change inheritance of Cells, fix build

* fix build

* fix build again

* remove Peepholes from LSTMSeq, fix copy_runtime_info in transformations

* Rewrite tests to use gtest exception assertions.

* resolve tests issues

* ngraph codestyle

* add missed files

* fix typeprop tests

* fix lstm sequence checks

* fix arm build

* fix arm again

* delete unnecessary file

* add convert weghts format function, enable lstm test, resolve review comments

* add ngraph builders

* ngraph codestyle

* fix unit tests

* revert transpose reference implementation

* revert LSTM Cell v0, add LSTMCell v1, update transformation lstm_cell_to_cell_ie

* v1 version of LSTMCell op

* LSTMSequence v1 operation, exclude LSTMSeq from opset4

* fix python api tests

* resolve review comments, tests for decomposition transformations, switch lstm cell to opset4 in mo

Co-authored-by: Szymon Durawa <szymon.durawa@intel.com>
This commit is contained in:
Ivan Tikhonov
2020-09-04 09:04:36 +03:00
committed by GitHub
parent 28eed7708e
commit 2f5a28d44f
65 changed files with 4695 additions and 1248 deletions

View File

@@ -0,0 +1,38 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include "functional_test_utils/layer_test_utils.hpp"
#include "ngraph_functions/builders.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
namespace LayerTestsDefinitions {
using GRUCellParams = typename std::tuple<
bool, // using decompose to sub-ops transformation
size_t, // batch
size_t, // hidden size
size_t, // input size
std::vector<std::string>, // activations
float, // clip
bool, // linear_before_reset
InferenceEngine::Precision, // Network precision
std::string>; // Device name
class GRUCellTest : public testing::WithParamInterface<GRUCellParams >,
virtual public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(const testing::TestParamInfo<GRUCellParams> &obj);
protected:
void SetUp() override;
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include "functional_test_utils/layer_test_utils.hpp"
#include "ngraph_functions/builders.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
namespace LayerTestsDefinitions {
using LSTMCellParams = typename std::tuple<
bool, // using decompose to sub-ops transformation
size_t, // batch
size_t, // hidden size
size_t, // input size
std::vector<std::string>, // activations
float, // clip
InferenceEngine::Precision, // Network precision
std::string>; // Device name
class LSTMCellTest : public testing::WithParamInterface<LSTMCellParams >,
virtual public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(const testing::TestParamInfo<LSTMCellParams> &obj);
protected:
void SetUp() override;
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,37 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include "functional_test_utils/layer_test_utils.hpp"
#include "ngraph_functions/builders.hpp"
#include "ngraph_functions/utils/ngraph_helpers.hpp"
namespace LayerTestsDefinitions {
using RNNCellParams = typename std::tuple<
bool, // using decompose to sub-ops transformation
size_t, // batch
size_t, // hidden size
size_t, // input size
std::vector<std::string>, // activations
float, // clip
InferenceEngine::Precision, // Network precision
std::string>; // Device name
class RNNCellTest : public testing::WithParamInterface<RNNCellParams >,
virtual public LayerTestsUtils::LayerTestsCommon {
public:
static std::string getTestCaseName(const testing::TestParamInfo<RNNCellParams> &obj);
protected:
void SetUp() override;
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,90 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include "ie_core.hpp"
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/precision_utils.hpp"
#include "functional_test_utils/plugin_cache.hpp"
#include "functional_test_utils/skip_tests_config.hpp"
#include <transformations/gru_cell_decomposition.hpp>
#include "single_layer_tests/gru_cell.hpp"
namespace LayerTestsDefinitions {
std::string GRUCellTest::getTestCaseName(const testing::TestParamInfo<GRUCellParams> &obj) {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> activations_beta;
float clip;
bool linear_before_reset;
std::vector<std::vector<size_t>> inputShapes;
InferenceEngine::Precision netPrecision;
std::string targetDevice;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip,
linear_before_reset, netPrecision, targetDevice) = obj.param;
std::ostringstream result;
result << "decomposition" << should_decompose << "_";
result << "batch=" << batch << "_";
result << "hidden_size=" << hidden_size << "_";
result << "input_size=" << input_size << "_";
result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_";
result << "activations=" << CommonTestUtils::vec2str(activations) << "_";
result << "clip=" << clip << "_";
result << "linear_before_reset=" << linear_before_reset << "_";
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetDevice << "_";
return result.str();
}
void GRUCellTest::SetUp() {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> activations_beta;
float clip;
bool linear_before_reset;
InferenceEngine::Precision netPrecision;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, linear_before_reset,
netPrecision, targetDevice) = this->GetParam();
std::vector<std::vector<size_t>> inputShapes = {
{{batch, input_size}, {batch, hidden_size}, {3 * hidden_size, input_size},
{3 * hidden_size, hidden_size}, {(linear_before_reset? 4 : 3) * hidden_size}},
};
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]});
std::vector<ngraph::Shape> WRB = {inputShapes[2], inputShapes[3], inputShapes[4]};
auto gru_cell = ngraph::builder::makeGRUCell(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
WRB, hidden_size, activations, {}, {}, clip, linear_before_reset);
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(gru_cell->output(0))};
function = std::make_shared<ngraph::Function>(results, params, "gru_cell");
if (should_decompose) {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::GRUCellDecomposition>();
m.run_passes(function);
}
}
TEST_P(GRUCellTest, CompareWithRefs) {
Run();
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,89 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include "ie_core.hpp"
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/precision_utils.hpp"
#include "functional_test_utils/plugin_cache.hpp"
#include "functional_test_utils/skip_tests_config.hpp"
#include <transformations/lstm_cell_decomposition.hpp>
#include "single_layer_tests/lstm_cell.hpp"
namespace LayerTestsDefinitions {
std::string LSTMCellTest::getTestCaseName(const testing::TestParamInfo<LSTMCellParams> &obj) {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> activations_beta;
float clip;
InferenceEngine::Precision netPrecision;
std::string targetDevice;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, netPrecision,
targetDevice) = obj.param;
std::vector<std::vector<size_t>> inputShapes = {
{{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size},
{4 * hidden_size, hidden_size}, {4 * hidden_size}},
};
std::ostringstream result;
result << "decomposition" << should_decompose << "_";
result << "batch=" << batch << "_";
result << "hidden_size=" << hidden_size << "_";
result << "input_size=" << input_size << "_";
result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_";
result << "activations=" << CommonTestUtils::vec2str(activations) << "_";
result << "clip=" << clip << "_";
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetDevice << "_";
return result.str();
}
void LSTMCellTest::SetUp() {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> activations_beta;
float clip;
InferenceEngine::Precision netPrecision;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, netPrecision,
targetDevice) = this->GetParam();
std::vector<std::vector<size_t>> inputShapes = {
{{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size},
{4 * hidden_size, hidden_size}, {4 * hidden_size}},
};
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1], inputShapes[2]});
std::vector<ngraph::Shape> WRB = {inputShapes[3], inputShapes[4], inputShapes[5]};
auto lstm_cell = ngraph::builder::makeLSTMCell(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
WRB, hidden_size, activations, {}, {}, clip);
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(lstm_cell->output(0)),
std::make_shared<ngraph::opset1::Result>(lstm_cell->output(1))};
function = std::make_shared<ngraph::Function>(results, params, "lstm_cell");
if (should_decompose) {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::LSTMCellDecomposition>();
m.run_passes(function);
}
}
TEST_P(LSTMCellTest, CompareWithRefs) {
Run();
};
} // namespace LayerTestsDefinitions

View File

@@ -0,0 +1,82 @@
// Copyright (C) 2019 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <tuple>
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include "ie_core.hpp"
#include "common_test_utils/common_utils.hpp"
#include "functional_test_utils/blob_utils.hpp"
#include "functional_test_utils/precision_utils.hpp"
#include "functional_test_utils/plugin_cache.hpp"
#include "functional_test_utils/skip_tests_config.hpp"
#include <transformations/rnn_cell_decomposition.hpp>
#include "single_layer_tests/rnn_cell.hpp"
namespace LayerTestsDefinitions {
std::string RNNCellTest::getTestCaseName(const testing::TestParamInfo<RNNCellParams> &obj) {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
float clip;
InferenceEngine::Precision netPrecision;
std::string targetDevice;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip,
netPrecision, targetDevice) = obj.param;
std::vector<std::vector<size_t>> inputShapes = {{batch, input_size}, {batch, hidden_size},
{hidden_size, input_size}, {hidden_size, hidden_size}, {hidden_size}};
std::ostringstream result;
result << "decomposition" << should_decompose << "_";
result << "batch=" << batch << "_";
result << "hidden_size=" << hidden_size << "_";
result << "input_size=" << input_size << "_";
result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_";
result << "activations=" << CommonTestUtils::vec2str(activations) << "_";
result << "clip=" << clip << "_";
result << "netPRC=" << netPrecision.name() << "_";
result << "targetDevice=" << targetDevice << "_";
return result.str();
}
void RNNCellTest::SetUp() {
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> activations_beta;
float clip;
InferenceEngine::Precision netPrecision;
std::tie(should_decompose, batch, hidden_size, input_size, activations, clip,
netPrecision, targetDevice) = this->GetParam();
std::vector<std::vector<size_t>> inputShapes = {{batch, input_size}, {batch, hidden_size},
{hidden_size, input_size}, {hidden_size, hidden_size}, {hidden_size}};
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]});
std::vector<ngraph::Shape> WRB = {inputShapes[2], inputShapes[3], inputShapes[4]};
auto rnn_cell = ngraph::builder::makeRNNCell(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
WRB, hidden_size, activations, {}, {}, clip);
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(rnn_cell)};
function = std::make_shared<ngraph::Function>(results, params, "rnn_cell");
if (should_decompose) {
ngraph::pass::Manager m;
m.register_pass<ngraph::pass::RNNCellDecomposition>();
m.run_passes(function);
}
}
TEST_P(RNNCellTest, CompareWithRefs) {
Run();
};
} // namespace LayerTestsDefinitions

View File

@@ -72,7 +72,7 @@ void Basic_LSTM_S::SetUp() {
//lstm [1, 10], [1, 118], [1, 118] -> [1, 118], [1, 118]
outFormShapes1 = { batch_size, reshape1_shape[2] };
auto constantX = std::make_shared<ngraph::opset1::Constant>(ngraph::element::i64, ngraph::Shape{2}, outFormShapes1);
auto lstm1 = std::make_shared<ngraph::opset1::LSTMCell>(std::make_shared<ngraph::opset1::Reshape>(X, constantX, false),
auto lstm1 = std::make_shared<ngraph::opset4::LSTMCell>(std::make_shared<ngraph::opset1::Reshape>(X, constantX, false),
H_t, C_t,
weightsNode, reccurrenceWeightsNode, hidden_size);
@@ -137,7 +137,7 @@ std::shared_ptr<ngraph::Function> Basic_LSTM_S::CreateGraphWithUnrolledTI() {
ngraph::Output<ngraph::Node> H[iterations + 1];
ngraph::Output<ngraph::Node> C[iterations + 1];
std::shared_ptr<ngraph::opset1::LSTMCell> lstm[iterations];
std::shared_ptr<ngraph::opset4::LSTMCell> lstm[iterations];
H[0] = ngraph::builder::makeConstant<float>(ngPrc, { batch_size, hidden_size }, {}, true);
C[0] = ngraph::builder::makeConstant<float>(ngPrc, { batch_size, hidden_size }, {}, true);
auto reshape1_shape = reshape1->output(0).get_shape();
@@ -149,7 +149,7 @@ std::shared_ptr<ngraph::Function> Basic_LSTM_S::CreateGraphWithUnrolledTI() {
for (size_t i = 0; i < iterations; ++i) {
auto X = split1->output(i);
lstm[i] = std::make_shared<ngraph::opset1::LSTMCell>(std::make_shared<ngraph::opset1::Reshape>(X, constantX, false),
lstm[i] = std::make_shared<ngraph::opset4::LSTMCell>(std::make_shared<ngraph::opset1::Reshape>(X, constantX, false),
H[i], C[i],
weightsNode, reccurrenceWeightsNode, hidden_size);