Reduce number of Reshape operations in RNN sequences decomposition (#9495)
Move Squeeze/Unsqueeze for hidden and cell state outside of tensor iterator's body. So it's executed once per sequence instead of once per cell.
This commit is contained in:
parent
b06c0b5c32
commit
8ef08292a6
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -87,35 +87,38 @@ namespace {
|
||||
reverse_seq_before = std::make_shared<ngraph::opset5::ReverseSequence>(X, seq_lengths, 0, 1);
|
||||
}
|
||||
|
||||
auto axis_0 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 0 });
|
||||
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
|
||||
// TensorIterator Body: begin
|
||||
auto X_param_pshape = X_pshape;
|
||||
X_param_pshape[1] = 1; // split by seq_lengths dimension
|
||||
auto X_body_param = std::make_shared<ngraph::opset5::Parameter>(X.get_element_type(), X_param_pshape);
|
||||
auto H_body_param = std::make_shared<ngraph::opset5::Parameter>(H_t.get_element_type(), H_t.get_partial_shape());
|
||||
|
||||
const auto squeezed_h = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(H_t, axis_1);
|
||||
auto H_body_param = std::make_shared<ngraph::opset5::Parameter>(squeezed_h->get_element_type(), squeezed_h->get_output_partial_shape(0));
|
||||
auto seq_body_param = std::make_shared<ngraph::opset5::Parameter>(seq_lengths.get_element_type(), seq_lengths.get_partial_shape());
|
||||
|
||||
// LSTM sequence case
|
||||
const bool cell_state_defined = C_t.get_node_shared_ptr() != nullptr;
|
||||
std::shared_ptr<ngraph::opset5::Parameter> C_body_param = cell_state_defined ?
|
||||
std::make_shared<ngraph::opset5::Parameter>(C_t.get_element_type(), C_t.get_partial_shape()) :
|
||||
nullptr;
|
||||
|
||||
auto axis_0 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 0 });
|
||||
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
std::shared_ptr<ngraph::opset5::Parameter> C_body_param = nullptr;
|
||||
std::shared_ptr<ngraph::Node> squeezed_c = nullptr;
|
||||
if (cell_state_defined) {
|
||||
squeezed_c = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(C_t, axis_1);
|
||||
C_body_param = std::make_shared<ngraph::opset5::Parameter>(squeezed_c->get_element_type(), squeezed_c->get_output_partial_shape(0));
|
||||
}
|
||||
|
||||
const auto squeezed_x = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(X_body_param, axis_1);
|
||||
const auto squeezed_h = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(H_body_param, axis_1);
|
||||
const auto squeezed_w = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(W, axis_0);
|
||||
const auto squeezed_r = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(R, axis_0);
|
||||
const auto squeezed_b = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(B, axis_0);
|
||||
|
||||
std::shared_ptr<ngraph::Node> cell;
|
||||
if (const auto lstm_sequence = ngraph::as_type_ptr<ngraph::opset5::LSTMSequence>(sequence)) {
|
||||
const auto squeezed_c = ngraph::op::util::make_try_fold<ngraph::opset5::Squeeze>(C_body_param, axis_1);
|
||||
cell = std::make_shared<ngraph::opset5::LSTMCell>(
|
||||
squeezed_x,
|
||||
squeezed_h,
|
||||
squeezed_c,
|
||||
H_body_param,
|
||||
C_body_param,
|
||||
squeezed_w,
|
||||
squeezed_r,
|
||||
squeezed_b,
|
||||
@ -127,7 +130,7 @@ namespace {
|
||||
} else if (const auto rnn_sequence = ngraph::as_type_ptr<ngraph::opset5::RNNSequence>(sequence)) {
|
||||
cell = std::make_shared<ngraph::opset5::RNNCell>(
|
||||
squeezed_x,
|
||||
squeezed_h,
|
||||
H_body_param,
|
||||
squeezed_w,
|
||||
squeezed_r,
|
||||
squeezed_b,
|
||||
@ -139,7 +142,7 @@ namespace {
|
||||
} else if (const auto gnn_sequence = ngraph::as_type_ptr<ngraph::opset5::GRUSequence>(sequence)) {
|
||||
cell = std::make_shared<ngraph::opset5::GRUCell>(
|
||||
squeezed_x,
|
||||
squeezed_h,
|
||||
H_body_param,
|
||||
squeezed_w,
|
||||
squeezed_r,
|
||||
squeezed_b,
|
||||
@ -153,24 +156,24 @@ namespace {
|
||||
|
||||
ngraph::ParameterVector body_params;
|
||||
ngraph::ResultVector body_results;
|
||||
auto unsqueeze_dum_dir_h = std::make_shared<ngraph::opset5::Unsqueeze>(cell->output(0), axis_1);
|
||||
ngraph::Output<ngraph::Node> h_node_to_result = unsqueeze_dum_dir_h;
|
||||
|
||||
auto unsqueeze_dum_dir_c = cell_state_defined ? std::make_shared<ngraph::opset5::Unsqueeze>(cell->output(1), axis_1) : nullptr;
|
||||
ngraph::Output<ngraph::Node> c_node_to_result = cell_state_defined ? unsqueeze_dum_dir_c : ngraph::Output<ngraph::Node>();
|
||||
ngraph::Output<ngraph::Node> hidden_state = cell->output(0);
|
||||
ngraph::Output<ngraph::Node> cell_state;
|
||||
if (cell_state_defined)
|
||||
cell_state = cell->output(1);
|
||||
|
||||
auto tensor_iterator = std::make_shared<ngraph::opset5::TensorIterator>();
|
||||
if (enable_mask) {
|
||||
const auto current_iter = get_current_iter(body_params, body_results, seq_body_param);
|
||||
h_node_to_result = get_masked_value(tensor_iterator, body_params, body_results, current_iter, unsqueeze_dum_dir_h, seq_body_param);
|
||||
hidden_state = get_masked_value(tensor_iterator, body_params, body_results, current_iter, hidden_state, seq_body_param);
|
||||
if (cell_state_defined)
|
||||
c_node_to_result = get_masked_value(tensor_iterator, body_params, body_results, current_iter, unsqueeze_dum_dir_c, seq_body_param);
|
||||
cell_state = get_masked_value(tensor_iterator, body_params, body_results, current_iter, cell_state, seq_body_param);
|
||||
}
|
||||
|
||||
auto H_res = std::make_shared<ngraph::opset5::Result>(h_node_to_result);
|
||||
auto C_res = cell_state_defined ? std::make_shared<ngraph::opset5::Result>(c_node_to_result) : nullptr;
|
||||
auto unsqueeze_seq_len = std::make_shared<ngraph::opset5::Unsqueeze>(h_node_to_result, axis_1);
|
||||
auto concat_res = std::make_shared<ngraph::opset5::Result>(unsqueeze_seq_len);
|
||||
auto H_res = std::make_shared<ngraph::opset5::Result>(hidden_state);
|
||||
auto C_res = cell_state_defined ? std::make_shared<ngraph::opset5::Result>(cell_state) : nullptr;
|
||||
auto hidden_state_unsqueezed = std::make_shared<ngraph::opset5::Unsqueeze>(hidden_state, axis_1);
|
||||
auto concat_res = std::make_shared<ngraph::opset5::Result>(hidden_state_unsqueezed);
|
||||
|
||||
body_params.push_back(X_body_param);
|
||||
body_params.push_back(H_body_param);
|
||||
@ -190,21 +193,21 @@ namespace {
|
||||
if (!enable_mask) {
|
||||
// Reversed order, stride -1
|
||||
tensor_iterator->set_sliced_input(X_body_param, X, -1, -1, 1, 0, 1);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, -1, -1, 1, 0, 2);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, -1, -1, 1, 0, 1);
|
||||
} else {
|
||||
// use ReverseSequence as initializer
|
||||
tensor_iterator->set_sliced_input(X_body_param, reverse_seq_before, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 1);
|
||||
}
|
||||
} else {
|
||||
// forward order
|
||||
tensor_iterator->set_sliced_input(X_body_param, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(concat_res, 0, 1, 1, -1, 1);
|
||||
}
|
||||
|
||||
tensor_iterator->set_merged_input(H_body_param, H_t, H_res);
|
||||
tensor_iterator->set_merged_input(H_body_param, squeezed_h, H_res);
|
||||
if (cell_state_defined)
|
||||
tensor_iterator->set_merged_input(C_body_param, C_t, C_res);
|
||||
tensor_iterator->set_merged_input(C_body_param, squeezed_c, C_res);
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
|
||||
ngraph::Output<ngraph::Node> H_out = H_res;
|
||||
@ -242,8 +245,12 @@ namespace {
|
||||
if (cell_state_defined)
|
||||
tensor_iterator->get_iter_value(C_out);
|
||||
tensor_iterator->set_friendly_name(sequence->get_friendly_name());
|
||||
ngraph::NodeVector new_nodes{squeezed_h, tensor_iterator};
|
||||
if (cell_state_defined)
|
||||
new_nodes.push_back(squeezed_c);
|
||||
ngraph::OutputVector nodes_to_replace;
|
||||
if (enable_mask && is_reverse) {
|
||||
auto reverse_seq_after = std::make_shared<ngraph::opset5::ReverseSequence>(tensor_iterator->output(0), seq_lengths, 0, 2);
|
||||
auto reverse_seq_after = std::make_shared<ngraph::opset5::ReverseSequence>(tensor_iterator->output(0), seq_lengths, 0, 1);
|
||||
// Resolve a collision of names data nodes in CNN Network in Reverse case with mask.
|
||||
/*
|
||||
* Before transformation (no collisions)
|
||||
@ -262,33 +269,31 @@ namespace {
|
||||
* TI [other_name] -- (data_node: other_name.0) --> RevSequence [rnn_name.0] -- (data_node: rnn_name.0) -> Result1
|
||||
* -- (data_node: other_name.1) --> Identity(rnn_name.1) -- (data_node: rnn_name.1) -> Result2
|
||||
*/
|
||||
auto identity_1_h = std::make_shared<ngraph::opset5::Unsqueeze>(tensor_iterator->output(1), axis_1);
|
||||
auto identity_2_h = std::make_shared<ngraph::opset5::Squeeze>(identity_1_h, axis_1);
|
||||
|
||||
ngraph::NodeVector new_nodes{ reverse_seq_after, tensor_iterator, reverse_seq_before, identity_1_h, identity_2_h };
|
||||
ngraph::OutputVector nodes_to_replace{ reverse_seq_after, identity_2_h };
|
||||
new_nodes.push_back(reverse_seq_before);
|
||||
new_nodes.push_back(reverse_seq_after);
|
||||
nodes_to_replace.push_back(reverse_seq_after);
|
||||
nodes_to_replace.push_back(tensor_iterator->output(1));
|
||||
|
||||
if (cell_state_defined) {
|
||||
auto identity_1_c = std::make_shared<ngraph::opset5::Unsqueeze>(tensor_iterator->output(2), axis_1);
|
||||
auto identity_2_c = std::make_shared<ngraph::opset5::Squeeze>(identity_1_c, axis_1);
|
||||
|
||||
new_nodes.emplace_back(identity_1_c);
|
||||
new_nodes.emplace_back(identity_2_c);
|
||||
nodes_to_replace.emplace_back(identity_2_c);
|
||||
|
||||
identity_2_c->set_friendly_name(sequence->get_friendly_name() + ".2");
|
||||
auto cell_state = tensor_iterator->output(2);
|
||||
new_nodes.emplace_back(cell_state.get_node_shared_ptr());
|
||||
nodes_to_replace.emplace_back(cell_state);
|
||||
}
|
||||
|
||||
tensor_iterator->set_friendly_name(sequence->get_friendly_name() + "/tensor_iterator");
|
||||
} else {
|
||||
nodes_to_replace = tensor_iterator->outputs();
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nodes_to_replace.size(); i++) {
|
||||
auto unsqueeze = std::make_shared<ngraph::opset5::Unsqueeze>(nodes_to_replace[i], axis_1);
|
||||
unsqueeze->set_friendly_name(sequence->get_friendly_name() + "." + std::to_string(i));
|
||||
nodes_to_replace[i] = unsqueeze;
|
||||
new_nodes.push_back(unsqueeze);
|
||||
}
|
||||
ngraph::copy_runtime_info(sequence, new_nodes);
|
||||
ngraph::replace_node(sequence, nodes_to_replace);
|
||||
|
||||
tensor_iterator->set_friendly_name(sequence->get_friendly_name() + "/tensor_iterator");
|
||||
reverse_seq_after->set_friendly_name(sequence->get_friendly_name() + ".0");
|
||||
identity_2_h->set_friendly_name(sequence->get_friendly_name() + ".1");
|
||||
} else {
|
||||
ngraph::copy_runtime_info(sequence, tensor_iterator);
|
||||
ngraph::replace_node(sequence, tensor_iterator);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// Copyright (C) 2018-2022 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
@ -56,17 +56,17 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIterator) {
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 2, 16 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto Z = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, squeeze_pattern);
|
||||
auto squeeze_z = std::make_shared<opset5::Squeeze>(Z, squeeze_pattern);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 16 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto Zi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 128 });
|
||||
auto Zi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, squeeze_pattern);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, squeeze_pattern);
|
||||
auto squeeze_z = std::make_shared<opset5::Squeeze>(Zi, squeeze_pattern);
|
||||
|
||||
auto w_val = std::vector<float>(512 * 16, 0);
|
||||
auto r_val = std::vector<float>(512 * 128, 0);
|
||||
@ -75,17 +75,15 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIterator) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 512, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 512 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::LSTMCell>(squeeze_x, squeeze_y, squeeze_z, W, R, B, 128);
|
||||
auto rnn_cell = std::make_shared<opset5::LSTMCell>(squeeze_x, Yi, Zi, W, R, B, 128);
|
||||
|
||||
auto unsqueeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(0), unsqueeze_pattern);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell->output(0));
|
||||
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
auto unsqueeze_y = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(0), unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze_y);
|
||||
|
||||
auto unsqueeze3 = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(1), unsqueeze_pattern);
|
||||
auto Co = std::make_shared<opset5::Result>(unsqueeze3);
|
||||
auto Co = std::make_shared<opset5::Result>(rnn_cell->output(1));
|
||||
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho, Co }, ParameterVector{ Xi, Yi, Zi, seq_body_param });
|
||||
|
||||
@ -93,10 +91,10 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIterator) {
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Zi, Z, Co);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
tensor_iterator->set_merged_input(Zi, squeeze_z, Co);
|
||||
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
@ -104,9 +102,9 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIterator) {
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
tensor_iterator->get_iter_value(Co);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_C = std::make_shared<opset5::Result>(tensor_iterator->output(2));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), unsqueeze_pattern));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), unsqueeze_pattern));
|
||||
auto res_ti_C = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(2), unsqueeze_pattern));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
res_ti_C->set_friendly_name("Co");
|
||||
@ -153,17 +151,17 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIteratorDynamic) {
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 2, -1 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto Z = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, squeeze_pattern);
|
||||
auto squeeze_z = std::make_shared<opset5::Squeeze>(Z, squeeze_pattern);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 1, -1 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto Zi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 128 });
|
||||
auto Zi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, squeeze_pattern);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, squeeze_pattern);
|
||||
auto squeeze_z = std::make_shared<opset5::Squeeze>(Zi, squeeze_pattern);
|
||||
|
||||
auto w_val = std::vector<float>(512 * 16, 0);
|
||||
auto r_val = std::vector<float>(512 * 128, 0);
|
||||
@ -172,17 +170,15 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIteratorDynamic) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 512, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 512 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::LSTMCell>(squeeze_x, squeeze_y, squeeze_z, W, R, B, 128);
|
||||
auto rnn_cell = std::make_shared<opset5::LSTMCell>(squeeze_x, Yi, Zi, W, R, B, 128);
|
||||
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell->output(0));
|
||||
|
||||
auto unsqueeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(0), unsqueeze_pattern);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto unsqueeze_y = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(0), unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze_y);
|
||||
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
|
||||
auto unsqueeze3 = std::make_shared<opset5::Unsqueeze>(rnn_cell->output(1), unsqueeze_pattern);
|
||||
auto Co = std::make_shared<opset5::Result>(unsqueeze3);
|
||||
auto Co = std::make_shared<opset5::Result>(rnn_cell->output(1));
|
||||
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho, Co }, ParameterVector{ Xi, Yi, Zi, seq_body_param });
|
||||
|
||||
@ -190,10 +186,10 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIteratorDynamic) {
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Zi, Z, Co);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
tensor_iterator->set_merged_input(Zi, squeeze_z, Co);
|
||||
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
@ -201,9 +197,9 @@ TEST(TransformationTests, ConvertLSTMSequenceToTensorIteratorDynamic) {
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
tensor_iterator->get_iter_value(Co);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_C = std::make_shared<opset5::Result>(tensor_iterator->output(2));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), unsqueeze_pattern));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), unsqueeze_pattern));
|
||||
auto res_ti_C = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(2), unsqueeze_pattern));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
res_ti_C->set_friendly_name("Co");
|
||||
@ -248,15 +244,15 @@ TEST(TransformationTests, ConvertRNNSequenceToTensorIterator) {
|
||||
{
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 2, 16 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, squeeze_pattern);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 16 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, squeeze_pattern);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, squeeze_pattern);
|
||||
|
||||
auto w_val = std::vector<float>(128 * 16, 0);
|
||||
auto r_val = std::vector<float>(128 * 128, 0);
|
||||
@ -265,28 +261,27 @@ TEST(TransformationTests, ConvertRNNSequenceToTensorIterator) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 128, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 128 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::RNNCell>(squeeze_x, squeeze_y, W, R, B, 128);
|
||||
auto rnn_cell = std::make_shared<opset5::RNNCell>(squeeze_x, Yi, W, R, B, 128);
|
||||
auto unsqueeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell);
|
||||
auto unsqueeze = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze);
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho }, ParameterVector{ Xi, Yi, seq_body_param });
|
||||
|
||||
auto tensor_iterator = std::make_shared<opset5::TensorIterator>();
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), unsqueeze_pattern));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), unsqueeze_pattern));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
|
||||
@ -329,15 +324,15 @@ TEST(TransformationTests, ConvertRNNSequenceToTensorIteratorDynamic) {
|
||||
{
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 2, -1 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, axis_1);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 1, -1 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto axis_1 = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, axis_1);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, axis_1);
|
||||
|
||||
auto w_val = std::vector<float>(128 * 16, 0);
|
||||
auto r_val = std::vector<float>(128 * 128, 0);
|
||||
@ -346,27 +341,26 @@ TEST(TransformationTests, ConvertRNNSequenceToTensorIteratorDynamic) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 128, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 128 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::RNNCell>(squeeze_x, squeeze_y, W, R, B, 128);
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell, axis_1);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, axis_1);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
auto rnn_cell = std::make_shared<opset5::RNNCell>(squeeze_x, Yi, W, R, B, 128);
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell);
|
||||
auto unsqueeze = std::make_shared<opset5::Unsqueeze>(rnn_cell, axis_1);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze);
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho }, ParameterVector{ Xi, Yi, seq_body_param });
|
||||
|
||||
auto tensor_iterator = std::make_shared<opset5::TensorIterator>();
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), axis_1));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), axis_1));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
|
||||
@ -409,15 +403,15 @@ TEST(TransformationTests, ConvertGRUSequenceToTensorIterator) {
|
||||
{
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 2, 16 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, squeeze_pattern);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 16 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, Shape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, squeeze_pattern);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, squeeze_pattern);
|
||||
|
||||
auto w_val = std::vector<float>(384 * 16, 0);
|
||||
auto r_val = std::vector<float>(384 * 128, 0);
|
||||
@ -426,28 +420,27 @@ TEST(TransformationTests, ConvertGRUSequenceToTensorIterator) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 384, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 384 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::GRUCell>(squeeze_x, squeeze_y, W, R, B, 128);
|
||||
auto rnn_cell = std::make_shared<opset5::GRUCell>(squeeze_x, Yi, W, R, B, 128);
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell);
|
||||
auto unsqueeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
auto unsqueeze = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze);
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho }, ParameterVector{ Xi, Yi, seq_body_param });
|
||||
|
||||
auto tensor_iterator = std::make_shared<opset5::TensorIterator>();
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), unsqueeze_pattern));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), unsqueeze_pattern));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
|
||||
@ -490,15 +483,15 @@ TEST(TransformationTests, ConvertGRUSequenceToTensorIteratorDynamic) {
|
||||
{
|
||||
auto X = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 2, -1 });
|
||||
auto Y = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Y, squeeze_pattern);
|
||||
|
||||
auto Xi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ -1, 1, -1 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 1, 128 });
|
||||
auto Yi = std::make_shared<opset5::Parameter>(element::f32, PartialShape{ 1, 128 });
|
||||
auto seq_body_param = std::make_shared<opset5::Parameter>(element::i32, PartialShape{ 1 });
|
||||
|
||||
// Body
|
||||
auto squeeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto squeeze_x = std::make_shared<opset5::Squeeze>(Xi, squeeze_pattern);
|
||||
auto squeeze_y = std::make_shared<opset5::Squeeze>(Yi, squeeze_pattern);
|
||||
|
||||
auto w_val = std::vector<float>(384 * 16, 0);
|
||||
auto r_val = std::vector<float>(384 * 128, 0);
|
||||
@ -507,28 +500,27 @@ TEST(TransformationTests, ConvertGRUSequenceToTensorIteratorDynamic) {
|
||||
auto R = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 384, 128 }, r_val);
|
||||
auto B = ngraph::opset5::Constant::create(ngraph::element::f32, ngraph::Shape{ 384 }, b_val);
|
||||
|
||||
auto rnn_cell = std::make_shared<opset5::GRUCell>(squeeze_x, squeeze_y, W, R, B, 128);
|
||||
auto rnn_cell = std::make_shared<opset5::GRUCell>(squeeze_x, Yi, W, R, B, 128);
|
||||
auto Ho = std::make_shared<opset5::Result>(rnn_cell);
|
||||
auto unsqueeze_pattern = ngraph::opset5::Constant::create(ngraph::element::i64, ngraph::Shape{ 1 }, { 1 });
|
||||
auto unsqueeze1 = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Ho = std::make_shared<opset5::Result>(unsqueeze1);
|
||||
auto unsqueeze2 = std::make_shared<opset5::Unsqueeze>(unsqueeze1, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze2);
|
||||
auto unsqueeze = std::make_shared<opset5::Unsqueeze>(rnn_cell, unsqueeze_pattern);
|
||||
auto Y_out = std::make_shared<opset5::Result>(unsqueeze);
|
||||
auto body = std::make_shared<Function>(OutputVector{ Y_out, Ho }, ParameterVector{ Xi, Yi, seq_body_param });
|
||||
|
||||
auto tensor_iterator = std::make_shared<opset5::TensorIterator>();
|
||||
tensor_iterator->set_body(body);
|
||||
|
||||
tensor_iterator->set_sliced_input(Xi, X, 0, 1, 1, -1, 1);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 2);
|
||||
tensor_iterator->get_concatenated_slices(Y_out, 0, 1, 1, -1, 1);
|
||||
|
||||
tensor_iterator->set_merged_input(Yi, Y, Ho);
|
||||
tensor_iterator->set_merged_input(Yi, squeeze_y, Ho);
|
||||
auto seq_lengths = opset5::Constant::create(element::i32, Shape{ 1 }, { 2 });
|
||||
tensor_iterator->set_invariant_input(seq_body_param, seq_lengths);
|
||||
|
||||
tensor_iterator->get_iter_value(Ho);
|
||||
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(tensor_iterator->output(0));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(tensor_iterator->output(1));
|
||||
auto res_ti_Y = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(0), unsqueeze_pattern));
|
||||
auto res_ti_H = std::make_shared<opset5::Result>(std::make_shared<opset5::Unsqueeze>(tensor_iterator->output(1), unsqueeze_pattern));
|
||||
res_ti_Y->set_friendly_name("Y_out");
|
||||
res_ti_H->set_friendly_name("Ho");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user