Support of passing model from memory to mo.convert_model() (#13457)
* convert() method added. * Moved conversion to convert() method. * Fixed commits. * Output dir fix. * Added objects support for extesions param. * Added support for transformations_config extension objects. * Input to str unit tests. * Added tests, added comments. * Updated BOM. * Removed commented code. * Fixed extension passing. * Small corrections. * Fixed for python 3.6. * Small fix. * Moved dir creating to ov.serialize(), removed mo.serialize(), small fixes. * Small fix. * Small correction. * Removed coping of params, moved convert implemetation to separate module. * Import fixes. * Moved hiding of exceptions to main(). * Updated comment. * Fixed unit tests. * Comment changed. * Fixed dir creating. * Tests fixed. * Small fixes. * Test fix. * Added meta data generation, removed printing of execution time for silent mode. * Import fix. * Conflict fix. * Fixed error. * Fix for custom config. * Added version, data_type params to help. * Added mo.convert() full-functional tests. * Small corrections. * Comment correction. * Moved convert to openvino package, moved LayotMap and InputCutInfo to openvino.convert. * Added help param. * Wrong change removed. * Small fix. * Removed unnecessary comments. * Removed .xml extension check from append_ir_info. * Added missed file. * Fixed error. * Fix for bool value in InputCutInfo. * Moved InputCutInfo, LayoutMap to openvino.tools.mo. * Moved InputCutInfo, LayoutMap to openvino.tools.mo. * Moved check and read_model to emit_ir. * Small correction. * Added comment. * Added unit_tests with convert(). * Small corrections. * Removed convert alias from openvino. * Fixed conflicting unit tests. * Removed unnecessary warnings. * Params check fix. * Small correction. * Added paths checks. * Added negative tests for to_str methods, fixed errors. * Added tuples support in input parameter. * Added direct support of BytesIO and TF1 graph def. * Moved reminders to update OV and use API 2.0 to main(). * Fixed keras loading. * Returned .mapping file generating. * Added positional input_model param. * Added test for unnamed input_model. * Optimize imports. * Added more informative error for brackets syntax in --input. * Keras direct model support. * Keras direct model support. * Small fix. * Conflict fix. * Conflict fix. * Added direct support of BytesIO and TF1 graph def. * Fixed keras loading. * Keras direct model support. * Keras direct model support. * Small fix. * Tests for importing from memory. * Support of other tf/pytorch formats. * Updated mo_convert extensions tests to use ov models. * Removed debug output. * Implemented PyTorch converting logic. * Small corrections. * Small corrections. * Added comments. * Fixed for single input case. * Added switching between save to file and BytesIO. * Small fixes. * Rename convert() to convert_model(). * Added env variable to disable converting to onnx. * Tests refactoring. * Add MO Python API tests to precommit. * Add MO Python API tests to precommit. * Added PyTorch to layer tests requirements. * Added supported formats description. * Fixed errors, added tests. * Fixed bugs, added support of numpy and ov.Tensor sample_input. * Added more torch.Size tests. * Small correction. * Renamed sample_input->example_inputs. * Tests refactoring. * Code style. * Added support of dict in example_inputs. * Small correction. * Added removing of tmp onnx model in case of conversion error. * Fix for lists of tensors in example_inputs. * Support of dynamic axes for Keras layer, Keras module. * Removed disabling of eager execution. * Tests fixed. * Added pytest requirement for layer tests. * Added convert_model to openvino.runtime, fixed test runs. * Small fix. * Tests fix. * Better help message. * Error fixed. * Renamed example_inputs->example_input. * Small fix. * Added support of list of layouts. * Removed wrong change. * Added tuple support for --layout. * Removed convert_model from openvino.runtime. * Use of default onnx opset version. * Added support of dynamic input shapes without example_input. * Made better error message. * Removed stack trace from exceptions. * Fixed tests. * Small fix. * Removed wrong change. * Added import model from memory tests in unit tests. * Replaced compare_functions() with MO IR reader compare. * Removed test. * Removed not needed change. * Fixed conflicts.
This commit is contained in:
@@ -544,6 +544,33 @@ jobs:
|
||||
displayName: 'TensorFlow 2 Layer Tests - Legacy FE'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
. $(PY_VENV)/bin/activate
|
||||
python3 -m pip install -r $(LAYER_TESTS_DIR)/requirements.txt
|
||||
export PYTHONPATH=$(LAYER_TESTS_DIR):$PYTHONPATH
|
||||
export TEST_DEVICE=CPU
|
||||
$(RUN_PREFIX) python3 -m pytest $(LAYER_TESTS_DIR)/mo_python_api_tests/test_mo_convert_complex_params.py --ir_version=11 --junitxml=./TEST-test_mo_convert_complex_params.xmlTEST
|
||||
displayName: 'MO Python API Tests - Complex Python params'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
. $(PY_VENV)/bin/activate
|
||||
python3 -m pip install -r $(LAYER_TESTS_DIR)/requirements.txt
|
||||
export PYTHONPATH=$(LAYER_TESTS_DIR):$PYTHONPATH
|
||||
export TEST_DEVICE=CPU
|
||||
$(RUN_PREFIX) python3 -m pytest $(LAYER_TESTS_DIR)/mo_python_api_tests/test_mo_convert_tf.py --ir_version=11 --junitxml=./TEST-test_mo_convert_tf.xmlTEST
|
||||
displayName: 'MO Python API Tests - Import TF model from memory'
|
||||
continueOnError: false
|
||||
|
||||
- script: |
|
||||
. $(PY_VENV)/bin/activate
|
||||
python3 -m pip install -r $(LAYER_TESTS_DIR)/requirements.txt
|
||||
export PYTHONPATH=$(LAYER_TESTS_DIR):$PYTHONPATH
|
||||
export TEST_DEVICE=CPU
|
||||
$(RUN_PREFIX) python3 -m pytest $(LAYER_TESTS_DIR)/mo_python_api_tests/test_mo_convert_pytorch.py --ir_version=11 --junitxml=./TEST-test_mo_convert_pytorch.xmlTEST
|
||||
displayName: 'MO Python API Tests - Import PyTorch model from memory'
|
||||
continueOnError: false
|
||||
|
||||
- task: PublishTestResults@2
|
||||
condition: always()
|
||||
inputs:
|
||||
|
||||
@@ -13,16 +13,20 @@ namespace py = pybind11;
|
||||
PYBIND11_MODULE(test_utils_api, m) {
|
||||
m.def(
|
||||
"compare_functions",
|
||||
[](const ov::Model& lhs, const ov::Model& rhs) {
|
||||
[](const ov::Model& lhs, const ov::Model& rhs, bool compare_tensor_names) {
|
||||
const auto lhs_ptr = std::const_pointer_cast<ov::Model>(lhs.shared_from_this());
|
||||
const auto rhs_ptr = std::const_pointer_cast<ov::Model>(rhs.shared_from_this());
|
||||
|
||||
const auto fc = FunctionsComparator::with_default()
|
||||
.enable(FunctionsComparator::ATTRIBUTES)
|
||||
.enable(FunctionsComparator::CONST_VALUES);
|
||||
auto fc = FunctionsComparator::with_default()
|
||||
.enable(FunctionsComparator::ATTRIBUTES)
|
||||
.enable(FunctionsComparator::CONST_VALUES);
|
||||
|
||||
if (!compare_tensor_names)
|
||||
fc.disable(FunctionsComparator::TENSOR_NAMES);
|
||||
const auto results = fc.compare(lhs_ptr, rhs_ptr);
|
||||
return std::make_pair(results.valid, results.message);
|
||||
},
|
||||
py::arg("lhs"),
|
||||
py::arg("rhs"));
|
||||
py::arg("rhs"),
|
||||
py::arg("compare_tensor_names") = true);
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
from pathlib import Path
|
||||
|
||||
from openvino.runtime import serialize
|
||||
from openvino.tools.mo import convert
|
||||
from openvino.tools.mo.utils.ir_engine.ir_engine import IREngine
|
||||
from openvino.test_utils import compare_functions
|
||||
from openvino.tools.mo import convert_model
|
||||
|
||||
from common.utils.common_utils import generate_ir
|
||||
|
||||
@@ -16,7 +16,7 @@ class CommonMOConvertTest:
|
||||
output_dir = kwargs['output_dir']
|
||||
model_name = kwargs['model_name']
|
||||
del kwargs['output_dir']
|
||||
model = convert(**kwargs)
|
||||
model = convert_model(**kwargs)
|
||||
serialize(model, str(Path(output_dir, model_name + '.xml')))
|
||||
|
||||
def _test(self, temp_dir, test_params, ref_params):
|
||||
@@ -24,6 +24,9 @@ class CommonMOConvertTest:
|
||||
Generates two IRs using MO Python API and using cmd tool.
|
||||
Then two IRs are compared.
|
||||
"""
|
||||
from openvino.runtime import Core
|
||||
core = Core()
|
||||
|
||||
test_params.update({"model_name": 'model_test', "output_dir": temp_dir})
|
||||
ref_params.update({"model_name": 'model_ref', "output_dir": temp_dir})
|
||||
|
||||
@@ -33,19 +36,25 @@ class CommonMOConvertTest:
|
||||
assert not exit_code, (
|
||||
"Reference IR generation failed with {} exit code: {}".format(exit_code, stderr))
|
||||
|
||||
ir_test = IREngine(Path(temp_dir, 'model_test.xml'), Path(temp_dir, 'model_test.bin'))
|
||||
ir_ref = IREngine(Path(temp_dir, 'model_ref.xml'), Path(temp_dir, 'model_ref.bin'))
|
||||
flag, resp = ir_test.compare(ir_ref)
|
||||
assert flag, '\n'.join(resp)
|
||||
ir_test = core.read_model(Path(temp_dir, 'model_test.xml'))
|
||||
ir_ref = core.read_model(Path(temp_dir, 'model_ref.xml'))
|
||||
|
||||
def _test_by_ref_graph(self, temp_dir, test_params, ref_graph):
|
||||
flag, msg = compare_functions(ir_test, ir_ref)
|
||||
assert flag, '\n'.join(msg)
|
||||
|
||||
def _test_by_ref_graph(self, temp_dir, test_params, ref_graph, compare_tensor_names=True, compare_layout=True):
|
||||
"""
|
||||
Generates IR using MO Python API, reads it and compares with reference graph.
|
||||
"""
|
||||
from openvino.runtime import Core
|
||||
core = Core()
|
||||
|
||||
test_params.update({"model_name": 'model_test', "output_dir": temp_dir})
|
||||
|
||||
self.generate_ir_python_api(**test_params)
|
||||
ir_test = core.read_model(Path(temp_dir, 'model_test.xml'))
|
||||
flag, msg = compare_functions(ir_test, ref_graph, compare_tensor_names=compare_tensor_names)
|
||||
assert flag, msg
|
||||
|
||||
ir_test = IREngine(Path(temp_dir, 'model_test.xml'), Path(temp_dir, 'model_test.bin'))
|
||||
flag, resp = ir_test.compare(ref_graph)
|
||||
assert flag, '\n'.join(resp)
|
||||
if compare_layout:
|
||||
for idx in range(len(ir_test.inputs)):
|
||||
assert ir_test.inputs[idx].node.layout == ref_graph.inputs[idx].node.layout
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
|
||||
from common.mo_convert_test_class import CommonMOConvertTest
|
||||
from common.onnx_layer_test_class import save_to_onnx
|
||||
from unit_tests.utils.graph import build_graph
|
||||
|
||||
import openvino.runtime as ov
|
||||
from openvino.runtime import PartialShape, Model
|
||||
|
||||
|
||||
class TestExtensions(CommonMOConvertTest):
|
||||
def create_onnx_model(self, tmp_dir):
|
||||
@@ -77,44 +81,26 @@ class TestExtensions(CommonMOConvertTest):
|
||||
return ConversionExtension("Elu", custom_converter)
|
||||
|
||||
def create_ref_graph1():
|
||||
nodes_attributes = {
|
||||
'input': {'kind': 'op', 'type': 'Parameter'},
|
||||
'input_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'relu': {'kind': 'op', 'type': 'ReLU'},
|
||||
'relu_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'elu': {'kind': 'op', 'type': 'Elu'},
|
||||
'elu_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'result': {'kind': 'op', 'type': 'Result'}
|
||||
}
|
||||
shape = PartialShape([2, 3, 4])
|
||||
param = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param.get_output_tensor(0).set_names({"input"})
|
||||
relu = ov.opset8.relu(param)
|
||||
relu.get_output_tensor(0).set_names({"LeakyRelu_data"})
|
||||
elu = ov.opset8.elu(relu, alpha=0.1)
|
||||
elu.get_output_tensor(0).set_names({"output"})
|
||||
|
||||
return build_graph(nodes_attributes,
|
||||
[('input', 'input_data'),
|
||||
('input_data', 'relu'),
|
||||
('relu', 'relu_data'),
|
||||
('relu_data', 'elu'),
|
||||
('elu', 'elu_data'),
|
||||
('elu_data', 'result'),
|
||||
])
|
||||
return Model([elu], [param], "test")
|
||||
|
||||
def create_ref_graph2():
|
||||
nodes_attributes = {
|
||||
'input': {'kind': 'op', 'type': 'Parameter'},
|
||||
'input_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'relu': {'kind': 'op', 'type': 'ReLU'},
|
||||
'relu_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'sigmoid': {'kind': 'op', 'type': 'Sigmoid'},
|
||||
'sigmoid_data': {'shape': [2, 3, 4], 'kind': 'data'},
|
||||
'result': {'kind': 'op', 'type': 'Result'}
|
||||
}
|
||||
shape = PartialShape([2, 3, 4])
|
||||
param = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param.get_output_tensor(0).set_names({"input"})
|
||||
relu = ov.opset8.relu(param)
|
||||
relu.get_output_tensor(0).set_names({"LeakyRelu_data"})
|
||||
sigmoid = ov.opset8.sigmoid(relu)
|
||||
sigmoid.get_output_tensor(0).set_names({"output"})
|
||||
|
||||
return build_graph(nodes_attributes,
|
||||
[('input', 'input_data'),
|
||||
('input_data', 'relu'),
|
||||
('relu', 'relu_data'),
|
||||
('relu_data', 'sigmoid'),
|
||||
('sigmoid', 'sigmoid_data'),
|
||||
('sigmoid_data', 'result'),
|
||||
])
|
||||
return Model([sigmoid], [param], "test")
|
||||
|
||||
test_data = [
|
||||
{'params_test': {'extensions': create_custom_extension_leaky_relu_to_relu()},
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
|
||||
import numpy
|
||||
import numpy as np
|
||||
import openvino.runtime as ov
|
||||
import pytest
|
||||
import torch
|
||||
from openvino.runtime import PartialShape, Dimension, Model
|
||||
|
||||
from common.mo_convert_test_class import CommonMOConvertTest
|
||||
|
||||
|
||||
def make_pt_model_one_input():
|
||||
from torch import nn
|
||||
class NeuralNetwork(nn.Module):
|
||||
def __init__(self):
|
||||
super(NeuralNetwork, self).__init__()
|
||||
self.linear_relu_stack = nn.Sequential(
|
||||
nn.ReLU(),
|
||||
nn.Sigmoid(),
|
||||
)
|
||||
|
||||
def forward(self, x):
|
||||
logits = self.linear_relu_stack(x)
|
||||
return logits
|
||||
|
||||
return NeuralNetwork()
|
||||
|
||||
|
||||
def make_pt_model_two_inputs():
|
||||
from torch import nn
|
||||
class NeuralNetwork(nn.Module):
|
||||
def __init__(self):
|
||||
super(NeuralNetwork, self).__init__()
|
||||
self.linear_relu_stack = nn.Sequential(
|
||||
nn.ReLU(),
|
||||
nn.Sigmoid(),
|
||||
)
|
||||
|
||||
def forward(self, x, y):
|
||||
logits = self.linear_relu_stack(x + y)
|
||||
return logits
|
||||
|
||||
return NeuralNetwork()
|
||||
|
||||
|
||||
def make_ref_pt_model_one_input(shape, dtype=np.float32):
|
||||
shape = PartialShape(shape)
|
||||
param1 = ov.opset8.parameter(shape, name="input_0", dtype=dtype)
|
||||
relu = ov.opset8.relu(param1)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1]
|
||||
model = Model([sigm], parameter_list, "test")
|
||||
return model
|
||||
|
||||
|
||||
def make_ref_pt_model_two_inputs(shape, dtype=np.float32):
|
||||
if len(shape) == 2:
|
||||
param1 = ov.opset8.parameter(PartialShape(shape[0]), name="input_0", dtype=dtype)
|
||||
param2 = ov.opset8.parameter(PartialShape(shape[1]), name="input_1", dtype=dtype)
|
||||
else:
|
||||
shape = PartialShape(shape)
|
||||
param1 = ov.opset8.parameter(shape, name="input_0", dtype=dtype)
|
||||
param2 = ov.opset8.parameter(shape, name="input_1", dtype=dtype)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model = Model([sigm], parameter_list, "test")
|
||||
return model
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case1(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
ref_model = make_ref_pt_model_two_inputs([-1, 3, -1, -1])
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input = sample_input1, sample_input2
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [PartialShape([-1, 3, -1, -1]), PartialShape([-1, 3, -1, -1])],
|
||||
'example_input': sample_input}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case2(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
ref_model = make_ref_pt_model_two_inputs([-1, 3, -1, -1])
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input = sample_input1, sample_input2
|
||||
|
||||
return pt_model, ref_model, {'input_shape': ["[?,3,?,?]", PartialShape([-1, 3, -1, -1])],
|
||||
'example_input': sample_input, 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case3(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
ref_model = make_ref_pt_model_two_inputs([-1, 3, -1, -1])
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10)
|
||||
sample_input = tuple([sample_input1, sample_input2])
|
||||
|
||||
return pt_model, ref_model, {'input_shape': "[?,3,?,?],[?,3,?,?]", 'example_input': sample_input}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case4(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
sample_input = torch.zeros(1, 3, 10, 10)
|
||||
|
||||
ref_model = make_ref_pt_model_one_input([1, 3, 10, 10])
|
||||
|
||||
return pt_model, ref_model, {'example_input': sample_input}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case5(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
inp_shape = PartialShape([-1, 3, Dimension(2, -1), Dimension(-1, 10)])
|
||||
ref_model = make_ref_pt_model_one_input(inp_shape)
|
||||
|
||||
sample_input = torch.zeros(3, 3, 10, 10)
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'input_shape': inp_shape}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_case6(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
shape = PartialShape([1, 3, Dimension(2, -1), Dimension(-1, 10)])
|
||||
ref_model = make_ref_pt_model_one_input(shape)
|
||||
|
||||
return pt_model, ref_model, {'input_shape': shape}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_torch_size(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
ref_model = make_ref_pt_model_one_input([1, 3, 2, 10])
|
||||
|
||||
return pt_model, ref_model, {'input_shape': torch.Size([1, 3, 2, 10])}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_int32(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
shape = PartialShape([-1, 3, Dimension(2, -1), Dimension(-1, 10)])
|
||||
|
||||
sample_input = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
|
||||
ref_model = make_ref_pt_model_one_input(shape, dtype=numpy.int32)
|
||||
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'input_shape': shape}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_int32_two_inputs(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
inp_shapes = ["[?,3,?,?]", PartialShape([-1, 3, -1, -1])]
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input = sample_input1, sample_input2
|
||||
ref_model = make_ref_pt_model_two_inputs([PartialShape([-1, 3, -1, -1]), inp_shapes[1]], dtype=np.int32)
|
||||
|
||||
return pt_model, ref_model, {'input_shape': inp_shapes,
|
||||
'example_input': sample_input, 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case1(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
sample_input = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': sample_input, 'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case2(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
sample_input = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'input_shape': [1, 3, 10, 10],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case3(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
sample_input = torch.zeros(1, 3, 10, 10, dtype=torch.float32)
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'input_shape': [1, 3, 10, 10],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case4(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input = (sample_input1, sample_input2)
|
||||
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
|
||||
return pt_model, ref_model, {'example_input': sample_input, 'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case5(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10, dtype=torch.int32)
|
||||
sample_input = tuple([sample_input1, sample_input2])
|
||||
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'input_shape': [torch.Size([1, 3, 10, 10]), PartialShape([1, 3, 10, 10])],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_compare_convert_paths_case6(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
|
||||
sample_input1 = torch.zeros(1, 3, 10, 10, dtype=torch.float32)
|
||||
sample_input2 = torch.zeros(1, 3, 10, 10, dtype=torch.float32)
|
||||
sample_input = tuple([sample_input1, sample_input2])
|
||||
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, sample_input, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [torch.Size([1, 3, 10, 10]), torch.Size([1, 3, 10, 10])],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_jit_script_module(tmp_dir):
|
||||
import torch
|
||||
|
||||
net = make_pt_model_two_inputs()
|
||||
scripted_model = torch.jit.script(net)
|
||||
|
||||
model_ref = make_ref_pt_model_two_inputs([1, 3, 5, 5])
|
||||
return scripted_model, model_ref, {'input_shape': [PartialShape([1, 3, 5, 5]), PartialShape([1, 3, 5, 5])]}
|
||||
|
||||
|
||||
def create_pytorch_jit_script_function(tmp_dir):
|
||||
import torch
|
||||
|
||||
@torch.jit.script
|
||||
def scripted_fn(x: torch.Tensor, y: torch.Tensor):
|
||||
return torch.sigmoid(torch.relu(x + y))
|
||||
|
||||
inp_shape = PartialShape([Dimension(1, -1), Dimension(-1, 5), 10])
|
||||
ref_model = make_ref_pt_model_two_inputs(inp_shape)
|
||||
return scripted_fn, ref_model, {'input_shape': [inp_shape, inp_shape]}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_numpy(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
example_inputs = np.array(torch.zeros(1, 3, 10, 10, dtype=torch.int32))
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, torch.zeros(1, 3, 10, 10, dtype=torch.int32), onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': example_inputs,
|
||||
'input_shape': [1, 3, 10, 10],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_dict(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
example_inputs = {"x": np.array(torch.zeros(1, 3, 10, 10, dtype=torch.int32))}
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, torch.zeros(1, 3, 10, 10, dtype=torch.int32), onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': example_inputs,
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_dict_two_inputs(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
|
||||
example_inputs = {"y": np.array(torch.zeros(1, 3, 10, 10, dtype=torch.int32)),
|
||||
"x": np.array(torch.zeros(1, 3, 10, 10, dtype=torch.int32))}
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, {"y": torch.zeros(1, 3, 10, 10, dtype=torch.int32),
|
||||
"x": torch.zeros(1, 3, 10, 10, dtype=torch.int32)}, onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': example_inputs,
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_list_of_tensors(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
example_inputs = [torch.zeros(3, 10, 10, dtype=torch.float32)]
|
||||
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, torch.unsqueeze(example_inputs[0], 0), onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': example_inputs,
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_ov_host_tensor(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
from openvino.runtime import Tensor
|
||||
pt_model = make_pt_model_one_input()
|
||||
|
||||
sample_input = Tensor(np.zeros([1, 3, 10, 10], dtype=np.int32))
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, torch.zeros(1, 3, 10, 10, dtype=torch.int32), onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'input_shape': [1, 3, 10, 10],
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_sample_input_ov_host_tensor_two_inputs(tmp_dir):
|
||||
from openvino.tools.mo import convert_model
|
||||
from openvino.runtime import Tensor
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
|
||||
sample_input1 = Tensor(np.zeros([1, 3, 10, 10], dtype=np.int32))
|
||||
sample_input2 = Tensor(np.zeros([1, 3, 10, 10], dtype=np.int32))
|
||||
sample_input = sample_input1, sample_input2
|
||||
|
||||
onnx_model_path = os.path.join(tmp_dir, 'export.onnx')
|
||||
torch.onnx.export(pt_model, tuple([torch.zeros(1, 3, 10, 10, dtype=torch.int32),
|
||||
torch.zeros(1, 3, 10, 10, dtype=torch.int32)]),
|
||||
onnx_model_path, opset_version=16)
|
||||
|
||||
ref_model = convert_model(onnx_model_path)
|
||||
|
||||
return pt_model, ref_model, {'example_input': sample_input,
|
||||
'onnx_opset_version': 16}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_layout_list(tmp_dir):
|
||||
from openvino.runtime import Layout
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
shape = [1, 3, 10, 10]
|
||||
|
||||
shape = PartialShape(shape)
|
||||
ref_model = make_ref_pt_model_two_inputs(shape)
|
||||
ref_model.inputs[0].node.layout = Layout('nchw')
|
||||
ref_model.inputs[1].node.layout = Layout('nhwc')
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [shape, shape], 'layout': ['nchw', Layout('nhwc')],
|
||||
'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_layout_list_case2(tmp_dir):
|
||||
from openvino.runtime import Layout
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
shape = [1, 3, 10, 10]
|
||||
|
||||
shape = PartialShape(shape)
|
||||
ref_model = make_ref_pt_model_two_inputs(shape)
|
||||
ref_model.inputs[0].node.layout = Layout('nchw')
|
||||
ref_model.inputs[1].node.layout = Layout('nhwc')
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [shape, shape], 'layout': ('nchw', Layout('nhwc')),
|
||||
'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_mean_list(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
shape = [1, 10, 10, 3]
|
||||
|
||||
shape = PartialShape(shape)
|
||||
param1 = ov.opset8.parameter(shape)
|
||||
param2 = ov.opset8.parameter(shape)
|
||||
const1 = ov.opset8.constant([[[[0, 0, 0]]]], dtype=np.float32)
|
||||
const2 = ov.opset8.constant([[[[0, 0, 0]]]], dtype=np.float32)
|
||||
sub1 = ov.opset8.subtract(param1, const1)
|
||||
sub2 = ov.opset8.subtract(param2, const2)
|
||||
add = ov.opset8.add(sub1, sub2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
ref_model = Model([sigm], parameter_list, "test")
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [shape, shape], 'mean_values': [[0, 0, 0], [0, 0, 0]],
|
||||
'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_scale_list(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
shape = [1, 10, 10, 3]
|
||||
|
||||
shape = PartialShape(shape)
|
||||
param1 = ov.opset8.parameter(shape)
|
||||
param2 = ov.opset8.parameter(shape)
|
||||
const1 = ov.opset8.constant([[[[1, 1, 1]]]], dtype=np.float32)
|
||||
const2 = ov.opset8.constant([[[[1, 1, 1]]]], dtype=np.float32)
|
||||
sub1 = ov.opset8.multiply(param1, const1)
|
||||
sub2 = ov.opset8.multiply(param2, const2)
|
||||
add = ov.opset8.add(sub1, sub2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
ref_model = Model([sigm], parameter_list, "test")
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [shape, shape], 'scale_values': [[1, 1, 1], [1, 1, 1]],
|
||||
'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_shapes_list_static(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
ref_model = make_ref_pt_model_two_inputs([1, 3, 20, 20])
|
||||
|
||||
return pt_model, ref_model, {'input_shape': [[1, 3, 20, 20], [1, 3, 20, 20]], 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_shapes_list_dynamic(tmp_dir):
|
||||
pt_model = make_pt_model_two_inputs()
|
||||
inp_shapes = [[Dimension(-1), 3, 20, Dimension(20, -1)], [-1, 3, 20, Dimension(-1, 20)]]
|
||||
|
||||
param1 = ov.opset8.parameter(PartialShape(inp_shapes[0]), name="input_0", dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(PartialShape(inp_shapes[1]), name="input_1", dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
ref_model = Model([sigm], parameter_list, "test")
|
||||
return pt_model, ref_model, {'input_shape': inp_shapes, 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_shapes_list_dynamic_single_input(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
inp_shapes = [[Dimension(-1), 3, 20, Dimension(20, -1)]]
|
||||
ref_model = make_ref_pt_model_one_input(inp_shapes[0])
|
||||
return pt_model, ref_model, {'input_shape': inp_shapes, 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
def create_pytorch_nn_module_shapes_list_static_single_input(tmp_dir):
|
||||
pt_model = make_pt_model_one_input()
|
||||
inp_shapes = [[1, 3, 20, 20]]
|
||||
ref_model = make_ref_pt_model_one_input(inp_shapes[0])
|
||||
return pt_model, ref_model, {'input_shape': inp_shapes, 'onnx_opset_version': 11}
|
||||
|
||||
|
||||
class TestMoConvertPyTorch(CommonMOConvertTest):
|
||||
test_data = [
|
||||
create_pytorch_nn_module_case1,
|
||||
create_pytorch_nn_module_case2,
|
||||
create_pytorch_nn_module_case3,
|
||||
create_pytorch_nn_module_case4,
|
||||
create_pytorch_nn_module_case5,
|
||||
create_pytorch_nn_module_case6,
|
||||
create_pytorch_nn_module_torch_size,
|
||||
create_pytorch_nn_module_sample_input_int32,
|
||||
create_pytorch_nn_module_sample_input_int32_two_inputs,
|
||||
create_pytorch_nn_module_compare_convert_paths_case1,
|
||||
create_pytorch_nn_module_compare_convert_paths_case2,
|
||||
create_pytorch_nn_module_compare_convert_paths_case4,
|
||||
create_pytorch_nn_module_compare_convert_paths_case5,
|
||||
create_pytorch_nn_module_compare_convert_paths_case6,
|
||||
create_pytorch_nn_module_sample_input_numpy,
|
||||
create_pytorch_nn_module_sample_input_ov_host_tensor,
|
||||
create_pytorch_nn_module_sample_input_ov_host_tensor_two_inputs,
|
||||
create_pytorch_nn_module_sample_input_dict,
|
||||
create_pytorch_nn_module_sample_input_dict_two_inputs,
|
||||
create_pytorch_nn_module_sample_list_of_tensors,
|
||||
create_pytorch_jit_script_module,
|
||||
create_pytorch_jit_script_function,
|
||||
create_pytorch_nn_module_layout_list,
|
||||
create_pytorch_nn_module_layout_list_case2,
|
||||
create_pytorch_nn_module_mean_list,
|
||||
create_pytorch_nn_module_scale_list,
|
||||
create_pytorch_nn_module_shapes_list_static,
|
||||
create_pytorch_nn_module_shapes_list_dynamic,
|
||||
create_pytorch_nn_module_shapes_list_dynamic_single_input,
|
||||
create_pytorch_nn_module_shapes_list_static_single_input
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("create_model", test_data)
|
||||
@pytest.mark.nightly
|
||||
@pytest.mark.precommit
|
||||
def test_mo_import_from_memory(self, create_model, ie_device, precision, ir_version,
|
||||
temp_dir, use_new_frontend, use_old_api):
|
||||
fw_model, graph_ref, mo_params = create_model(temp_dir)
|
||||
|
||||
test_params = {'input_model': fw_model}
|
||||
if mo_params is not None:
|
||||
test_params.update(mo_params)
|
||||
self._test_by_ref_graph(temp_dir, test_params, graph_ref, compare_tensor_names=False)
|
||||
@@ -0,0 +1,356 @@
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import numpy as np
|
||||
import openvino.runtime as ov
|
||||
import pytest
|
||||
from openvino.runtime import PartialShape, Model, Dimension
|
||||
|
||||
from common.mo_convert_test_class import CommonMOConvertTest
|
||||
|
||||
|
||||
def create_tf_graph_def(tmp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
tf.compat.v1.reset_default_graph()
|
||||
|
||||
with tf.compat.v1.Session() as sess:
|
||||
inp1 = tf.compat.v1.placeholder(tf.float32, [1, 2, 3], 'Input')
|
||||
inp2 = tf.compat.v1.placeholder(tf.float32, [1, 2, 3], 'Input')
|
||||
relu = tf.nn.relu(inp1 + inp2, name='Relu')
|
||||
|
||||
output = tf.nn.sigmoid(relu, name='Sigmoid')
|
||||
|
||||
tf.compat.v1.global_variables_initializer()
|
||||
tf_net = sess.graph_def
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
return tf_net, model_ref, None
|
||||
|
||||
|
||||
def create_keras_model(temp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
tf.keras.backend.clear_session()
|
||||
tf.compat.v1.reset_default_graph()
|
||||
|
||||
input_names = ["Input1", "Input2"]
|
||||
input_shape = [1, 2, 3]
|
||||
|
||||
x1 = tf.keras.Input(shape=input_shape, name=input_names[0])
|
||||
x2 = tf.keras.Input(shape=input_shape, name=input_names[1])
|
||||
y = tf.nn.sigmoid(tf.nn.relu(x1 + x2))
|
||||
keras_net = tf.keras.Model(inputs=[x1, x2], outputs=[y])
|
||||
|
||||
shape = PartialShape([-1, 1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
tf.keras.backend.clear_session()
|
||||
|
||||
return keras_net, model_ref, None
|
||||
|
||||
|
||||
def create_tf1_wrap_function(tmp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
def f(x, y):
|
||||
return tf.nn.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
func = tf.compat.v1.wrap_function(f, [tf.TensorSpec((1, 2, 3), tf.float32),
|
||||
tf.TensorSpec((1, 2, 3), tf.float32)])
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
return func, model_ref, None
|
||||
|
||||
|
||||
def create_tf_session(tmp_dir):
|
||||
import tensorflow as tf
|
||||
from tensorflow.python.eager.context import graph_mode
|
||||
|
||||
|
||||
with graph_mode():
|
||||
tf.compat.v1.reset_default_graph()
|
||||
sess = tf.compat.v1.Session()
|
||||
inp1 = tf.compat.v1.placeholder(tf.float32, [1, 2, 3], 'Input1')
|
||||
inp2 = tf.compat.v1.placeholder(tf.float32, [1, 2, 3], 'Input2')
|
||||
relu = tf.nn.relu(inp1 + inp2, name='Relu')
|
||||
|
||||
output = tf.nn.sigmoid(relu, name='Sigmoid')
|
||||
|
||||
tf.compat.v1.global_variables_initializer()
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
return sess, model_ref, None
|
||||
|
||||
|
||||
def create_tf_module(tmp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
class Net(tf.Module):
|
||||
def __init__(self, name=None):
|
||||
super(Net, self).__init__(name=name)
|
||||
|
||||
def __call__(self, x, y):
|
||||
return tf.nn.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
net = Net()
|
||||
return net, model_ref, {'input_shape': [PartialShape([1, 2, 3]), PartialShape([1, 2, 3])]}
|
||||
|
||||
|
||||
def create_tf_module_layout_list(tmp_dir):
|
||||
from openvino.runtime import Layout
|
||||
import tensorflow as tf
|
||||
|
||||
class Net(tf.Module):
|
||||
def __init__(self, name=None):
|
||||
super(Net, self).__init__(name=name)
|
||||
|
||||
def __call__(self, x, y):
|
||||
return tf.nn.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
model_ref.inputs[0].node.layout = Layout('NCH')
|
||||
model_ref.inputs[1].node.layout = Layout('NHC')
|
||||
|
||||
net = Net()
|
||||
return net, model_ref, {'input_shape': [PartialShape([1, 2, 3]), PartialShape([1, 2, 3])], 'layout': ["NCH", "NHC"]}
|
||||
|
||||
|
||||
def create_tf_module_dynamic(tmp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
class Net(tf.Module):
|
||||
def __init__(self, name=None):
|
||||
super(Net, self).__init__(name=name)
|
||||
|
||||
def __call__(self, x, y):
|
||||
return tf.nn.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
shape = PartialShape([-1, 3, 4])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
net = Net()
|
||||
return net, model_ref, {'input_shape': [PartialShape([-1, Dimension(3, -1), Dimension(4)]),
|
||||
PartialShape([-1, Dimension(3), Dimension(4, -1)])]}
|
||||
|
||||
def create_keras_layer(tmp_dir):
|
||||
import tensorflow as tf
|
||||
class LayerModel(tf.keras.layers.Layer):
|
||||
|
||||
def __init__(self):
|
||||
super(LayerModel, self).__init__()
|
||||
|
||||
def call(self, x, y):
|
||||
return tf.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
shape = PartialShape([1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
net = LayerModel()
|
||||
return net, model_ref, {'input_shape': [PartialShape([1, 2, 3]), PartialShape([1, 2, 3])]}
|
||||
|
||||
def create_keras_layer_dynamic(tmp_dir):
|
||||
import tensorflow as tf
|
||||
class LayerModel(tf.keras.layers.Layer):
|
||||
|
||||
def __init__(self):
|
||||
super(LayerModel, self).__init__()
|
||||
|
||||
def call(self, x, y):
|
||||
return tf.sigmoid(tf.nn.relu(x + y))
|
||||
|
||||
shape = PartialShape([-1, 3, 4])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
net = LayerModel()
|
||||
return net, model_ref, {'input_shape': [PartialShape([-1, Dimension(3, -1), Dimension(4)]),
|
||||
PartialShape([-1, Dimension(3), Dimension(4, -1)])]}
|
||||
|
||||
|
||||
def create_tf_checkpoint(tmp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
input_names = ["Input1", "Input2"]
|
||||
input_shape = [1, 2, 3]
|
||||
|
||||
x1 = tf.keras.Input(shape=input_shape, name=input_names[0])
|
||||
x2 = tf.keras.Input(shape=input_shape, name=input_names[1])
|
||||
y = tf.nn.sigmoid(tf.nn.relu(x1 + x2))
|
||||
|
||||
model = tf.keras.Model(inputs=[x1, x2], outputs=[y])
|
||||
checkpoint = tf.train.Checkpoint(model)
|
||||
|
||||
shape = PartialShape([-1, 1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
return checkpoint, model_ref, None
|
||||
|
||||
|
||||
def create_tf_function(temp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
input_names = ["Input1", "Input2"]
|
||||
input_shape = [1, 2, 3]
|
||||
|
||||
x1 = tf.keras.Input(shape=input_shape, name=input_names[0])
|
||||
x2 = tf.keras.Input(shape=input_shape, name=input_names[1])
|
||||
y = tf.nn.sigmoid(tf.nn.relu(x1 + x2))
|
||||
keras_net = tf.keras.Model(inputs=[x1, x2], outputs=[y])
|
||||
|
||||
@tf.function(
|
||||
input_signature=[tf.TensorSpec(shape=[1, 2, 3], dtype=tf.float32),
|
||||
tf.TensorSpec(shape=[1, 2, 3], dtype=tf.float32)])
|
||||
def f(x):
|
||||
return keras_net(x)
|
||||
|
||||
shape = PartialShape([-1, 1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
return keras_net, model_ref, None
|
||||
|
||||
|
||||
def create_tf_saved_model(temp_dir):
|
||||
import tensorflow as tf
|
||||
|
||||
input_names = ["Input1", "Input2"]
|
||||
input_shape = [1, 2, 3]
|
||||
|
||||
x1 = tf.keras.Input(shape=input_shape, name=input_names[0])
|
||||
x2 = tf.keras.Input(shape=input_shape, name=input_names[1])
|
||||
y = tf.nn.sigmoid(tf.nn.relu(x1 + x2))
|
||||
keras_net = tf.keras.Model(inputs=[x1, x2], outputs=[y])
|
||||
|
||||
shape = PartialShape([-1, 1, 2, 3])
|
||||
param1 = ov.opset8.parameter(shape, name="Input1:0", dtype=np.float32)
|
||||
param2 = ov.opset8.parameter(shape, name="Input2:0", dtype=np.float32)
|
||||
add = ov.opset8.add(param1, param2)
|
||||
relu = ov.opset8.relu(add)
|
||||
sigm = ov.opset8.sigmoid(relu)
|
||||
|
||||
parameter_list = [param1, param2]
|
||||
model_ref = Model([sigm], parameter_list, "test")
|
||||
|
||||
tf.saved_model.save(keras_net, temp_dir + "/model")
|
||||
saved_model = tf.saved_model.load(temp_dir + "/model")
|
||||
|
||||
return saved_model, model_ref, None
|
||||
|
||||
|
||||
class TestMoConvertTF(CommonMOConvertTest):
|
||||
test_data = [
|
||||
# TF2
|
||||
create_keras_model,
|
||||
create_keras_layer,
|
||||
create_tf_function,
|
||||
create_tf_module,
|
||||
create_tf_checkpoint,
|
||||
create_tf_saved_model,
|
||||
create_keras_layer_dynamic,
|
||||
create_tf_module_dynamic,
|
||||
create_tf_module_layout_list,
|
||||
|
||||
|
||||
# TF1
|
||||
create_tf_graph_def,
|
||||
create_tf1_wrap_function,
|
||||
create_tf_session,
|
||||
]
|
||||
|
||||
@pytest.mark.parametrize("create_model", test_data)
|
||||
@pytest.mark.nightly
|
||||
@pytest.mark.precommit_tf_fe
|
||||
@pytest.mark.precommit
|
||||
def test_mo_import_from_memory(self, create_model, ie_device, precision, ir_version,
|
||||
temp_dir, use_new_frontend, use_old_api):
|
||||
fw_model, graph_ref, mo_params = create_model(temp_dir)
|
||||
|
||||
test_params = {'input_model': fw_model}
|
||||
if mo_params is not None:
|
||||
test_params.update(mo_params)
|
||||
self._test_by_ref_graph(temp_dir, test_params, graph_ref, compare_tensor_names=False)
|
||||
@@ -1,2 +1,4 @@
|
||||
requests>=2.25.1
|
||||
numpy>=1.19.2
|
||||
torch
|
||||
pytest
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2018-2022 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
from .convert import convert, InputCutInfo, LayoutMap
|
||||
from .convert import convert_model, InputCutInfo, LayoutMap
|
||||
|
||||
@@ -59,6 +59,32 @@ def update_mean_scale_to_dict(input_nodes: list, mean_scale_val, scale):
|
||||
return mean_scale_val
|
||||
|
||||
|
||||
def update_layout_to_dict(input_nodes: list, layout: [list, dict]):
|
||||
"""
|
||||
Internal function. Updates layout values from array to dictionary
|
||||
:param: input_nodes Inputs of model
|
||||
:param: layout Parsed 'layout' object from command line arguments
|
||||
"""
|
||||
if isinstance(layout, dict):
|
||||
return layout
|
||||
if isinstance(layout, list):
|
||||
if len(layout) != len(input_nodes):
|
||||
raise Error('Numbers of inputs and mean/scale values do not match. ' + refer_to_faq_msg(61))
|
||||
layout_dict = {}
|
||||
for idx, node in enumerate(input_nodes):
|
||||
names_list = list(node.get_tensor().get_names())
|
||||
if not names_list:
|
||||
raise Error("Empty tensor names list for node {}".format(node.name))
|
||||
node_name = names_list[0]
|
||||
layout_dict.update(
|
||||
{
|
||||
node_name: layout[idx]
|
||||
}
|
||||
)
|
||||
return layout_dict
|
||||
raise Error("Unknown layout type. Expected dict, list. Got {}".format(type(layout)))
|
||||
|
||||
|
||||
def check_keys_valid(ov_function: Model, dict_to_validate: dict, search_outputs: bool):
|
||||
"""
|
||||
Internal function: checks if keys from cmd line arguments correspond to ov_function's inputs/outputs
|
||||
@@ -360,7 +386,7 @@ def apply_preprocessing(ov_function: Model, argv: argparse.Namespace):
|
||||
|
||||
layout_values = {}
|
||||
if 'layout_values' in argv and argv.layout_values:
|
||||
layout_values = argv.layout_values
|
||||
layout_values = update_layout_to_dict(ov_function.inputs, argv.layout_values)
|
||||
|
||||
if '' in layout_values:
|
||||
if len(ov_function.inputs) > 1:
|
||||
|
||||
@@ -8,15 +8,36 @@ InputCutInfo = namedtuple("InputInfo", ["name", "shape", "type", "value"])
|
||||
LayoutMap = namedtuple("LayoutMap", ["source_layout", "target_layout"])
|
||||
|
||||
|
||||
def convert(input_model=None, **args):
|
||||
def convert_model(input_model=None, **args):
|
||||
"""
|
||||
Converts the model from original framework to OpenVino Model.
|
||||
|
||||
Args:
|
||||
input_model:
|
||||
Model object in original framework (PyTorch, Tensorflow) or path to model file.
|
||||
Tensorflow*: a file with a pre-trained model (binary or text .pb file after freezing).
|
||||
Caffe*: a model proto file with model weights
|
||||
|
||||
Supported formats of input model:
|
||||
|
||||
PyTorch
|
||||
torch.nn.Module
|
||||
torch.jit.ScriptModule
|
||||
torch.jit.ScriptFunction
|
||||
|
||||
TF
|
||||
tf.compat.v1.GraphDef
|
||||
tf.compat.v1.wrap_function
|
||||
tf.compat.v1.session
|
||||
|
||||
TF2 / Keras
|
||||
tf.keras.Model
|
||||
tf.keras.layers.Layer
|
||||
tf.function
|
||||
tf.Module
|
||||
tf.train.checkpoint
|
||||
tf.python.training.tracking.base.Trackable for case when it is output from tf.saved_model.load()
|
||||
|
||||
Run convert(help=true) to list all available parameters.
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -10,6 +10,8 @@ import sys
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
|
||||
try:
|
||||
import openvino_telemetry as tm
|
||||
except ImportError:
|
||||
@@ -30,7 +32,7 @@ from openvino.tools.mo.utils.cli_parser import check_available_transforms, \
|
||||
get_common_cli_options, get_freeze_placeholder_values, get_kaldi_cli_options, get_layout_values, \
|
||||
get_mean_scale_dictionary, get_mxnet_cli_options, get_onnx_cli_options, \
|
||||
get_placeholder_shapes, get_tf_cli_options, get_tuple_values, parse_transform, parse_tuple_pairs, \
|
||||
get_all_cli_parser, mo_convert_params, get_model_name_from_args, depersonalize
|
||||
get_all_cli_parser, mo_convert_params, get_model_name_from_args, split_shapes, depersonalize
|
||||
|
||||
from openvino.tools.mo.utils.error import Error
|
||||
from openvino.tools.mo.utils.find_ie_version import find_ie_version
|
||||
@@ -46,6 +48,7 @@ from openvino.tools.mo.moc_frontend.check_config import legacy_extensions_used
|
||||
|
||||
# pylint: disable=no-name-in-module,import-error
|
||||
from openvino.frontend import FrontEndManager, ProgressReporterExtension, TelemetryExtension, JsonConfigExtension
|
||||
from openvino.runtime import PartialShape, Dimension
|
||||
from openvino.runtime import get_version as get_rt_version
|
||||
|
||||
|
||||
@@ -158,6 +161,9 @@ def arguments_post_parsing(argv: argparse.Namespace):
|
||||
'Please use --framework with one from the list: {}.',
|
||||
'--input_model', argv.input_model, frameworks)
|
||||
elif argv.framework not in frameworks:
|
||||
if argv.framework == 'ir':
|
||||
raise Error('OpenVINO IR is passed as input_model in convert_model/mo, the IR doesn\'t need '
|
||||
'conversion, please use it in runtime for inference with read_model/compile_model.')
|
||||
raise Error('Framework {} is not a valid target. Please use --framework with one from the list: {}. ' +
|
||||
refer_to_faq_msg(15), argv.framework, frameworks)
|
||||
|
||||
@@ -486,6 +492,229 @@ def emit_ir(graph: Graph, argv: argparse.Namespace, non_default_params: dict):
|
||||
return func
|
||||
|
||||
|
||||
def get_static_shape(shape: [PartialShape, list, tuple], dynamic_value=None):
|
||||
# Current function returns list with static dimensions with following logic.
|
||||
# For dynamic dimensions return lower boundaries if they are set, otherwise
|
||||
# return upper boundaries if they are set. If dimension is fully dynamic then raise error.
|
||||
shape_list = []
|
||||
for idx, dim in enumerate(shape):
|
||||
if isinstance(dim, int):
|
||||
if dim == -1:
|
||||
shape_list.append(dynamic_value)
|
||||
continue
|
||||
shape_list.append(dim)
|
||||
elif isinstance(dim, np.int64):
|
||||
if dim == np.int64(-1):
|
||||
shape_list.append(dynamic_value)
|
||||
continue
|
||||
shape_list.append(dim)
|
||||
elif isinstance(dim, tuple):
|
||||
# tuple where (min_length, max_length), the format which uses MO cli parser
|
||||
assert len(dim) == 2, "Unknown dimension type {}".format(dim)
|
||||
if dim[0] > 0:
|
||||
shape_list.append(dim[0])
|
||||
elif dim[1] < np.iinfo(np.int64).max:
|
||||
shape_list.append(dim[1])
|
||||
else:
|
||||
shape_list.append(dynamic_value)
|
||||
continue
|
||||
elif isinstance(dim, Dimension):
|
||||
if dim.is_static or dim.get_min_length() > 0:
|
||||
shape_list.append(dim.get_min_length())
|
||||
elif dim.get_max_length() != -1:
|
||||
shape_list.append(dim.get_max_length())
|
||||
else:
|
||||
shape_list.append(dynamic_value)
|
||||
continue
|
||||
else:
|
||||
raise Error("Unknown dimension type {}".format(dim))
|
||||
|
||||
return tuple(shape_list)
|
||||
|
||||
|
||||
def get_dynamic_dims(shape: [PartialShape, list, tuple]):
|
||||
dynamic_dims = []
|
||||
for idx, dim in enumerate(shape):
|
||||
if isinstance(dim, int):
|
||||
if dim == -1:
|
||||
dynamic_dims.append(idx)
|
||||
if isinstance(dim, np.int64):
|
||||
if dim == np.int64(-1):
|
||||
dynamic_dims.append(idx)
|
||||
elif isinstance(dim, tuple):
|
||||
dynamic_dims.append(idx)
|
||||
elif isinstance(dim, Dimension):
|
||||
if dim.get_min_length() == 0 and dim.get_max_length() == -1:
|
||||
dynamic_dims.append(idx)
|
||||
|
||||
return dynamic_dims
|
||||
|
||||
|
||||
def check_model_object(argv):
|
||||
model = argv['input_model']
|
||||
if 'tensorflow' in sys.modules:
|
||||
import tensorflow as tf
|
||||
from tensorflow.python.training.tracking.base import Trackable
|
||||
|
||||
if isinstance(model, tf.compat.v1.GraphDef):
|
||||
return "tf"
|
||||
if isinstance(model, tf.compat.v1.Session):
|
||||
argv['input_model'] = model.graph_def
|
||||
return "tf"
|
||||
if isinstance(model, tf.types.experimental.ConcreteFunction):
|
||||
argv['input_model'] = model.graph.as_graph_def()
|
||||
return "tf"
|
||||
if isinstance(model, tf.keras.Model):
|
||||
return "tf"
|
||||
if isinstance(model, tf.train.Checkpoint):
|
||||
if isinstance(model.root, tf.keras.Model):
|
||||
argv['input_model'] = model.root
|
||||
return "tf"
|
||||
else:
|
||||
raise Error("Unknown checkpoint format.")
|
||||
|
||||
if isinstance(model, tf.keras.layers.Layer) or isinstance(model, tf.Module):
|
||||
assert 'input_shape' in argv and argv['input_shape'] is not None, \
|
||||
"Converting of {} requires providing of input_shape.".format(type(model))
|
||||
assert len(argv['input_shape']) > 0, "Please provide non-empty input shape."
|
||||
inputs = []
|
||||
for shape_idx, shape in enumerate(parse_input_shapes(argv)):
|
||||
inp_shape = get_static_shape(shape)
|
||||
batch_size = None
|
||||
if len(inp_shape) > 1:
|
||||
batch_size = inp_shape[0]
|
||||
inp_shape = inp_shape[1:]
|
||||
inputs.append(tf.keras.Input(shape=inp_shape, batch_size=batch_size))
|
||||
outputs = model(*inputs)
|
||||
argv['input_model'] = tf.keras.Model(inputs, outputs)
|
||||
argv['input_shape'] = None
|
||||
return "tf"
|
||||
if isinstance(model, Trackable):
|
||||
return "tf"
|
||||
if 'torch' in sys.modules:
|
||||
import torch
|
||||
if isinstance(model, torch.nn.Module) or isinstance(model, torch.jit.ScriptFunction):
|
||||
return "pytorch"
|
||||
|
||||
import io
|
||||
if isinstance(model, io.BytesIO):
|
||||
return 'onnx'
|
||||
|
||||
raise Error('Unknown model type: {}'.format(type(model)))
|
||||
|
||||
|
||||
def get_onnx_temp_filename(output_dir):
|
||||
output_dir = output_dir if output_dir is not None else os.getcwd()
|
||||
return os.path.normpath(os.path.join(output_dir, "model.onnx"))
|
||||
|
||||
|
||||
def to_torch_tensor(tensor):
|
||||
import torch
|
||||
from openvino.runtime import Tensor
|
||||
if isinstance(tensor, torch.Tensor):
|
||||
return tensor
|
||||
if isinstance(tensor, np.ndarray):
|
||||
return torch.tensor(tensor)
|
||||
if isinstance(tensor, np.ndarray):
|
||||
return torch.tensor(tensor)
|
||||
if isinstance(tensor, Tensor):
|
||||
return torch.tensor(tensor.data)
|
||||
else:
|
||||
raise Error("Unexpected type of example_input. Supported types torch.Tensor, np.array or ov.Tensor. "
|
||||
"Got {}".format(type(tensor)))
|
||||
|
||||
|
||||
def convert_pytorch_to_onnx(model, input_shape, opset_version, example_inputs, output_dir):
|
||||
import io
|
||||
import torch
|
||||
|
||||
input_names = None
|
||||
if example_inputs is not None:
|
||||
inputs = example_inputs
|
||||
if isinstance(inputs, list):
|
||||
inputs = [to_torch_tensor(x) for x in inputs]
|
||||
if len(inputs) == 1:
|
||||
inputs = torch.unsqueeze(inputs[0], 0)
|
||||
else:
|
||||
inputs = inputs
|
||||
elif isinstance(inputs, tuple):
|
||||
inputs = [to_torch_tensor(x) for x in inputs]
|
||||
inputs = tuple(inputs)
|
||||
elif isinstance(inputs, dict):
|
||||
for name, tensor in inputs.items():
|
||||
assert isinstance(name, str), "Expected dictionary where keys are input names of string type and" \
|
||||
" values are tensors. Got key of type {}".format(type(name))
|
||||
inputs[name] = to_torch_tensor(tensor)
|
||||
else:
|
||||
inputs = to_torch_tensor(inputs)
|
||||
elif input_shape is not None:
|
||||
inputs = []
|
||||
for shape_idx, shape in enumerate(input_shape):
|
||||
static_shape = get_static_shape(shape, dynamic_value=1)
|
||||
inputs.append(torch.zeros(static_shape))
|
||||
inputs = tuple(inputs)
|
||||
else:
|
||||
raise Error("Please provide input_shape or example_input for converting PyTorch model.")
|
||||
|
||||
dynamic_dims_dict = {}
|
||||
if input_shape is not None and input_names is None:
|
||||
input_names = ["input_{}".format(idx) for idx in range(len(input_shape))]
|
||||
for shape_idx, shape in enumerate(input_shape):
|
||||
dynamic_dims = get_dynamic_dims(shape)
|
||||
if len(dynamic_dims) > 0:
|
||||
dynamic_dims_dict[input_names[shape_idx]] = dynamic_dims
|
||||
additional_params = {}
|
||||
if len(dynamic_dims_dict) > 0:
|
||||
additional_params.update({'dynamic_axes': dynamic_dims_dict})
|
||||
if input_names is not None and len(input_names) > 0:
|
||||
additional_params.update({'input_names': input_names})
|
||||
|
||||
if os.environ.get('SAVE_TO_BYTES_IO_ONNX_MODEL'):
|
||||
model_onnx = io.BytesIO()
|
||||
else:
|
||||
model_onnx = get_onnx_temp_filename(output_dir)
|
||||
if opset_version is not None:
|
||||
additional_params.update({'opset_version': opset_version})
|
||||
|
||||
torch.onnx.export(model,
|
||||
inputs,
|
||||
model_onnx,
|
||||
**additional_params)
|
||||
return model_onnx
|
||||
|
||||
|
||||
def parse_input_shapes(argv):
|
||||
input_shapes = None
|
||||
if 'input_shape' in argv and argv['input_shape'] is not None:
|
||||
shapes = argv['input_shape']
|
||||
if isinstance(shapes, str):
|
||||
shapes = ["[{}]".format(x) for x in split_shapes(shapes)]
|
||||
if isinstance(shapes, list) or isinstance(shapes, tuple):
|
||||
input_shapes = []
|
||||
is_single_shape = False
|
||||
for shape in shapes:
|
||||
if isinstance(shape, str):
|
||||
_, shape_tuple, _ = get_placeholder_shapes(argv_input=None, argv_input_shape=shape)
|
||||
input_shapes.append(shape_tuple)
|
||||
if is_single_shape:
|
||||
raise Error("Incorrect format of shape.")
|
||||
elif isinstance(shape, int) or isinstance(shape, np.int64) or isinstance(shape, Dimension):
|
||||
is_single_shape = True
|
||||
input_shapes.append(shape)
|
||||
else:
|
||||
input_shapes.append(shape)
|
||||
if is_single_shape:
|
||||
return [input_shapes]
|
||||
else:
|
||||
return input_shapes
|
||||
elif isinstance(shapes, PartialShape) or isinstance(shapes, torch.Size):
|
||||
return [shapes]
|
||||
else:
|
||||
raise Error("Unknown type of input shape {}.".format(type(shapes)))
|
||||
|
||||
return input_shapes
|
||||
|
||||
|
||||
def driver(argv: argparse.Namespace, non_default_params: dict):
|
||||
init_logger(argv.log_level.upper(), argv.silent)
|
||||
|
||||
@@ -535,8 +764,13 @@ def pack_params_to_args_namespace(**kwargs):
|
||||
fe_manager = FrontEndManager()
|
||||
cli_parser = get_all_cli_parser(fe_manager)
|
||||
argv = cli_parser.parse_args(args_dict_to_list(cli_parser, **kwargs))
|
||||
|
||||
all_params = {}
|
||||
for key, value in mo_convert_params.items():
|
||||
all_params.update(value)
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key not in argv and key not in mo_convert_params.keys():
|
||||
if key not in argv and key not in all_params.keys():
|
||||
raise Error("Unrecognized argument: {}".format(key))
|
||||
if value is not None:
|
||||
setattr(argv, key, value)
|
||||
@@ -551,19 +785,73 @@ def pack_params_to_args_namespace(**kwargs):
|
||||
|
||||
|
||||
def params_to_string(**kwargs):
|
||||
all_params = {}
|
||||
for key, value in mo_convert_params.items():
|
||||
all_params.update(value)
|
||||
|
||||
for key, value in kwargs.items():
|
||||
if key in mo_convert_params.keys():
|
||||
param_data = mo_convert_params[key]
|
||||
if key in all_params:
|
||||
param_data = all_params[key]
|
||||
if param_data.to_string is not None:
|
||||
kwargs[key] = param_data.to_string(value)
|
||||
return kwargs
|
||||
|
||||
|
||||
def add_line_breaks(text: str, char_num: int, line_break: str):
|
||||
words = text.split(" ")
|
||||
cnt = 0
|
||||
for i, w in enumerate(words):
|
||||
cnt += len(w)
|
||||
if '\n' in w:
|
||||
cnt = len(w) - w.find('\n') - 1
|
||||
if cnt > char_num:
|
||||
if words[i][-1] not in ['\n', '\t']:
|
||||
words[i] = w + '\n'
|
||||
cnt = 0
|
||||
text = ' '.join(words).replace("\n ", "\n")
|
||||
return line_break + text.replace("\n", line_break)
|
||||
|
||||
|
||||
def show_mo_convert_help():
|
||||
print('MO convert parameters:')
|
||||
for param_name in mo_convert_params.keys():
|
||||
param_data = mo_convert_params[param_name]
|
||||
print("{}: {}".format(param_name, param_data.description.format(param_data.possible_types_python_api)))
|
||||
for group_name, group in mo_convert_params.items():
|
||||
if group_name == "optional":
|
||||
print("optional arguments:")
|
||||
elif group_name == "fw_agnostic":
|
||||
print("Framework-agnostic parameters:")
|
||||
elif group_name == "tf":
|
||||
print("TensorFlow*-specific parameters:")
|
||||
elif group_name == "caffe":
|
||||
print("Caffe*-specific parameters:")
|
||||
elif group_name == "mxnet":
|
||||
print("Mxnet-specific parameters:")
|
||||
elif group_name == "kaldi":
|
||||
print("Kaldi-specific parameters:")
|
||||
elif group_name == "pytorch":
|
||||
print("Pytorch-specific parameters:")
|
||||
else:
|
||||
raise Error("Unknown parameters group {}.".format(group_name))
|
||||
for param_name in group:
|
||||
param_data = group[param_name]
|
||||
text = param_data.description.format(param_data.possible_types_python_api)
|
||||
text = add_line_breaks(text, 56, "\n\t\t\t")
|
||||
print(" --{} {}".format(param_name, text))
|
||||
print()
|
||||
|
||||
|
||||
def input_model_is_object(argv):
|
||||
if isinstance(argv['input_model'], str):
|
||||
return False
|
||||
if argv['input_model'] is None:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def remove_tmp_onnx_model(out_dir):
|
||||
if not os.environ.get('SAVE_TO_BYTES_IO_ONNX_MODEL'):
|
||||
tmp_onnx_model = get_onnx_temp_filename(out_dir)
|
||||
|
||||
if os.path.exists(tmp_onnx_model):
|
||||
os.remove(tmp_onnx_model)
|
||||
|
||||
|
||||
def _convert(**args):
|
||||
@@ -574,13 +862,63 @@ def _convert(**args):
|
||||
telemetry = tm.Telemetry(tid=get_tid(), app_name='Model Optimizer', app_version=get_simplified_mo_version())
|
||||
telemetry.start_session('mo')
|
||||
telemetry.send_event('mo', 'version', get_simplified_mo_version())
|
||||
args = params_to_string(**args)
|
||||
argv, non_default_params = pack_params_to_args_namespace(**args)
|
||||
|
||||
if argv.model_name is None:
|
||||
argv.model_name = get_model_name_from_args(argv)
|
||||
|
||||
try:
|
||||
model_framework = None
|
||||
inp_model_is_object = input_model_is_object(args)
|
||||
if inp_model_is_object:
|
||||
model_framework = check_model_object(args)
|
||||
if model_framework == "pytorch" and not os.environ.get('USE_PYTORCH_FRONTEND'):
|
||||
|
||||
opset_version = None
|
||||
if 'onnx_opset_version' in args and args['onnx_opset_version'] is not None:
|
||||
opset_version = args['onnx_opset_version']
|
||||
|
||||
example_inputs = None
|
||||
if 'example_input' in args and args['example_input'] is not None:
|
||||
example_inputs = args['example_input']
|
||||
|
||||
out_dir = args['output_dir'] if 'output_dir' in args else None
|
||||
|
||||
model_onnx = convert_pytorch_to_onnx(args['input_model'],
|
||||
parse_input_shapes(args),
|
||||
opset_version,
|
||||
example_inputs,
|
||||
out_dir)
|
||||
|
||||
|
||||
args['input_model'] = model_onnx
|
||||
if os.environ.get('SAVE_TO_BYTES_IO_ONNX_MODEL'):
|
||||
args['use_legacy_frontend'] = True
|
||||
args['example_input'] = None
|
||||
args['onnx_opset_version'] = None
|
||||
|
||||
try:
|
||||
ov_model = _convert(**args)
|
||||
except Exception as e:
|
||||
remove_tmp_onnx_model(out_dir)
|
||||
raise e
|
||||
|
||||
remove_tmp_onnx_model(out_dir)
|
||||
return ov_model
|
||||
args = params_to_string(**args)
|
||||
argv, non_default_params = pack_params_to_args_namespace(**args)
|
||||
|
||||
if inp_model_is_object:
|
||||
argv.model_name = "model"
|
||||
if argv.model_name is None:
|
||||
argv.model_name = get_model_name_from_args(argv)
|
||||
|
||||
if model_framework is not None:
|
||||
if argv.framework is not None:
|
||||
if argv.framework != model_framework:
|
||||
raise Error("Provided model does not correspond to provided framework. The provided "
|
||||
"framework is {}, the model type is {} which is expected to be {} framework.".format(
|
||||
argv.framework,
|
||||
type(argv.input_model),
|
||||
model_framework))
|
||||
else:
|
||||
argv.framework = model_framework
|
||||
|
||||
# Initialize logger with 'ERROR' as default level to be able to form nice messages
|
||||
# before arg parser deliver log_level requested by user
|
||||
init_logger('ERROR', False)
|
||||
@@ -603,4 +941,4 @@ def _convert(**args):
|
||||
telemetry.send_event('mo', 'conversion_result', 'fail')
|
||||
telemetry.end_session('mo')
|
||||
telemetry.force_shutdown(1.0)
|
||||
raise e
|
||||
raise e.with_traceback(None)
|
||||
|
||||
@@ -633,6 +633,8 @@ def input_user_data_repack(graph: Graph, input_user_shapes: [None, list, dict, n
|
||||
if input_user_shapes is None:
|
||||
# None User did not provide neither --input nor --input_shape keys
|
||||
_input_shapes = None
|
||||
elif isinstance(input_user_shapes, list) and len(input_user_shapes) > 1 and isinstance(input_user_shapes[0], PartialShape):
|
||||
raise Error('Please provide input layer names for input layer shapes. ' + refer_to_faq_msg(58))
|
||||
elif isinstance(input_user_shapes, list) or isinstance(input_user_shapes, dict):
|
||||
# list [layer names w or w/o ports]. User provided only --input key
|
||||
# dict {layer names w or w/o ports as keys: shapes as values}. User provided both --input and --input_shape
|
||||
|
||||
@@ -16,9 +16,6 @@ from openvino.tools.mo.utils.versions_checker import get_environment_setup
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
import tensorflow as tf
|
||||
from tensorflow.python.framework.convert_to_constants import convert_variables_to_constants_v2
|
||||
except ImportError:
|
||||
@@ -175,9 +172,81 @@ def deducing_metagraph_path(meta_graph_file: str):
|
||||
return meta_graph_file
|
||||
|
||||
|
||||
def freeze_tf2_concrete_function(model, concrete_func, env_setup):
|
||||
|
||||
if "tensorflow" in env_setup and env_setup["tensorflow"] >= LooseVersion("2.2.0"):
|
||||
frozen_func = convert_variables_to_constants_v2(concrete_func,
|
||||
lower_control_flow=False,
|
||||
aggressive_inlining=True) # pylint: disable=E1123
|
||||
else:
|
||||
frozen_func = convert_variables_to_constants_v2(concrete_func,
|
||||
lower_control_flow=False) # pylint: disable=E1123
|
||||
graph_def = frozen_func.graph.as_graph_def(add_shapes=True)
|
||||
|
||||
input_names = []
|
||||
if hasattr(model, 'inputs') and model.inputs is not None:
|
||||
# Extract tensor names order from Keras model
|
||||
input_names = [tensor.name for tensor in model.inputs]
|
||||
|
||||
# After model freezing output tensor names are changing and recieve "Func/PartitionedCall" prefix,
|
||||
# so output_names from saved_model cannot be used. Here tensor names from frozen graph are used,
|
||||
# as TF adds indexed Identity nodes during freezing to each output, so this indexing is used for
|
||||
# order alignment.
|
||||
output_names = [tensor.name for tensor in frozen_func.outputs]
|
||||
|
||||
inputs_outputs_order = (input_names, output_names)
|
||||
|
||||
return graph_def, {}, 'tf2', inputs_outputs_order
|
||||
|
||||
|
||||
def prepare_graph_def(model):
|
||||
from tensorflow.python.training.tracking.base import Trackable
|
||||
if isinstance(model, tf_v1.GraphDef):
|
||||
nodes_to_clear_device = model.node
|
||||
for node in nodes_to_clear_device:
|
||||
node.device = ""
|
||||
return model, {}, "tf", None
|
||||
if isinstance(model, tf.keras.Model):
|
||||
env_setup = get_environment_setup("tf")
|
||||
|
||||
assert hasattr(model, "inputs") and model.inputs is not None, "Model inputs specification is required."
|
||||
|
||||
model_inputs = []
|
||||
for inp in model.inputs:
|
||||
if isinstance(inp, tf.Tensor):
|
||||
model_inputs.append(inp)
|
||||
elif tf.keras.backend.is_keras_tensor(inp):
|
||||
model_inputs.append(inp.type_spec)
|
||||
else:
|
||||
raise Error("Unknown input tensor type {}".format(type(input)))
|
||||
|
||||
@tf.function
|
||||
def tf_function(x):
|
||||
return model(x)
|
||||
|
||||
conc_func = tf_function.get_concrete_function(model_inputs)
|
||||
return freeze_tf2_concrete_function(model, conc_func, env_setup)
|
||||
if isinstance(model, Trackable):
|
||||
env_setup = get_environment_setup("tf")
|
||||
return saved_model_load(model, env_setup)
|
||||
raise Exception("Unknown model type {}.".format(type(model)))
|
||||
|
||||
|
||||
def saved_model_load(imported, env_setup):
|
||||
# to get a signature by key throws KeyError for TF 1.x SavedModel format in case TF 2.x installed
|
||||
concrete_func = imported.signatures[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
|
||||
# the aggressive inlining parameter needs to freeze a table of embeddings for Keras Embedding operation
|
||||
# and a model with Embedding operation cannot properly converted to IR without this function parameter
|
||||
|
||||
return freeze_tf2_concrete_function(imported, concrete_func, env_setup)
|
||||
|
||||
|
||||
def load_tf_graph_def(graph_file_name: str = "", is_binary: bool = True, checkpoint: str = "",
|
||||
model_dir: str = "", saved_model_tags: list = [], meta_graph_file: str = "",
|
||||
user_output_node_names_list: list = []):
|
||||
|
||||
if not isinstance(graph_file_name, str) and graph_file_name is not None:
|
||||
return prepare_graph_def(graph_file_name)
|
||||
# As a provisional solution, use a native TF methods to load a model protobuf
|
||||
graph_def = tf_v1.GraphDef()
|
||||
if isinstance(graph_file_name, str) and (re.match(r'.*\.(ckpt|meta)$', graph_file_name)):
|
||||
@@ -230,8 +299,6 @@ def load_tf_graph_def(graph_file_name: str = "", is_binary: bool = True, checkpo
|
||||
# saved model directory
|
||||
try:
|
||||
env_setup = get_environment_setup("tf")
|
||||
# enable eager execution temporarily while TensorFlow 2 model is being loaded
|
||||
tf_v1.enable_eager_execution()
|
||||
|
||||
try:
|
||||
# Code to extract Keras model.
|
||||
@@ -241,38 +308,8 @@ def load_tf_graph_def(graph_file_name: str = "", is_binary: bool = True, checkpo
|
||||
except:
|
||||
imported = tf.saved_model.load(model_dir, saved_model_tags) # pylint: disable=E1120
|
||||
|
||||
# to get a signature by key throws KeyError for TF 1.x SavedModel format in case TF 2.x installed
|
||||
concrete_func = imported.signatures[tf.saved_model.DEFAULT_SERVING_SIGNATURE_DEF_KEY]
|
||||
# the aggressive inlining parameter needs to freeze a table of embeddings for Keras Embedding operation
|
||||
# and a model with Embedding operation cannot properly converted to IR without this function parameter
|
||||
if "tensorflow" in env_setup and env_setup["tensorflow"] >= LooseVersion("2.2.0"):
|
||||
frozen_func = convert_variables_to_constants_v2(concrete_func,
|
||||
lower_control_flow=False,
|
||||
aggressive_inlining=True) # pylint: disable=E1123
|
||||
else:
|
||||
frozen_func = convert_variables_to_constants_v2(concrete_func,
|
||||
lower_control_flow=False) # pylint: disable=E1123
|
||||
graph_def = frozen_func.graph.as_graph_def(add_shapes=True)
|
||||
# disable eager execution since next steps are executed with a graph in non-eager mode
|
||||
tf_v1.disable_eager_execution()
|
||||
|
||||
input_names = []
|
||||
if hasattr(imported, 'inputs') and imported.inputs is not None:
|
||||
# Extract tensor names order from Keras model
|
||||
input_names = [tensor.name for tensor in imported.inputs]
|
||||
|
||||
# After model freezing output tensor names are changing and recieve "Func/PartitionedCall" prefix,
|
||||
# so output_names from saved_model cannot be used. Here tensor names from frozen graph are used,
|
||||
# as TF adds indexed Identity nodes during freezing to each output, so this indexing is used for
|
||||
# order alignment.
|
||||
output_names = [tensor.name for tensor in frozen_func.outputs]
|
||||
|
||||
inputs_outputs_order = (input_names, output_names)
|
||||
|
||||
return graph_def, variables_values, 'tf2', inputs_outputs_order
|
||||
return saved_model_load(imported, env_setup)
|
||||
except:
|
||||
# disable eager execution since TensorFlow 1 model is handled
|
||||
tf_v1.disable_eager_execution()
|
||||
# code to extract GraphDef for TF 1.0 SavedModel format
|
||||
tags = saved_model_tags if saved_model_tags is not None else [tf_v1.saved_model.tag_constants.SERVING]
|
||||
with tf_v1.Session() as sess:
|
||||
|
||||
@@ -11,8 +11,6 @@ import numpy as np
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
|
||||
@@ -20,6 +18,7 @@ except ImportError:
|
||||
tf_v1.get_logger().setLevel("ERROR")
|
||||
|
||||
from google.protobuf import text_format
|
||||
from tensorflow.python.eager.context import graph_mode
|
||||
|
||||
from openvino.tools.mo.front.extractor import node_defs_to_str
|
||||
from openvino.tools.mo.front.tf.extractors.utils import tf_dtype_extractor, tf_tensor_shape, get_tf_node_port
|
||||
@@ -27,7 +26,6 @@ from openvino.tools.mo.graph.graph import Node
|
||||
from openvino.tools.mo.utils.graph import node_incoming_neighbourhood, node_outcoming_neighbourhood
|
||||
from openvino.tools.mo.front.common.partial_infer.utils import mo_array
|
||||
|
||||
|
||||
def tf_native_tf_node_infer(node: Node):
|
||||
"""
|
||||
The infer function should be used to infer shape and data type of the TF operation not supported by IE.
|
||||
@@ -58,7 +56,9 @@ def tf_native_tf_node_infer(node: Node):
|
||||
for ind in range(len(tmp_node.out_edges())):
|
||||
tmp_node_attrs['output_tensors_names'].append(tmp_node.id + ":" + str(ind))
|
||||
|
||||
tf_subgraph_infer(tmp_node)
|
||||
with graph_mode():
|
||||
tf_subgraph_infer(tmp_node)
|
||||
|
||||
# the shape and value has been inferred and saved to the tmp_node's out nodes attribute. Let's copy it back!
|
||||
for tmp_out_port, tmp_out_node in tmp_node.out_nodes().items():
|
||||
if tmp_out_node.value is not None:
|
||||
|
||||
@@ -24,8 +24,16 @@ class ONNXLoader(Loader):
|
||||
run_not_recursively = True
|
||||
|
||||
def load(self, graph: Graph):
|
||||
import onnx
|
||||
import io
|
||||
argv = graph.graph['cmd_params']
|
||||
model_proto = load_onnx_model(argv.input_model)
|
||||
if isinstance(argv.input_model, str):
|
||||
model_proto = load_onnx_model(argv.input_model)
|
||||
elif isinstance(argv.input_model, io.BytesIO):
|
||||
model_proto = onnx.load_model_from_string(argv.input_model.getvalue())
|
||||
else:
|
||||
raise Error('Unknown ONNX model type: {}'.format(type(argv.input_model)))
|
||||
|
||||
model_graph = model_proto.graph # pylint: disable=no-member
|
||||
# print(model_graph)
|
||||
# assert len(model_graph) == 1, "An ONNX model contains more than 1 graph: unsupported"
|
||||
|
||||
@@ -7,8 +7,6 @@ import os
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ try:
|
||||
except ImportError:
|
||||
import openvino.tools.mo.utils.telemetry_stub as tm
|
||||
|
||||
from openvino.tools.mo.convert import convert
|
||||
from openvino.tools.mo.convert import convert_model
|
||||
from openvino.tools.mo.pipeline.common import get_ir_version
|
||||
from openvino.tools.mo.utils.cli_parser import get_model_name_from_args
|
||||
from openvino.tools.mo.utils.logger import init_logger
|
||||
@@ -40,7 +40,7 @@ def main(cli_parser: argparse.ArgumentParser, framework=None):
|
||||
|
||||
ngraph_function = None
|
||||
try:
|
||||
ngraph_function = convert(**argv)
|
||||
ngraph_function = convert_model(**argv)
|
||||
ov_update_message = get_ov_update_message()
|
||||
ov_api20_message = get_ov_api20_message()
|
||||
if ov_update_message is not None:
|
||||
|
||||
@@ -55,8 +55,6 @@ class CustomSubgraphCall(MiddleReplacementPattern):
|
||||
"""
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
# in some environment suppressing through TF_CPP_MIN_LOG_LEVEL does not work
|
||||
@@ -278,8 +276,6 @@ class CustomSubgraphCall(MiddleReplacementPattern):
|
||||
"""
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
# in some environment suppressing through TF_CPP_MIN_LOG_LEVEL does not work
|
||||
|
||||
@@ -188,7 +188,14 @@ def fe_input_user_data_repack(
|
||||
}
|
||||
"""
|
||||
_input_shapes = []
|
||||
if isinstance(input_user_shapes, list) or isinstance(input_user_shapes, dict):
|
||||
if isinstance(input_user_shapes, list) and len(input_user_shapes) > 1 and isinstance(input_user_shapes[0], PartialShape):
|
||||
for shape in input_user_shapes:
|
||||
assert isinstance(shape, PartialShape), "Got incorrect format of input shapes."
|
||||
model_inputs = input_model.get_inputs()
|
||||
assert len(model_inputs) == len(input_user_shapes)
|
||||
for idx, model_input in enumerate(model_inputs):
|
||||
_input_shapes.append({"node": model_input, "shape": input_user_shapes[idx]})
|
||||
elif isinstance(input_user_shapes, list) or isinstance(input_user_shapes, dict):
|
||||
for input_name in input_user_shapes:
|
||||
node = decode_name_with_port(
|
||||
input_model, input_name, framework, IOType.Input
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import argparse
|
||||
import io
|
||||
import logging as log
|
||||
from typing import List
|
||||
import sys
|
||||
@@ -27,7 +28,11 @@ def moc_pipeline(argv: argparse.Namespace, moc_front_end: FrontEnd):
|
||||
:param: moc_front_end: Loaded Frontend for converting input model
|
||||
:return: converted nGraph function ready for serialization
|
||||
"""
|
||||
input_model = moc_front_end.load(argv.input_model)
|
||||
if isinstance(argv.input_model, io.BytesIO):
|
||||
raise Exception("ONNX frontend does not support input model as BytesIO object. "
|
||||
"Please use use_legacy_frontend=True to convert the model.")
|
||||
else:
|
||||
input_model = moc_front_end.load(argv.input_model)
|
||||
|
||||
user_shapes, outputs, freeze_placeholder = fe_user_data_repack(
|
||||
input_model, argv.placeholder_shapes, argv.placeholder_data_types,
|
||||
@@ -80,6 +85,9 @@ def moc_pipeline(argv: argparse.Namespace, moc_front_end: FrontEnd):
|
||||
inputs_equal, outputs_equal))
|
||||
|
||||
def create_target_input_shapes(new_input_places):
|
||||
if isinstance(new_input_places, list) and len(new_input_places) > 1 \
|
||||
and isinstance(new_input_places[0], tuple):
|
||||
return new_input_places
|
||||
new_input_place_names = [x.get_names()[0] for x in new_input_places]
|
||||
shapes = [shape for shape in argv.placeholder_shapes.values()]
|
||||
return dict(zip(new_input_place_names, shapes))
|
||||
|
||||
@@ -63,12 +63,21 @@ class ClassType(Enum):
|
||||
|
||||
|
||||
def _update(cls, registered_list: list, registered_dict: dict, key: str, enabled_transforms: list,
|
||||
disabled_transforms: list):
|
||||
disabled_transforms: list, exclude_modules: set):
|
||||
new_keys = {} # maps a custom name to class
|
||||
new_keys_lower = {} # translates lowered custom name to its original form
|
||||
# print('Registering new subclasses for', cls)
|
||||
|
||||
for c in cls.__subclasses__():
|
||||
# skip importing loaders of other frameworks
|
||||
if cls.__name__ == 'Loader':
|
||||
need_exclude = False
|
||||
for framework in exclude_modules:
|
||||
if framework in c.__module__:
|
||||
need_exclude = True
|
||||
break
|
||||
if need_exclude:
|
||||
continue
|
||||
# Force enabling operations
|
||||
if hasattr(c, 'id') and c.id in enabled_transforms or \
|
||||
".".join([c.__module__, c.__name__]) in enabled_transforms:
|
||||
@@ -87,10 +96,9 @@ def _update(cls, registered_list: list, registered_dict: dict, key: str, enabled
|
||||
if hasattr(c, key) and getattr(c, key) is not None:
|
||||
k = getattr(c, key)
|
||||
if k.lower() in new_keys_lower:
|
||||
raise Error(
|
||||
'Attempt to register of custom name {} for the second time as class {}. ' \
|
||||
'Note that custom names are case-insensitive. ' +
|
||||
refer_to_faq_msg(55), k, c)
|
||||
log.warning('Attempt to register of custom name {} for the second time as class {}. '
|
||||
'Note that custom names are case-insensitive. ' + refer_to_faq_msg(55), k, c)
|
||||
continue
|
||||
else:
|
||||
new_keys_lower[k.lower()] = k
|
||||
new_keys[k] = c
|
||||
@@ -100,9 +108,9 @@ def _update(cls, registered_list: list, registered_dict: dict, key: str, enabled
|
||||
registered_dict.update(new_keys)
|
||||
|
||||
|
||||
def update_registration(classes: list, enabled_transforms: list, disabled_transforms: list):
|
||||
def update_registration(classes: list, enabled_transforms: list, disabled_transforms: list, exclude_modules: set):
|
||||
for cls in classes:
|
||||
_update(cls, cls.registered_cls, cls.registered_ops, 'op', enabled_transforms, disabled_transforms)
|
||||
_update(cls, cls.registered_cls, cls.registered_ops, 'op', enabled_transforms, disabled_transforms, exclude_modules)
|
||||
_registered_classes_dict.setdefault(cls.class_type(), set()).add(cls)
|
||||
|
||||
|
||||
@@ -326,3 +334,7 @@ def apply_replacements(graph: Graph, replacements_type: list):
|
||||
"""
|
||||
replacers_order = get_replacers_order(replacements_type)
|
||||
apply_replacements_list(graph, replacers_order)
|
||||
|
||||
|
||||
def clear_registered_classes_dict():
|
||||
_registered_classes_dict.clear()
|
||||
|
||||
@@ -74,6 +74,15 @@ def path_to_str(path):
|
||||
raise Exception("Incorrect type of {} expected str or Path, got {}".format(path, type(path)))
|
||||
|
||||
|
||||
def path_to_str_or_object(value):
|
||||
if value is None or isinstance(value, str):
|
||||
return value
|
||||
elif isinstance(value, Path):
|
||||
return str(value)
|
||||
else:
|
||||
return value
|
||||
|
||||
|
||||
def paths_to_str(paths):
|
||||
if paths is None:
|
||||
return None
|
||||
@@ -271,7 +280,7 @@ def layout_to_str(layout):
|
||||
if isinstance(layout, Layout):
|
||||
return layout.to_string()
|
||||
raise Exception("Incorrect layout type. Expected Layout or string or dictionary, "
|
||||
"where key is operation name and value is Layout, got {}".format(type(layout)))
|
||||
"where key is operation name and value is layout or list of layouts, got {}".format(type(layout)))
|
||||
|
||||
|
||||
def source_target_layout_to_str(value):
|
||||
@@ -320,6 +329,13 @@ def layout_param_to_str(value):
|
||||
raise Exception("Incorrect operation name type. Expected string, got {}".format(type(op_name)))
|
||||
values_str.append(op_name + "(" + layoutmap_to_str(layout) + ")")
|
||||
return ",".join(values_str)
|
||||
if isinstance(value, openvino.tools.mo.LayoutMap):
|
||||
return layoutmap_to_str(value)
|
||||
if isinstance(value, list) or isinstance(value, tuple):
|
||||
values_str = []
|
||||
for layout in value:
|
||||
values_str.append(layoutmap_to_str(layout))
|
||||
return ",".join(values_str)
|
||||
|
||||
return layoutmap_to_str(value)
|
||||
|
||||
@@ -401,13 +417,26 @@ def transform_param_to_str(value):
|
||||
ParamDescription = namedtuple("ParamData",
|
||||
["description", "possible_types_command_line", "possible_types_python_api", "to_string"])
|
||||
mo_convert_params = {
|
||||
'input_model': ParamDescription(
|
||||
'Tensorflow*: a file with a pre-trained model ' +
|
||||
' (binary or text .pb file after freezing).\n' +
|
||||
' Caffe*: a model proto file with model weights', '', '',
|
||||
path_to_str),
|
||||
'optional':
|
||||
{
|
||||
'help': ParamDescription(
|
||||
'Print available parameters.', '', '', None),
|
||||
'framework': ParamDescription(
|
||||
'Name of the framework used to train the input model.', '', '', None),
|
||||
},
|
||||
'fw_agnostic':
|
||||
{
|
||||
'input_model': ParamDescription(
|
||||
'{} Tensorflow*: a file with a pre-trained model ' +
|
||||
' (binary or text .pb file after freezing).\n' +
|
||||
' Caffe*: a model proto file with model weights', '',
|
||||
'Model object in original framework (PyTorch, Tensorflow) or path to model file. \n' +
|
||||
'Supported object formats of input model:\n PyTorch - torch.nn.Module, torch.jit.ScriptModule, torch.jit.ScriptFunction' +
|
||||
'TF - tf.compat.v1.GraphDef, tf.compat.v1.wrap_function, tf.compat.v1.session\n ' +
|
||||
'TF2 / Keras - tf.keras.Model, tf.keras.layers.Layer, tf.function, tf.Module, tf.train.checkpoint, ' +
|
||||
'tf.python.training.tracking.base.Trackable for case when it is output from tf.saved_model.load().\n' +
|
||||
'File formats examples:\n',
|
||||
path_to_str_or_object),
|
||||
'model_name': ParamDescription(
|
||||
'Model_name parameter passed to the final create_ir transform. ' +
|
||||
'This parameter is used to name ' +
|
||||
@@ -536,10 +565,11 @@ mo_convert_params = {
|
||||
'Apply additional transformations. {}' +
|
||||
'"--transform transformation_name1[args],transformation_name2..." ' +
|
||||
'where [args] is key=value pairs separated by semicolon. ' +
|
||||
'Examples: "--transform LowLatency2" or ' +
|
||||
' "--transform Pruning" or ' +
|
||||
' "--transform LowLatency2[use_const_initializer=False]" or ' +
|
||||
' "--transform \"MakeStateful[param_res_names='
|
||||
'Examples:' +
|
||||
' "--transform LowLatency2" or \n' +
|
||||
' "--transform Pruning" or \n' +
|
||||
' "--transform LowLatency2[use_const_initializer=False]" or \n' +
|
||||
' "--transform \"MakeStateful[param_res_names=\n'
|
||||
'{{\'input_name_1\':\'output_name_1\',\'input_name_2\':\'output_name_2\'}}]\"" ' +
|
||||
'Available transformations: "LowLatency2", "MakeStateful", "Pruning"', 'Usage: ',
|
||||
'\'transform\' can be set by a list of tuples, where the first element is '
|
||||
@@ -588,6 +618,17 @@ mo_convert_params = {
|
||||
'Force the usage of legacy Frontend of Model Optimizer for model conversion into IR. '
|
||||
'The legacy Frontend is Python based and is available for TensorFlow*, ONNX*, MXNet*, '
|
||||
'Caffe*, and Kaldi* models.', '', '', None),
|
||||
},
|
||||
"caffe":
|
||||
{
|
||||
'input_proto': ParamDescription(
|
||||
'Deploy-ready prototxt file that contains a topology structure ' +
|
||||
'and layer attributes', '', '', path_to_str),
|
||||
'caffe_parser_path': ParamDescription(
|
||||
'Path to Python Caffe* parser generated from caffe.proto', '', '',
|
||||
path_to_str),
|
||||
'k': ParamDescription(
|
||||
'Path to CustomLayersMapping.xml to register custom layers', '', '', path_to_str),
|
||||
'disable_omitting_optional': ParamDescription(
|
||||
'Disable omitting optional attributes to be used for custom layers. ' +
|
||||
'Use this option if you want to transfer all attributes of a custom layer to IR. ' +
|
||||
@@ -598,6 +639,9 @@ mo_convert_params = {
|
||||
'Enable flattening optional params to be used for custom layers. ' +
|
||||
'Use this option if you want to transfer attributes of a custom layer to IR with flattened nested parameters. ' +
|
||||
'Default behavior is to transfer the attributes without flattening nested parameters.', '', '', None),
|
||||
},
|
||||
"tf":
|
||||
{
|
||||
'input_model_is_text': ParamDescription(
|
||||
'TensorFlow*: treat the input model file as a text protobuf format. If not specified, ' +
|
||||
'the Model Optimizer treats it as a binary file by default.', '', '', None),
|
||||
@@ -624,14 +668,9 @@ mo_convert_params = {
|
||||
'tensorflow_custom_layer_libraries': ParamDescription(
|
||||
'TensorFlow*: comma separated list of shared libraries with TensorFlow* custom '
|
||||
'operations implementation.', '', '', path_to_str),
|
||||
'input_proto': ParamDescription(
|
||||
'Deploy-ready prototxt file that contains a topology structure ' +
|
||||
'and layer attributes', '', '', path_to_str),
|
||||
'caffe_parser_path': ParamDescription(
|
||||
'Path to Python Caffe* parser generated from caffe.proto', '', '',
|
||||
path_to_str),
|
||||
'k': ParamDescription(
|
||||
'Path to CustomLayersMapping.xml to register custom layers', '', '', path_to_str),
|
||||
},
|
||||
"mxnet":
|
||||
{
|
||||
'input_symbol': ParamDescription(
|
||||
'Symbol file (for example, model-symbol.json) that contains a topology structure ' +
|
||||
'and layer attributes', '', '', path_to_str),
|
||||
@@ -650,6 +689,9 @@ mo_convert_params = {
|
||||
'enable_ssd_gluoncv': ParamDescription(
|
||||
"Enable pattern matchers replacers for converting gluoncv ssd topologies.",
|
||||
'', '', None),
|
||||
},
|
||||
"kaldi":
|
||||
{
|
||||
'counts': ParamDescription(
|
||||
"Path to the counts file", '', '', path_to_str),
|
||||
'remove_output_softmax': ParamDescription(
|
||||
@@ -657,8 +699,14 @@ mo_convert_params = {
|
||||
'remove_memory': ParamDescription(
|
||||
"Removes the Memory layer and use additional inputs outputs instead", '', '',
|
||||
None),
|
||||
'help': ParamDescription(
|
||||
'Print available parameters.', '', '', None),
|
||||
},
|
||||
"pytorch":
|
||||
{
|
||||
'example_input': ParamDescription('Sample of model input in original framework. '
|
||||
'For PyTorch it can be torch.Tensor.', '', '', None),
|
||||
'onnx_opset_version': ParamDescription('Version of ONNX opset that is used for converting from PyTorch to ONNX.',
|
||||
'', '', None)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -891,9 +939,10 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
if not parser:
|
||||
parser = argparse.ArgumentParser()
|
||||
common_group = parser.add_argument_group('Framework-agnostic parameters')
|
||||
mo_convert_params_common = mo_convert_params['fw_agnostic']
|
||||
# Common parameters
|
||||
common_group.add_argument('--input_model', '-w', '-m',
|
||||
help=mo_convert_params['input_model'].description,
|
||||
help=mo_convert_params_common['input_model'].description,
|
||||
action=CanonicalizePathCheckExistenceAction,
|
||||
type=readable_file_or_dir)
|
||||
common_group.add_argument('--model_name', '-n',
|
||||
@@ -907,8 +956,8 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
action=CanonicalizePathAction,
|
||||
type=writable_dir)
|
||||
common_group.add_argument('--input_shape',
|
||||
help=mo_convert_params['input_shape'].description.format(
|
||||
mo_convert_params['input_shape'].possible_types_command_line))
|
||||
help=mo_convert_params_common['input_shape'].description.format(
|
||||
mo_convert_params_common['input_shape'].possible_types_command_line))
|
||||
common_group.add_argument('--scale', '-s',
|
||||
type=float,
|
||||
help='All input values coming from original network inputs will be ' +
|
||||
@@ -935,39 +984,39 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
'DEBUG', 'NOTSET'],
|
||||
default='ERROR')
|
||||
common_group.add_argument('--input',
|
||||
help=mo_convert_params['input'].description.format(
|
||||
mo_convert_params['input'].possible_types_command_line))
|
||||
help=mo_convert_params_common['input'].description.format(
|
||||
mo_convert_params_common['input'].possible_types_command_line))
|
||||
common_group.add_argument('--output',
|
||||
help=mo_convert_params['output'].description.format(
|
||||
mo_convert_params['output'].possible_types_command_line))
|
||||
help=mo_convert_params_common['output'].description.format(
|
||||
mo_convert_params_common['output'].possible_types_command_line))
|
||||
common_group.add_argument('--mean_values', '-ms',
|
||||
help=mo_convert_params['mean_values'].description.format(
|
||||
mo_convert_params['mean_values'].possible_types_command_line),
|
||||
help=mo_convert_params_common['mean_values'].description.format(
|
||||
mo_convert_params_common['mean_values'].possible_types_command_line),
|
||||
default=())
|
||||
common_group.add_argument('--scale_values',
|
||||
help=mo_convert_params['scale_values'].description.format(
|
||||
mo_convert_params['scale_values'].possible_types_command_line),
|
||||
help=mo_convert_params_common['scale_values'].description.format(
|
||||
mo_convert_params_common['scale_values'].possible_types_command_line),
|
||||
default=())
|
||||
common_group.add_argument('--source_layout',
|
||||
help=mo_convert_params['source_layout'].description.format(
|
||||
mo_convert_params['source_layout'].possible_types_command_line),
|
||||
help=mo_convert_params_common['source_layout'].description.format(
|
||||
mo_convert_params_common['source_layout'].possible_types_command_line),
|
||||
default=())
|
||||
common_group.add_argument('--target_layout',
|
||||
help=mo_convert_params['target_layout'].description.format(
|
||||
mo_convert_params['target_layout'].possible_types_command_line),
|
||||
help=mo_convert_params_common['target_layout'].description.format(
|
||||
mo_convert_params_common['target_layout'].possible_types_command_line),
|
||||
default=())
|
||||
common_group.add_argument('--layout',
|
||||
help=mo_convert_params['layout'].description.format(
|
||||
mo_convert_params['layout'].possible_types_command_line),
|
||||
help=mo_convert_params_common['layout'].description.format(
|
||||
mo_convert_params_common['layout'].possible_types_command_line),
|
||||
default=())
|
||||
# TODO: isn't it a weights precision type
|
||||
common_group.add_argument('--data_type',
|
||||
help=mo_convert_params['data_type'].description,
|
||||
help=mo_convert_params_common['data_type'].description,
|
||||
choices=["FP16", "FP32", "half", "float"],
|
||||
default='float')
|
||||
common_group.add_argument('--transform',
|
||||
help=mo_convert_params['transform'].description.format(
|
||||
mo_convert_params['transform'].possible_types_command_line),
|
||||
help=mo_convert_params_common['transform'].description.format(
|
||||
mo_convert_params_common['transform'].possible_types_command_line),
|
||||
default="")
|
||||
common_group.add_argument('--disable_fusing',
|
||||
help='[DEPRECATED] Turn off fusing of linear operations to Convolution.',
|
||||
@@ -984,22 +1033,22 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
action=DeprecatedStoreTrue, default=False)
|
||||
# we use CanonicalizeDirCheckExistenceAction instead of readable_dirs to handle empty strings
|
||||
common_group.add_argument("--extensions",
|
||||
help=mo_convert_params['extensions'].description.format(
|
||||
mo_convert_params['extensions'].possible_types_command_line),
|
||||
help=mo_convert_params_common['extensions'].description.format(
|
||||
mo_convert_params_common['extensions'].possible_types_command_line),
|
||||
default=[import_extensions.default_path()],
|
||||
action=CanonicalizePathCheckExistenceAction,
|
||||
type=readable_dirs_or_files_or_empty)
|
||||
common_group.add_argument("--batch", "-b",
|
||||
type=check_positive,
|
||||
default=None,
|
||||
help=mo_convert_params['batch'].description)
|
||||
help=mo_convert_params_common['batch'].description)
|
||||
common_group.add_argument("--version",
|
||||
action='version',
|
||||
version='Version of Model Optimizer is: {}'.format(get_version()),
|
||||
help=mo_convert_params['version'].description)
|
||||
help=mo_convert_params_common['version'].description)
|
||||
|
||||
common_group.add_argument('--silent',
|
||||
help=mo_convert_params['silent'].description,
|
||||
help=mo_convert_params_common['silent'].description,
|
||||
type=check_bool,
|
||||
default=True)
|
||||
common_group.add_argument('--freeze_placeholder_with_value',
|
||||
@@ -1009,26 +1058,26 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
'Use --input option to specify a value for freezing.',
|
||||
default=None)
|
||||
common_group.add_argument('--static_shape',
|
||||
help=mo_convert_params['static_shape'].description,
|
||||
help=mo_convert_params_common['static_shape'].description,
|
||||
action='store_true', default=False)
|
||||
common_group.add_argument('--disable_weights_compression',
|
||||
help='[DEPRECATED] Disable compression and store weights with original precision.',
|
||||
action=DeprecatedStoreTrue, default=False)
|
||||
common_group.add_argument('--progress',
|
||||
help=mo_convert_params['progress'].description,
|
||||
help=mo_convert_params_common['progress'].description,
|
||||
action='store_true', default=False)
|
||||
common_group.add_argument('--stream_output',
|
||||
help=mo_convert_params['stream_output'].description,
|
||||
help=mo_convert_params_common['stream_output'].description,
|
||||
action='store_true', default=False)
|
||||
common_group.add_argument('--transformations_config',
|
||||
help=mo_convert_params['transformations_config'].description.format(
|
||||
mo_convert_params['transformations_config'].possible_types_command_line),
|
||||
help=mo_convert_params_common['transformations_config'].description.format(
|
||||
mo_convert_params_common['transformations_config'].possible_types_command_line),
|
||||
action=CanonicalizeTransformationPathCheckExistenceAction)
|
||||
common_group.add_argument("--use_new_frontend",
|
||||
help=mo_convert_params['use_new_frontend'].description,
|
||||
help=mo_convert_params_common['use_new_frontend'].description,
|
||||
action='store_true', default=False)
|
||||
common_group.add_argument("--use_legacy_frontend",
|
||||
help=mo_convert_params['use_legacy_frontend'].description,
|
||||
help=mo_convert_params_common['use_legacy_frontend'].description,
|
||||
action='store_true', default=False)
|
||||
return parser
|
||||
|
||||
@@ -1143,18 +1192,19 @@ def get_caffe_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
get_common_cli_parser(parser=parser)
|
||||
|
||||
caffe_group = parser.add_argument_group('Caffe*-specific parameters')
|
||||
mo_convert_params_caffe = mo_convert_params['caffe']
|
||||
|
||||
caffe_group.add_argument('--input_proto', '-d',
|
||||
help=mo_convert_params['input_proto'].description,
|
||||
help=mo_convert_params_caffe['input_proto'].description,
|
||||
type=str,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
caffe_group.add_argument('--caffe_parser_path',
|
||||
help=mo_convert_params['caffe_parser_path'].description,
|
||||
help=mo_convert_params_caffe['caffe_parser_path'].description,
|
||||
type=str,
|
||||
default=os.path.join(os.path.dirname(__file__), os.pardir, 'front', 'caffe', 'proto'),
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
caffe_group.add_argument('-k',
|
||||
help=mo_convert_params['k'].description,
|
||||
help=mo_convert_params_caffe['k'].description,
|
||||
type=str,
|
||||
default=os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'extensions',
|
||||
'front', 'caffe',
|
||||
@@ -1175,11 +1225,11 @@ def get_caffe_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
'from the upper left corner of the mean image',
|
||||
default=None)
|
||||
caffe_group.add_argument('--disable_omitting_optional',
|
||||
help=mo_convert_params['disable_omitting_optional'].description,
|
||||
help=mo_convert_params_caffe['disable_omitting_optional'].description,
|
||||
action='store_true',
|
||||
default=False)
|
||||
caffe_group.add_argument('--enable_flattening_nested_params',
|
||||
help=mo_convert_params['enable_flattening_nested_params'].description,
|
||||
help=mo_convert_params_caffe['enable_flattening_nested_params'].description,
|
||||
action='store_true',
|
||||
default=False)
|
||||
return parser
|
||||
@@ -1196,39 +1246,40 @@ def get_tf_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
if not parser:
|
||||
parser = argparse.ArgumentParser(usage='%(prog)s [options]')
|
||||
get_common_cli_parser(parser=parser)
|
||||
mo_convert_params_tf = mo_convert_params['tf']
|
||||
|
||||
tf_group = parser.add_argument_group('TensorFlow*-specific parameters')
|
||||
tf_group.add_argument('--input_model_is_text',
|
||||
help=mo_convert_params['input_model_is_text'].description,
|
||||
help=mo_convert_params_tf['input_model_is_text'].description,
|
||||
action='store_true')
|
||||
tf_group.add_argument('--input_checkpoint', type=str, default=None,
|
||||
help=mo_convert_params['input_checkpoint'].description,
|
||||
help=mo_convert_params_tf['input_checkpoint'].description,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--input_meta_graph',
|
||||
help=mo_convert_params['input_meta_graph'].description,
|
||||
help=mo_convert_params_tf['input_meta_graph'].description,
|
||||
action=CanonicalizePathCheckExistenceAction,
|
||||
type=readable_file)
|
||||
tf_group.add_argument('--saved_model_dir', default=None,
|
||||
help=mo_convert_params['saved_model_dir'].description,
|
||||
help=mo_convert_params_tf['saved_model_dir'].description,
|
||||
action=CanonicalizePathCheckExistenceAction,
|
||||
type=readable_dirs)
|
||||
tf_group.add_argument('--saved_model_tags', type=str, default=None,
|
||||
help=mo_convert_params['saved_model_tags'].description)
|
||||
help=mo_convert_params_tf['saved_model_tags'].description)
|
||||
tf_group.add_argument('--tensorflow_custom_operations_config_update',
|
||||
help=mo_convert_params['tensorflow_custom_operations_config_update'].description,
|
||||
help=mo_convert_params_tf['tensorflow_custom_operations_config_update'].description,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--tensorflow_use_custom_operations_config',
|
||||
help='Use the configuration file with custom operation description.',
|
||||
action=DeprecatedCanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--tensorflow_object_detection_api_pipeline_config',
|
||||
help=mo_convert_params['tensorflow_object_detection_api_pipeline_config'].description,
|
||||
help=mo_convert_params_tf['tensorflow_object_detection_api_pipeline_config'].description,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--tensorboard_logdir',
|
||||
help=mo_convert_params['tensorboard_logdir'].description,
|
||||
help=mo_convert_params_tf['tensorboard_logdir'].description,
|
||||
default=None,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--tensorflow_custom_layer_libraries',
|
||||
help=mo_convert_params['tensorflow_custom_layer_libraries'].description,
|
||||
help=mo_convert_params_tf['tensorflow_custom_layer_libraries'].description,
|
||||
default=None,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
tf_group.add_argument('--disable_nhwc_to_nchw',
|
||||
@@ -1251,26 +1302,27 @@ def get_mxnet_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
get_common_cli_parser(parser=parser)
|
||||
|
||||
mx_group = parser.add_argument_group('Mxnet-specific parameters')
|
||||
mo_convert_params_mxnet = mo_convert_params['mxnet']
|
||||
|
||||
mx_group.add_argument('--input_symbol',
|
||||
help=mo_convert_params['input_symbol'].description,
|
||||
help=mo_convert_params_mxnet['input_symbol'].description,
|
||||
type=str,
|
||||
action=CanonicalizePathCheckExistenceAction)
|
||||
mx_group.add_argument("--nd_prefix_name",
|
||||
help=mo_convert_params['nd_prefix_name'].description,
|
||||
help=mo_convert_params_mxnet['nd_prefix_name'].description,
|
||||
default=None)
|
||||
mx_group.add_argument("--pretrained_model_name",
|
||||
help=mo_convert_params['pretrained_model_name'].description,
|
||||
help=mo_convert_params_mxnet['pretrained_model_name'].description,
|
||||
default=None)
|
||||
mx_group.add_argument("--save_params_from_nd",
|
||||
action='store_true',
|
||||
help=mo_convert_params['save_params_from_nd'].description)
|
||||
help=mo_convert_params_mxnet['save_params_from_nd'].description)
|
||||
mx_group.add_argument("--legacy_mxnet_model",
|
||||
action='store_true',
|
||||
help=mo_convert_params['legacy_mxnet_model'].description)
|
||||
help=mo_convert_params_mxnet['legacy_mxnet_model'].description)
|
||||
mx_group.add_argument("--enable_ssd_gluoncv",
|
||||
action='store_true',
|
||||
help=mo_convert_params['enable_ssd_gluoncv'].description,
|
||||
help=mo_convert_params_mxnet['enable_ssd_gluoncv'].description,
|
||||
default=False)
|
||||
|
||||
return parser
|
||||
@@ -1289,19 +1341,20 @@ def get_kaldi_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
get_common_cli_parser(parser=parser)
|
||||
|
||||
kaldi_group = parser.add_argument_group('Kaldi-specific parameters')
|
||||
mo_convert_params_kaldi = mo_convert_params['kaldi']
|
||||
|
||||
kaldi_group.add_argument("--counts",
|
||||
help=mo_convert_params['counts'].description,
|
||||
help=mo_convert_params_kaldi['counts'].description,
|
||||
default=None,
|
||||
action=CanonicalizePathCheckExistenceIfNeededAction)
|
||||
|
||||
kaldi_group.add_argument("--remove_output_softmax",
|
||||
help=mo_convert_params['remove_output_softmax'].description,
|
||||
help=mo_convert_params_kaldi['remove_output_softmax'].description,
|
||||
action='store_true',
|
||||
default=False)
|
||||
|
||||
kaldi_group.add_argument("--remove_memory",
|
||||
help=mo_convert_params['remove_memory'].description,
|
||||
help=mo_convert_params_kaldi['remove_memory'].description,
|
||||
action='store_true',
|
||||
default=False)
|
||||
return parser
|
||||
@@ -1569,7 +1622,38 @@ def write_found_layout(name: str, found_layout: str, parsed: dict, dest: str = N
|
||||
parsed[name] = {'source_layout': s_layout, 'target_layout': t_layout}
|
||||
|
||||
|
||||
def parse_layouts_by_destination(s: str, parsed: dict, dest: str = None) -> None:
|
||||
def write_found_layout_list(idx: int, found_layout: str, parsed: list, dest: str = None):
|
||||
"""
|
||||
Writes found layout data to the 'parsed' dict.
|
||||
:param idx: idx of of the node to add layout
|
||||
:param found_layout: string containing layout for the node
|
||||
:param parsed: list where result will be stored
|
||||
:param dest: type of the command line:
|
||||
* 'source' is --source_layout
|
||||
* 'target' is --target_layout
|
||||
* None is --layout
|
||||
"""
|
||||
s_layout = None
|
||||
t_layout = None
|
||||
if idx < len(parsed):
|
||||
s_layout = parsed[idx]['source_layout']
|
||||
t_layout = parsed[idx]['target_layout']
|
||||
if dest == 'source':
|
||||
s_layout = found_layout
|
||||
elif dest == 'target':
|
||||
t_layout = found_layout
|
||||
else:
|
||||
s_layout, t_layout = split_layouts_by_arrow(found_layout)
|
||||
validate_layout(s_layout)
|
||||
validate_layout(t_layout)
|
||||
|
||||
if idx < len(parsed):
|
||||
parsed[idx] = {'source_layout': s_layout, 'target_layout': t_layout}
|
||||
else:
|
||||
parsed.append({'source_layout': s_layout, 'target_layout': t_layout})
|
||||
|
||||
|
||||
def parse_layouts_by_destination(s: str, parsed: dict, parsed_list: list, dest: str = None) -> None:
|
||||
"""
|
||||
Parses layout command line to get all names and layouts from it. Adds all found data in the 'parsed' dict.
|
||||
:param s: string to parse
|
||||
@@ -1584,29 +1668,25 @@ def parse_layouts_by_destination(s: str, parsed: dict, dest: str = None) -> None
|
||||
# single layout case
|
||||
write_found_layout('', list_s[0], parsed, dest)
|
||||
else:
|
||||
for layout_str in list_s:
|
||||
for idx, layout_str in enumerate(list_s):
|
||||
# case for: "name1(nhwc->[n,c,h,w])"
|
||||
p1 = re.compile(r'(\S+)\((\S+)\)')
|
||||
p1 = re.compile(r'(\w*)\((\S+)\)')
|
||||
m1 = p1.match(layout_str)
|
||||
# case for: "name1[n,h,w,c]->[n,c,h,w]"
|
||||
p2 = re.compile(r'(\S+)(\[\S*\])')
|
||||
p2 = re.compile(r'(\w*)(\[\S*\])')
|
||||
m2 = p2.match(layout_str)
|
||||
if m1:
|
||||
found_g = m1.groups()
|
||||
elif m2:
|
||||
found_g = m2.groups()
|
||||
else:
|
||||
error_msg = "Invalid usage of --{}layout parameter. Please use following syntax for each tensor " \
|
||||
"or operation name:" \
|
||||
"\n name(nchw)" \
|
||||
"\n name[n,c,h,w]".format(dest + '_' if dest else '')
|
||||
if dest is None:
|
||||
error_msg += "\n name(nhwc->[n,h,w,c])" \
|
||||
"\n name[n,h,w,c]->[n,c,h,w]"
|
||||
error_msg += '\n Please do not forget to surround whole expression with quotes, otherwise' \
|
||||
' symbols >[]() would be treated as special characters.'
|
||||
raise Error(error_msg)
|
||||
write_found_layout(found_g[0], found_g[1], parsed, dest)
|
||||
# case for layout without name
|
||||
write_found_layout_list(idx, layout_str, parsed_list, dest)
|
||||
continue
|
||||
if len(found_g[0]) > 0:
|
||||
write_found_layout(found_g[0], found_g[1], parsed, dest)
|
||||
else:
|
||||
write_found_layout_list(idx, found_g[1], parsed_list, dest)
|
||||
|
||||
|
||||
def get_layout_values(argv_layout: str = '', argv_source_layout: str = '', argv_target_layout: str = ''):
|
||||
@@ -1621,13 +1701,20 @@ def get_layout_values(argv_layout: str = '', argv_source_layout: str = '', argv_
|
||||
raise Error("--layout is used as well as --source_layout and/or --target_layout which is not allowed, please "
|
||||
"use one of them.")
|
||||
res = {}
|
||||
res_list = []
|
||||
if argv_layout:
|
||||
parse_layouts_by_destination(argv_layout, res)
|
||||
parse_layouts_by_destination(argv_layout, res, res_list)
|
||||
if argv_source_layout:
|
||||
parse_layouts_by_destination(argv_source_layout, res, 'source')
|
||||
parse_layouts_by_destination(argv_source_layout, res, res_list, 'source')
|
||||
if argv_target_layout:
|
||||
parse_layouts_by_destination(argv_target_layout, res, 'target')
|
||||
return res
|
||||
parse_layouts_by_destination(argv_target_layout, res, res_list, 'target')
|
||||
if len(res) > 0 and len(res_list) > 0:
|
||||
raise Error("Some layout values are provided with names, and some without names. "
|
||||
"Please provide ether all layouts with names or all layouts without names.")
|
||||
if len(res) > 0:
|
||||
return res
|
||||
else:
|
||||
return res_list
|
||||
|
||||
|
||||
def get_freeze_placeholder_values(argv_input: str, argv_freeze_placeholder_with_value: str):
|
||||
@@ -1708,6 +1795,18 @@ def split_inputs(input_str):
|
||||
|
||||
|
||||
|
||||
def split_shapes(argv_input_shape: str):
|
||||
range_reg = r'([0-9]*\.\.[0-9]*)'
|
||||
first_digit_reg = r'([0-9 ]+|-1|\?|{})'.format(range_reg)
|
||||
next_digits_reg = r'(,{})*'.format(first_digit_reg)
|
||||
tuple_reg = r'((\({}{}\))|(\[{}{}\]))'.format(first_digit_reg, next_digits_reg,
|
||||
first_digit_reg, next_digits_reg)
|
||||
|
||||
full_reg = r'^{}(\s*,\s*{})*$|^$'.format(tuple_reg, tuple_reg)
|
||||
if not re.match(full_reg, argv_input_shape):
|
||||
raise Error('Input shape "{}" cannot be parsed. ' + refer_to_faq_msg(57), argv_input_shape)
|
||||
return re.findall(r'[(\[]([0-9,\.\? -]+)[)\]]', argv_input_shape)
|
||||
|
||||
def get_placeholder_shapes(argv_input: str, argv_input_shape: str, argv_batch=None):
|
||||
"""
|
||||
Parses input layers names and input shapes from the cli and returns the parsed object.
|
||||
@@ -1769,16 +1868,9 @@ def get_placeholder_shapes(argv_input: str, argv_input_shape: str, argv_batch=No
|
||||
inputs_list = list()
|
||||
placeholder_shapes = None
|
||||
|
||||
range_reg = r'([0-9]*\.\.[0-9]*)'
|
||||
first_digit_reg = r'([0-9 ]+|-1|\?|{})'.format(range_reg)
|
||||
next_digits_reg = r'(,{})*'.format(first_digit_reg)
|
||||
tuple_reg = r'((\({}{}\))|(\[{}{}\]))'.format(first_digit_reg, next_digits_reg,
|
||||
first_digit_reg, next_digits_reg)
|
||||
|
||||
if argv_input_shape:
|
||||
full_reg = r'^{}(\s*,\s*{})*$|^$'.format(tuple_reg, tuple_reg)
|
||||
if not re.match(full_reg, argv_input_shape):
|
||||
raise Error('Input shape "{}" cannot be parsed. ' + refer_to_faq_msg(57), argv_input_shape)
|
||||
shapes = re.findall(r'[(\[]([0-9,\.\? -]+)[)\]]', argv_input_shape)
|
||||
shapes = split_shapes(argv_input_shape)
|
||||
|
||||
if argv_input:
|
||||
inputs = split_inputs(argv_input)
|
||||
@@ -1786,10 +1878,9 @@ def get_placeholder_shapes(argv_input: str, argv_input_shape: str, argv_batch=No
|
||||
|
||||
# check number of shapes with no input provided
|
||||
if argv_input_shape and not argv_input:
|
||||
if len(shapes) > 1:
|
||||
raise Error('Please provide input layer names for input layer shapes. ' + refer_to_faq_msg(58))
|
||||
else:
|
||||
placeholder_shapes = PartialShape(shapes[0])
|
||||
placeholder_shapes = [PartialShape(shape) for shape in shapes]
|
||||
if len(placeholder_shapes) == 1:
|
||||
placeholder_shapes = PartialShape(placeholder_shapes[0])
|
||||
# check if number of shapes does not match number of passed inputs
|
||||
elif argv_input and (len(shapes) == len(inputs) or len(shapes) == 0):
|
||||
# clean inputs from values for freezing
|
||||
|
||||
@@ -9,8 +9,6 @@ import sys
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
|
||||
|
||||
@@ -12,10 +12,22 @@ from openvino.tools.mo.load.loader import Loader
|
||||
from openvino.tools.mo.middle.replacement import MiddleReplacementPattern
|
||||
from openvino.tools.mo.ops.op import Op
|
||||
from openvino.tools.mo.utils.class_registration import _check_unique_ids, update_registration, \
|
||||
get_enabled_and_disabled_transforms
|
||||
get_enabled_and_disabled_transforms, clear_registered_classes_dict
|
||||
from openvino.tools.mo.utils.model_analysis import AnalyzeAction
|
||||
|
||||
|
||||
def get_internal_dirs(framework: str, get_front_classes: callable):
|
||||
front_classes = get_front_classes()
|
||||
return {
|
||||
('ops', ): [Op],
|
||||
('analysis',): [AnalyzeAction],
|
||||
('load', framework): [Loader],
|
||||
('front', ): front_classes,
|
||||
('front', framework): front_classes,
|
||||
('front', framework, 'extractors'): front_classes,
|
||||
('middle', ): [MiddleReplacementPattern],
|
||||
('back', ): [BackReplacementPattern]}
|
||||
|
||||
def import_by_path(path: str, middle_names: list = (), prefix: str = ''):
|
||||
for module_loader, name, ispkg in pkgutil.iter_modules([path]):
|
||||
importlib.import_module('{}{}.{}'.format(prefix, '.'.join(middle_names), name))
|
||||
@@ -60,27 +72,28 @@ def load_dir(framework: str, path: str, get_front_classes: callable):
|
||||
|
||||
enabled_transforms, disabled_transforms = get_enabled_and_disabled_transforms()
|
||||
|
||||
front_classes = get_front_classes()
|
||||
internal_dirs = {
|
||||
('ops', ): [Op],
|
||||
('analysis',): [AnalyzeAction],
|
||||
('load', framework): [Loader],
|
||||
('front', ): front_classes,
|
||||
('front', framework): front_classes,
|
||||
('front', framework, 'extractors'): front_classes,
|
||||
('middle', ): [MiddleReplacementPattern],
|
||||
('back', ): [BackReplacementPattern]}
|
||||
internal_dirs = get_internal_dirs(framework, get_front_classes)
|
||||
prefix = 'openvino.tools.' if ext == 'mo' else ''
|
||||
|
||||
exclude_modules = {'tf', 'onnx', 'kaldi', 'mxnet', 'caffe'}
|
||||
exclude_modules.remove(framework)
|
||||
|
||||
for p in internal_dirs.keys():
|
||||
import_by_path(os.path.join(path, *p), [ext, *p], prefix)
|
||||
update_registration(internal_dirs[p], enabled_transforms, disabled_transforms)
|
||||
update_registration(internal_dirs[p], enabled_transforms, disabled_transforms, exclude_modules)
|
||||
sys.path.remove(root_dir)
|
||||
|
||||
|
||||
def load_dirs(framework: str, dirs: list, get_front_classes: callable):
|
||||
if dirs is None:
|
||||
return
|
||||
internal_dirs = get_internal_dirs(framework, get_front_classes)
|
||||
|
||||
for p, dir_names in internal_dirs.items():
|
||||
for d in dir_names:
|
||||
d.registered_cls = []
|
||||
d.registered_ops = {}
|
||||
clear_registered_classes_dict()
|
||||
|
||||
mo_inner_extensions = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, 'mo'))
|
||||
dirs.insert(0, mo_inner_extensions)
|
||||
|
||||
@@ -65,7 +65,7 @@ def collect_ops(path: str):
|
||||
import_by_path(os.path.join(path, 'mo', 'ops'), ['mo', 'ops'], 'openvino.tools.')
|
||||
update_registration(classes=[Op, Activation, Elementwise, UnaryElementwise, LogicalElementwise,
|
||||
EmbeddingBagBase, ReduceOp, Scatter, ScatterNDBase, FFTBase],
|
||||
enabled_transforms=[], disabled_transforms=[])
|
||||
enabled_transforms=[], disabled_transforms=[], exclude_modules=set())
|
||||
|
||||
|
||||
def collect_extenders(path: str):
|
||||
@@ -76,7 +76,7 @@ def collect_extenders(path: str):
|
||||
"""
|
||||
import_by_path(os.path.join(path, 'mo', 'utils', 'ir_reader', 'extenders'),
|
||||
['mo', 'utils', 'ir_reader', 'extenders'], 'openvino.tools.')
|
||||
update_registration(classes=[Extender], enabled_transforms=[], disabled_transforms=[])
|
||||
update_registration(classes=[Extender], enabled_transforms=[], disabled_transforms=[], exclude_modules=set())
|
||||
|
||||
|
||||
def collect_node_outputs(node: Node) -> dict:
|
||||
|
||||
@@ -11,8 +11,6 @@ import sys
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
|
||||
|
||||
@@ -7,13 +7,12 @@ import os
|
||||
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
# disable eager execution of TensorFlow 2 environment immediately
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
|
||||
#in some environment suppressing through TF_CPP_MIN_LOG_LEVEL does not work
|
||||
tf_v1.get_logger().setLevel("ERROR")
|
||||
from tensorflow.python.eager.context import graph_mode
|
||||
|
||||
try:
|
||||
import tensorflow.contrib # pylint: disable=no-name-in-module,import-error
|
||||
@@ -27,8 +26,9 @@ def dump_for_tensorboard(graph_def: tf_v1.GraphDef, logdir: str):
|
||||
try:
|
||||
# TODO: graph_def is a deprecated argument, use graph instead
|
||||
print('Writing an event file for the tensorboard...')
|
||||
with tf_v1.summary.FileWriter(logdir=logdir, graph_def=graph_def) as writer:
|
||||
writer.flush()
|
||||
with graph_mode():
|
||||
with tf_v1.summary.FileWriter(logdir=logdir, graph_def=graph_def) as writer:
|
||||
writer.flush()
|
||||
print('Done writing an event file.')
|
||||
except Exception as err:
|
||||
raise Error('Cannot write an event file for the tensorboard to directory "{}". ' +
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
import numpy as np
|
||||
from generator import generator, generate
|
||||
from openvino.runtime import serialize
|
||||
|
||||
@@ -16,7 +17,6 @@ from utils import create_onnx_model, save_to_onnx
|
||||
|
||||
@generator
|
||||
class ConvertImportMOTest(UnitTestWithMockedTelemetry):
|
||||
# Checks convert import from openvino.tools.mo
|
||||
test_directory = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
@generate(*[
|
||||
@@ -24,15 +24,16 @@ class ConvertImportMOTest(UnitTestWithMockedTelemetry):
|
||||
({'input': InputCutInfo(name='LeakyRelu_out', shape=None, type=None, value=None)}),
|
||||
({'layout': {'input': LayoutMap(source_layout='NCHW', target_layout='NHWC')}}),
|
||||
])
|
||||
# Checks convert import from openvino.tools.mo
|
||||
def test_import(self, params):
|
||||
from openvino.tools.mo import convert
|
||||
from openvino.tools.mo import convert_model
|
||||
|
||||
with tempfile.TemporaryDirectory(dir=self.test_directory) as tmpdir:
|
||||
model = create_onnx_model()
|
||||
model_path = save_to_onnx(model, tmpdir)
|
||||
out_xml = os.path.join(tmpdir, "model.xml")
|
||||
|
||||
ov_model = convert(input_model=model_path, **params)
|
||||
ov_model = convert_model(input_model=model_path, **params)
|
||||
serialize(ov_model, out_xml.encode('utf-8'), out_xml.replace('.xml', '.bin').encode('utf-8'))
|
||||
assert os.path.exists(out_xml)
|
||||
|
||||
@@ -93,14 +94,13 @@ class ConvertImportMOTest(UnitTestWithMockedTelemetry):
|
||||
('sigmoid_data', 'result'),
|
||||
])
|
||||
|
||||
from openvino.tools.mo import convert
|
||||
from openvino.tools.mo import convert_model
|
||||
with tempfile.TemporaryDirectory(dir=self.test_directory) as tmpdir:
|
||||
|
||||
model = create_onnx_model()
|
||||
model_path = save_to_onnx(model, tmpdir)
|
||||
out_xml = os.path.join(tmpdir, "model.xml")
|
||||
|
||||
ov_model = convert(model_path)
|
||||
ov_model = convert_model(model_path)
|
||||
serialize(ov_model, out_xml.encode('utf-8'), out_xml.replace('.xml', '.bin').encode('utf-8'))
|
||||
|
||||
ir = IREngine(out_xml, out_xml.replace('.xml', '.bin'))
|
||||
|
||||
@@ -9,7 +9,7 @@ from generator import generator
|
||||
from openvino.runtime import get_version as get_rt_version
|
||||
from openvino.runtime import serialize
|
||||
|
||||
from openvino.tools.mo import convert
|
||||
from openvino.tools.mo import convert_model
|
||||
from openvino.tools.mo.utils import import_extensions
|
||||
from openvino.tools.mo.utils.version import get_version
|
||||
from unit_tests.mo.unit_test_with_mocked_telemetry import UnitTestWithMockedTelemetry
|
||||
@@ -93,7 +93,7 @@ class MetaDataTest(UnitTestWithMockedTelemetry):
|
||||
model_path = save_to_onnx(model, tmpdir)
|
||||
out_xml = os.path.join(tmpdir, "model.xml")
|
||||
|
||||
ov_model = convert(model_path)
|
||||
ov_model = convert_model(model_path)
|
||||
check_meta_data(ov_model)
|
||||
|
||||
serialize(ov_model, out_xml.encode('utf-8'), out_xml.replace('.xml', '.bin').encode('utf-8'))
|
||||
|
||||
@@ -34,19 +34,21 @@ class ConvertToPBTests(unittest.TestCase):
|
||||
def test_meta_format(self):
|
||||
try:
|
||||
import tensorflow.compat.v1 as tf_v1
|
||||
tf_v1.disable_eager_execution()
|
||||
except ImportError:
|
||||
import tensorflow as tf_v1
|
||||
from tensorflow.python.eager.context import graph_mode
|
||||
|
||||
with tempfile.TemporaryDirectory(dir=self.test_directory) as tmp_dir:
|
||||
a = tf_v1.get_variable("A", initializer=tf_v1.constant(3, shape=[2]))
|
||||
b = tf_v1.get_variable("B", initializer=tf_v1.constant(5, shape=[2]))
|
||||
tf_v1.add(a, b, name='Add')
|
||||
init_op = tf_v1.global_variables_initializer()
|
||||
saver = tf_v1.train.Saver()
|
||||
with tf_v1.Session() as sess:
|
||||
sess.run(init_op)
|
||||
saver.save(sess, os.path.join(tmp_dir, 'model'))
|
||||
with graph_mode():
|
||||
a = tf_v1.get_variable("A", initializer=tf_v1.constant(3, shape=[2]))
|
||||
b = tf_v1.get_variable("B", initializer=tf_v1.constant(5, shape=[2]))
|
||||
tf_v1.add(a, b, name='Add')
|
||||
init_op = tf_v1.global_variables_initializer()
|
||||
saver = tf_v1.train.Saver()
|
||||
with tf_v1.Session() as sess:
|
||||
sess.run(init_op)
|
||||
saver.save(sess, os.path.join(tmp_dir, 'model'))
|
||||
|
||||
self.argv.input_meta_graph = os.path.join(tmp_dir, 'model.meta')
|
||||
self.argv.output_dir = tmp_dir
|
||||
path_to_pb = convert_to_pb(self.argv)
|
||||
|
||||
@@ -225,3 +225,18 @@ class TestConvertingConvertArgumentsToString(UnitTestWithMockedTelemetry):
|
||||
self.assertRaises(Exception, layout_param_to_str, **{"value": {"op": Dimension(1)}})
|
||||
self.assertRaises(Exception, layout_param_to_str, **{"value": {("a", "b"): Layout("nhwc")}})
|
||||
self.assertRaises(Exception, layout_param_to_str, **{"value": Dimension(1)})
|
||||
|
||||
layout = ["nhwc", "[n,c]"]
|
||||
self.assertTrue(layout_param_to_str(layout) == "nhwc,[n,c]")
|
||||
|
||||
layout = ["abc->cab", "..nc"]
|
||||
self.assertTrue(layout_param_to_str(layout) == "abc->cab,..nc")
|
||||
|
||||
layout_map1 = LayoutMap(source_layout=Layout("n??"), target_layout=None)
|
||||
layout = [layout_map1, "..nc"]
|
||||
self.assertTrue(layout_param_to_str(layout) == "[N,?,?],..nc")
|
||||
|
||||
layout_map2 = LayoutMap(source_layout=Layout("nhwc"), target_layout=("nchw"))
|
||||
layout_map3 = LayoutMap(source_layout="abc", target_layout="cab")
|
||||
layout = [layout_map2, layout_map3]
|
||||
self.assertTrue(layout_param_to_str(layout) == "[N,H,W,C]->nchw,abc->cab")
|
||||
|
||||
@@ -738,11 +738,6 @@ class TestShapesParsing(UnitTestWithMockedTelemetry):
|
||||
input_shapes = "(1,22,333,123), (-1,45,7,1), (-1,456,7,1)"
|
||||
self.assertRaises(Error, get_placeholder_shapes, argv_input, input_shapes)
|
||||
|
||||
def test_get_shapes_several_shapes_no_input(self):
|
||||
argv_input = ""
|
||||
input_shapes = "(1,22,333,123), (-1,45,7,1), (-1,456,7,1)"
|
||||
self.assertRaises(Error, get_placeholder_shapes, argv_input, input_shapes)
|
||||
|
||||
def test_get_shapes_one_input_one_shape(self):
|
||||
argv_input = "inp1"
|
||||
input_shapes = "(1,22,333,123)"
|
||||
@@ -774,10 +769,6 @@ class TestShapesParsing(UnitTestWithMockedTelemetry):
|
||||
exp_res = np.array([12, 4, 1])
|
||||
assert np.array_equal(result, exp_res)
|
||||
|
||||
def test_get_shapes_no_input_two_shapes(self):
|
||||
argv_input = ""
|
||||
input_shapes = "(12,4,1),(5,4,3)"
|
||||
self.assertRaises(Error, get_placeholder_shapes, argv_input, input_shapes)
|
||||
|
||||
def test_get_shapes_one_input_no_shape(self):
|
||||
argv_input = "inp1"
|
||||
@@ -1606,20 +1597,351 @@ class TestLayoutParsing(unittest.TestCase):
|
||||
res = get_layout_values(argv_layout=argv_layout)
|
||||
print(res)
|
||||
|
||||
def test_get_layout_raises_multiple_layouts_without_names(self):
|
||||
argv_layout = "nhwc->nchw,nhwc->nchw"
|
||||
with self.assertRaises(Error):
|
||||
res = get_layout_values(argv_layout=argv_layout)
|
||||
print(res)
|
||||
|
||||
def test_get_layout_raises_multiple_layouts_without_names_source_layout(self):
|
||||
class TestLayoutParsingEmptyNames(unittest.TestCase):
|
||||
def test_get_layout_1(self):
|
||||
argv_layout = "([n,h,w,c]),([n,h,w,c]->[n,c,h,w])"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': None},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_2(self):
|
||||
argv_layout = "(nhwc),(nhwc->nchw)"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': 'nhwc', 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_3(self):
|
||||
argv_layout = "(n...c),(n...c->nc...)"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'n...c', 'target_layout': None},
|
||||
{'source_layout': 'n...c', 'target_layout': 'nc...'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_scalar(self):
|
||||
argv_layout = "(nhwc),([])"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_3(self):
|
||||
argv_source_layout = "(nhwc),(nchw)"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': 'nchw', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_4(self):
|
||||
argv_source_layout = "([n,h,w,c]),([n,c,h,w])"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_5(self):
|
||||
argv_source_layout = "(nhwc),([n,c,h,w])"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_6(self):
|
||||
argv_source_layout = "(nhwc),[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_scalar(self):
|
||||
argv_source_layout = "(nhwc),([])"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_3(self):
|
||||
argv_target_layout = "(nhwc),(nchw)"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_4(self):
|
||||
argv_target_layout = "([n,h,w,c]),([n,c,h,w])"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': '[n,h,w,c]'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_5(self):
|
||||
argv_target_layout = "(nhwc),([n,c,h,w])"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_6(self):
|
||||
argv_target_layout = "(nhwc),[n,c,h,w]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_scalar(self):
|
||||
argv_target_layout = "(nhwc),[]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_3(self):
|
||||
argv_source_layout = "(nhwc),(nhwc)"
|
||||
argv_target_layout = "(nchw),(nchw)"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': 'nhwc', 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_4(self):
|
||||
argv_source_layout = "([n,h,w,c]),([n,h,w,c])"
|
||||
argv_target_layout = "([n,c,h,w]),([n,c,h,w])"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_5(self):
|
||||
argv_source_layout = "(nhwc),[n,h,w,c]"
|
||||
argv_target_layout = "(nchw),[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_scalar(self):
|
||||
argv_source_layout = "(nhwc),[]"
|
||||
argv_target_layout = "(nchw),[]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': '[]', 'target_layout': '[]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
|
||||
class TestLayoutParsingEmptyNamesNoBrackets(unittest.TestCase):
|
||||
def test_get_layout_1(self):
|
||||
argv_layout = "[n,h,w,c],[n,h,w,c]->[n,c,h,w]"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': None},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_2(self):
|
||||
argv_layout = "nhwc,nhwc->nchw"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': 'nhwc', 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_3(self):
|
||||
argv_layout = "n...c,n...c->nc..."
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'n...c', 'target_layout': None},
|
||||
{'source_layout': 'n...c', 'target_layout': 'nc...'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_scalar(self):
|
||||
argv_layout = "nhwc,[]"
|
||||
result = get_layout_values(argv_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_3(self):
|
||||
argv_source_layout = "nhwc,nchw"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': 'nchw', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_4(self):
|
||||
argv_source_layout = "[n,h,w,c],[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_5(self):
|
||||
argv_source_layout = "nhwc,[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_6(self):
|
||||
argv_source_layout = "nhwc,[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[n,c,h,w]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_layout_scalar(self):
|
||||
argv_source_layout = "nhwc,[]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': None},
|
||||
{'source_layout': '[]', 'target_layout': None}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_3(self):
|
||||
argv_target_layout = "nhwc,nchw"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_4(self):
|
||||
argv_target_layout = "[n,h,w,c],[n,c,h,w]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': '[n,h,w,c]'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_5(self):
|
||||
argv_target_layout = "nhwc,[n,c,h,w]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_6(self):
|
||||
argv_target_layout = "nhwc,[n,c,h,w]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_target_layout_scalar(self):
|
||||
argv_target_layout = "nhwc,[]"
|
||||
result = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': None, 'target_layout': 'nhwc'},
|
||||
{'source_layout': None, 'target_layout': '[]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_3(self):
|
||||
argv_source_layout = "nhwc,nhwc"
|
||||
with self.assertRaises(Error):
|
||||
res = get_layout_values(argv_source_layout=argv_source_layout)
|
||||
print(res)
|
||||
|
||||
def test_get_layout_raises_multiple_layouts_without_names_target_layout(self):
|
||||
argv_target_layout = "nchw,nchw"
|
||||
with self.assertRaises(Error):
|
||||
res = get_layout_values(argv_target_layout=argv_target_layout)
|
||||
print(res)
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': 'nhwc', 'target_layout': 'nchw'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_4(self):
|
||||
argv_source_layout = "[n,h,w,c],[n,h,w,c]"
|
||||
argv_target_layout = "[n,c,h,w],[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_5(self):
|
||||
argv_source_layout = "nhwc,[n,h,w,c]"
|
||||
argv_target_layout = "nchw,[n,c,h,w]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': '[n,h,w,c]', 'target_layout': '[n,c,h,w]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def test_get_layout_source_target_layout_scalar(self):
|
||||
argv_source_layout = "nhwc,[]"
|
||||
argv_target_layout = "nchw,[]"
|
||||
result = get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout)
|
||||
exp_res = [{'source_layout': 'nhwc', 'target_layout': 'nchw'},
|
||||
{'source_layout': '[]', 'target_layout': '[]'}]
|
||||
self.assertEqual(exp_res, result)
|
||||
for i in range(len(exp_res)):
|
||||
assert np.array_equal(result[i], exp_res[i])
|
||||
|
||||
def wrong_case_1(self):
|
||||
argv_source_layout = "[n,h,w,c]),[n,h,w,c]"
|
||||
argv_target_layout = "[n,c,h,w],[n,c,h,w]"
|
||||
self.assertRaises(get_layout_values(argv_source_layout=argv_source_layout, argv_target_layout=argv_target_layout))
|
||||
|
||||
def wrong_case_2(self):
|
||||
argv_source_layout = "[nchv"
|
||||
self.assertRaises(get_layout_values(argv_source_layout=argv_source_layout))
|
||||
|
||||
def wrong_case_3(self):
|
||||
argv_source_layout = "nchv->"
|
||||
self.assertRaises(get_layout_values(argv_source_layout=argv_source_layout))
|
||||
Reference in New Issue
Block a user