Add Model Optimizer --transform option (#5504)
* Execute MO stages inside subprocess to have single IE check * Add --transform key * Updated ofline transformations to execute user specified passes; updated logic to raise when --transform is used * Parametrize LowLatency transformation with num_iterations key * Fixed MO and IE versions comparision * Use subprocess for offline transformations execution to catch errors * remove ie_is_available from IR; fixed typo * Fix for old IE versions * Update parse_transform key unit tests * Show available transformations * Fixed typo * Fix review comments * Fix python2 compatibility * Fixed review comments * Fixed __main__ import
This commit is contained in:
+3
-2
@@ -6,6 +6,7 @@ from ..inference_engine.ie_api cimport IENetwork
|
||||
|
||||
from libcpp cimport bool
|
||||
from libcpp.string cimport string
|
||||
from libc.stdint cimport int64_t
|
||||
|
||||
|
||||
def ApplyMOCTransformations(IENetwork network, bool cf):
|
||||
@@ -16,8 +17,8 @@ def ApplyPOTTransformations(IENetwork network, string device):
|
||||
C.ApplyPOTTransformations(network.impl, device)
|
||||
|
||||
|
||||
def ApplyLowLatencyTransformation(IENetwork network):
|
||||
C.ApplyLowLatencyTransformation(network.impl)
|
||||
def ApplyLowLatencyTransformation(IENetwork network, int64_t num_iterations=1):
|
||||
C.ApplyLowLatencyTransformation(network.impl, num_iterations)
|
||||
|
||||
|
||||
def ApplyPruningTransformation(IENetwork network):
|
||||
|
||||
+2
-1
@@ -26,8 +26,9 @@ void InferenceEnginePython::ApplyPOTTransformations(InferenceEnginePython::IENet
|
||||
manager.run_passes(network.actual->getFunction());
|
||||
}
|
||||
|
||||
void InferenceEnginePython::ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network) {
|
||||
void InferenceEnginePython::ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network, int64_t num_iterations) {
|
||||
ngraph::pass::Manager manager;
|
||||
// TODO: pass num_iterations to LowLatency
|
||||
manager.register_pass<ngraph::pass::LowLatency>();
|
||||
manager.register_pass<ngraph::pass::UnrollTensorIterator>();
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ void ApplyMOCTransformations(InferenceEnginePython::IENetwork network, bool cf);
|
||||
|
||||
void ApplyPOTTransformations(InferenceEnginePython::IENetwork network, std::string device);
|
||||
|
||||
void ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network);
|
||||
void ApplyLowLatencyTransformation(InferenceEnginePython::IENetwork network, int64_t num_iterations);
|
||||
|
||||
void ApplyPruningTransformation(InferenceEnginePython::IENetwork network);
|
||||
|
||||
|
||||
+2
-1
@@ -3,6 +3,7 @@
|
||||
|
||||
from libcpp cimport bool
|
||||
from libcpp.string cimport string
|
||||
from libc.stdint cimport int64_t
|
||||
|
||||
from ..inference_engine.ie_api_impl_defs cimport IENetwork
|
||||
|
||||
@@ -11,7 +12,7 @@ cdef extern from "offline_transformations_api_impl.hpp" namespace "InferenceEngi
|
||||
|
||||
cdef void ApplyPOTTransformations(IENetwork network, string device)
|
||||
|
||||
cdef void ApplyLowLatencyTransformation(IENetwork network)
|
||||
cdef void ApplyLowLatencyTransformation(IENetwork network, int64_t num_iterations)
|
||||
|
||||
cdef void ApplyPruningTransformation(IENetwork network)
|
||||
|
||||
|
||||
@@ -939,6 +939,11 @@ mo/graph/graph.py
|
||||
mo/graph/perm_inputs.py
|
||||
mo/graph/port.py
|
||||
mo/main.py
|
||||
mo/main_caffe.py
|
||||
mo/main_kaldi.py
|
||||
mo/main_mxnet.py
|
||||
mo/main_onnx.py
|
||||
mo/main_tf.py
|
||||
mo/middle/__init__.py
|
||||
mo/middle/passes/__init__.py
|
||||
mo/middle/passes/conv.py
|
||||
@@ -1004,6 +1009,7 @@ mo/ops/unsqueeze.py
|
||||
mo/pipeline/__init__.py
|
||||
mo/pipeline/common.py
|
||||
mo/pipeline/unified.py
|
||||
mo/subprocess_main.py
|
||||
mo/utils/__init__.py
|
||||
mo/utils/broadcasting.py
|
||||
mo/utils/check_ie_bindings.py
|
||||
|
||||
+2
-11
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_all_cli_parser # pylint: disable=no-name-in-module
|
||||
|
||||
sys.exit(main(get_all_cli_parser(), None))
|
||||
from mo.subprocess_main import subprocess_main # pylint: disable=no-name-in-module
|
||||
subprocess_main(framework=None)
|
||||
|
||||
@@ -1,16 +1,5 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module
|
||||
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_all_cli_parser # pylint: disable=no-name-in-module
|
||||
|
||||
sys.exit(main(get_all_cli_parser(), None))
|
||||
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework=None)
|
||||
|
||||
@@ -3,28 +3,48 @@
|
||||
|
||||
import argparse
|
||||
|
||||
from mo.utils.error import Error
|
||||
from mo.utils.cli_parser import parse_transform
|
||||
|
||||
|
||||
def get_available_transformations():
|
||||
try:
|
||||
from openvino.offline_transformations import ApplyLowLatencyTransformation # pylint: disable=import-error
|
||||
return {
|
||||
'LowLatency': ApplyLowLatencyTransformation,
|
||||
}
|
||||
except Exception as e:
|
||||
return {}
|
||||
|
||||
|
||||
def apply_offline_transformations(input_model: str, framework: str, transforms: list):
|
||||
# This variable is only needed by GenerateMappingFile transformation
|
||||
# to produce correct mapping
|
||||
extract_names = framework in ['tf', 'mxnet', 'kaldi']
|
||||
|
||||
from openvino.inference_engine import read_network # pylint: disable=import-error
|
||||
from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile # pylint: disable=import-error
|
||||
|
||||
net = read_network(input_model + "_tmp.xml", input_model + "_tmp.bin")
|
||||
|
||||
available_transformations = get_available_transformations()
|
||||
|
||||
for name, args in transforms:
|
||||
if name not in available_transformations.keys():
|
||||
raise Error("Transformation {} is not available.".format(name))
|
||||
|
||||
available_transformations[name](net, **args)
|
||||
|
||||
net.serialize(input_model + ".xml", input_model + ".bin")
|
||||
path_to_mapping = input_model + ".mapping"
|
||||
GenerateMappingFile(net, path_to_mapping.encode('utf-8'), extract_names)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--input_model")
|
||||
parser.add_argument("--framework")
|
||||
parser.add_argument("--transform")
|
||||
args = parser.parse_args()
|
||||
path_to_model = args.input_model
|
||||
|
||||
# This variable is only needed by GenerateMappingFile transformation
|
||||
# to produce correct mapping
|
||||
extract_names = True if args.framework in ['tf', 'mxnet', 'kaldi'] else False
|
||||
|
||||
try:
|
||||
from openvino.inference_engine import IECore, read_network # pylint: disable=import-error
|
||||
from openvino.offline_transformations import ApplyMOCTransformations, GenerateMappingFile, CheckAPI # pylint: disable=import-error
|
||||
except Exception as e:
|
||||
print("[ WARNING ] {}".format(e))
|
||||
exit(1)
|
||||
|
||||
CheckAPI()
|
||||
|
||||
net = read_network(path_to_model + "_tmp.xml", path_to_model + "_tmp.bin")
|
||||
net.serialize(path_to_model + ".xml", path_to_model + ".bin")
|
||||
path_to_mapping = path_to_model + ".mapping"
|
||||
GenerateMappingFile(net, path_to_mapping.encode('utf-8'), extract_names)
|
||||
|
||||
apply_offline_transformations(args.input_model, args.framework, parse_transform(args.transform))
|
||||
@@ -6,8 +6,8 @@ import datetime
|
||||
import logging as log
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import subprocess
|
||||
import traceback
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
@@ -24,7 +24,8 @@ from mo.pipeline.unified import unified_pipeline
|
||||
from mo.utils import import_extensions
|
||||
from mo.utils.cli_parser import get_placeholder_shapes, get_tuple_values, get_model_name, \
|
||||
get_common_cli_options, get_caffe_cli_options, get_tf_cli_options, get_mxnet_cli_options, get_kaldi_cli_options, \
|
||||
get_onnx_cli_options, get_mean_scale_dictionary, parse_tuple_pairs, get_freeze_placeholder_values, get_meta_info
|
||||
get_onnx_cli_options, get_mean_scale_dictionary, parse_tuple_pairs, get_freeze_placeholder_values, get_meta_info, \
|
||||
parse_transform, check_available_transforms
|
||||
from mo.utils.error import Error, FrameworkError
|
||||
from mo.utils.find_ie_version import find_ie_version
|
||||
from mo.utils.get_ov_update_message import get_ov_update_message
|
||||
@@ -33,7 +34,7 @@ from mo.utils.logger import init_logger
|
||||
from mo.utils.model_analysis import AnalysisResults
|
||||
from mo.utils.utils import refer_to_faq_msg
|
||||
from mo.utils.version import get_version, get_simplified_mo_version, get_simplified_ie_version
|
||||
from mo.utils.versions_checker import check_requirements
|
||||
from mo.utils.versions_checker import check_requirements # pylint: disable=no-name-in-module
|
||||
|
||||
|
||||
def replace_ext(name: str, old: str, new: str):
|
||||
@@ -141,14 +142,22 @@ def prepare_ir(argv: argparse.Namespace):
|
||||
# This try-except is additional reinsurance that the IE
|
||||
# dependency search does not break the MO pipeline
|
||||
try:
|
||||
if not find_ie_version(silent=argv.silent) and not argv.silent:
|
||||
argv.ie_is_available = find_ie_version(silent=argv.silent)
|
||||
|
||||
if not argv.ie_is_available and not argv.silent:
|
||||
print("[ WARNING ] Could not find the Inference Engine Python API. At this moment, the Inference Engine dependency is not required, but will be required in future releases.")
|
||||
print("[ WARNING ] Consider building the Inference Engine Python API from sources or try to install OpenVINO (TM) Toolkit using \"install_prerequisites.{}\"".format(
|
||||
"bat" if sys.platform == "windows" else "sh"))
|
||||
# If the IE was not found, it will not print the MO version, so we have to print it manually
|
||||
print("{}: \t{}".format("Model Optimizer version", get_version()))
|
||||
except Exception as e:
|
||||
pass
|
||||
argv.ie_is_available = False
|
||||
|
||||
# This is just to check that transform key is valid and transformations are available
|
||||
check_available_transforms(parse_transform(argv.transform), argv.ie_is_available)
|
||||
|
||||
if argv.legacy_ir_generation and len(argv.transform) != 0:
|
||||
raise Error("--legacy_ir_generation and --transform keys can not be used at the same time.")
|
||||
|
||||
ret_code = check_requirements(framework=argv.framework)
|
||||
if ret_code:
|
||||
@@ -250,6 +259,10 @@ def emit_ir(graph: Graph, argv: argparse.Namespace):
|
||||
mean_data = deepcopy(graph.graph['mf']) if 'mf' in graph.graph else None
|
||||
input_names = deepcopy(graph.graph['input_names']) if 'input_names' in graph.graph else []
|
||||
|
||||
# Remove temporary ie_is_available key from argv no to have it in IR
|
||||
ie_is_available = argv.ie_is_available
|
||||
del argv.ie_is_available
|
||||
|
||||
prepare_emit_ir(graph=graph,
|
||||
data_type=graph.graph['cmd_params'].data_type,
|
||||
output_dir=argv.output_dir,
|
||||
@@ -270,16 +283,16 @@ def emit_ir(graph: Graph, argv: argparse.Namespace):
|
||||
# This try-except is additional reinsurance that the IE
|
||||
# dependency search does not break the MO pipeline
|
||||
try:
|
||||
if not argv.legacy_ir_generation and find_ie_version(silent=True):
|
||||
if not argv.legacy_ir_generation and ie_is_available:
|
||||
path_to_offline_transformations = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'back',
|
||||
'offline_transformations.py')
|
||||
status = subprocess.run([sys.executable, path_to_offline_transformations,
|
||||
"--input_model", orig_model_name,
|
||||
"--framework", argv.framework], env=os.environ, timeout=10)
|
||||
"--framework", argv.framework,
|
||||
"--transform", argv.transform], env=os.environ)
|
||||
return_code = status.returncode
|
||||
if return_code != 0 and not argv.silent:
|
||||
log.error("offline_transformations return code {}".format(return_code), extra={'is_warning': True})
|
||||
except Exception as e:
|
||||
return_code = "failed"
|
||||
log.error(e, extra={'is_warning': True})
|
||||
|
||||
message = str(dict({
|
||||
@@ -296,6 +309,14 @@ def emit_ir(graph: Graph, argv: argparse.Namespace):
|
||||
# produced by prepare_ir. This IR needs to be renamed from XXX_tmp.xml to XXX.xml
|
||||
suffixes = [".xml", ".bin", ".mapping"]
|
||||
if return_code != 0:
|
||||
if len(argv.transform) != 0:
|
||||
# Remove temporary IR before throwing exception
|
||||
for suf in suffixes:
|
||||
path_to_file = orig_model_name + "_tmp" + suf
|
||||
if os.path.exists(path_to_file):
|
||||
os.remove(path_to_file)
|
||||
raise Error("Failed to apply transformations: {}".format(argv.transform))
|
||||
|
||||
log.error("Using fallback to produce IR.", extra={'is_warning': True})
|
||||
for suf in suffixes:
|
||||
# remove existing files
|
||||
@@ -400,3 +421,8 @@ def main(cli_parser: argparse.ArgumentParser, framework: str):
|
||||
telemetry.end_session()
|
||||
telemetry.force_shutdown(1.0)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.utils.cli_parser import get_all_cli_parser
|
||||
sys.exit(main(get_all_cli_parser(), None))
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.cli_parser import get_caffe_cli_parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.main import main
|
||||
sys.exit(main(get_caffe_cli_parser(), 'caffe'))
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.cli_parser import get_kaldi_cli_parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.main import main
|
||||
sys.exit(main(get_kaldi_cli_parser(), 'kaldi'))
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.cli_parser import get_mxnet_cli_parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.main import main
|
||||
sys.exit(main(get_mxnet_cli_parser(), 'mxnet'))
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.cli_parser import get_onnx_cli_parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.main import main
|
||||
sys.exit(main(get_onnx_cli_parser(), 'onnx'))
|
||||
@@ -0,0 +1,10 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.cli_parser import get_tf_cli_parser
|
||||
|
||||
if __name__ == "__main__":
|
||||
from mo.main import main
|
||||
sys.exit(main(get_tf_cli_parser(), 'tf'))
|
||||
@@ -0,0 +1,42 @@
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
from mo.utils.versions_checker import check_python_version # pylint: disable=no-name-in-module
|
||||
|
||||
|
||||
def subprocess_main(framework=None):
|
||||
"""
|
||||
Please keep this file compatible with python2 in order to check user python version.
|
||||
|
||||
This function checks that Inference Engine Python API available and working as expected
|
||||
and then in sub-process it executes main_<fw>.py files. Due to some OSs specifics we can't
|
||||
just add paths to Python modules and libraries into current env. So to make Inference Engine
|
||||
Python API to be available inside MO we need to use subprocess with new env.
|
||||
"""
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.utils.find_ie_version import find_ie_version
|
||||
find_ie_version(silent=True)
|
||||
|
||||
mo_root_path = os.path.join(os.path.dirname(__file__), os.pardir)
|
||||
|
||||
python_path_key = 'PYTHONPATH'
|
||||
if python_path_key not in os.environ:
|
||||
os.environ[python_path_key] = mo_root_path
|
||||
else:
|
||||
os.environ[python_path_key] = os.pathsep.join([os.environ[python_path_key], mo_root_path])
|
||||
|
||||
path_to_main = os.path.join(os.path.realpath(os.path.dirname(__file__)),
|
||||
'main_{}.py'.format(framework) if framework else 'main.py')
|
||||
# python2 compatible code. Do not remove.
|
||||
args = [sys.executable, path_to_main]
|
||||
for arg in sys.argv[1:]:
|
||||
args.append(arg)
|
||||
status = subprocess.run(args, env=os.environ)
|
||||
sys.exit(status.returncode)
|
||||
@@ -32,11 +32,20 @@ def send_telemetry(mo_version: str, message: str, event_type: str):
|
||||
|
||||
|
||||
def import_core_modules(silent: bool, path_to_module: str):
|
||||
try:
|
||||
from openvino.inference_engine import IECore, get_version # pylint: disable=import-error
|
||||
from openvino.offline_transformations import ApplyMOCTransformations, CheckAPI # pylint: disable=import-error
|
||||
"""
|
||||
This function checks that InferenceEngine Python API is available
|
||||
and necessary python modules exists. So the next list of imports
|
||||
must contain all IE/NG Python API imports that are used inside MO.
|
||||
|
||||
import openvino # pylint: disable=import-error
|
||||
:param silent: enables or disables logs printing to stdout
|
||||
:param path_to_module: path where python API modules were found
|
||||
:return: True if all imports were successful and False otherwise
|
||||
"""
|
||||
try:
|
||||
from openvino.inference_engine import get_version, read_network # pylint: disable=import-error
|
||||
from openvino.offline_transformations import ApplyMOCTransformations, ApplyLowLatencyTransformation, GenerateMappingFile # pylint: disable=import-error
|
||||
|
||||
import openvino # pylint: disable=import-error
|
||||
|
||||
if silent:
|
||||
return True
|
||||
@@ -46,15 +55,10 @@ def import_core_modules(silent: bool, path_to_module: str):
|
||||
|
||||
print("\t- {}: \t{}".format("Inference Engine found in", os.path.dirname(openvino.__file__)))
|
||||
print("{}: \t{}".format("Inference Engine version", ie_version))
|
||||
print("{}: \t {}".format("Model Optimizer version", mo_version))
|
||||
print("{}: \t{}".format("Model Optimizer version", mo_version))
|
||||
|
||||
versions_mismatch = False
|
||||
# MO and IE version have a small difference in the beginning of version because
|
||||
# IE version also includes API version. For example:
|
||||
# Inference Engine version: 2.1.custom_HEAD_4c8eae0ee2d403f8f5ae15b2c9ad19cfa5a9e1f9
|
||||
# Model Optimizer version: custom_HEAD_4c8eae0ee2d403f8f5ae15b2c9ad19cfa5a9e1f9
|
||||
# So to match this versions we skip IE API version.
|
||||
if not re.match(r"^([0-9]+).([0-9]+).{}$".format(mo_version), ie_version):
|
||||
if mo_version != ie_version:
|
||||
versions_mismatch = True
|
||||
extracted_mo_release_version = v.extract_release_version(mo_version)
|
||||
mo_is_custom = extracted_mo_release_version == (None, None)
|
||||
|
||||
@@ -6,7 +6,6 @@ import ast
|
||||
import logging as log
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
from itertools import zip_longest
|
||||
|
||||
@@ -254,6 +253,14 @@ def get_common_cli_parser(parser: argparse.ArgumentParser = None):
|
||||
'and biases are quantized to FP16.',
|
||||
choices=["FP16", "FP32", "half", "float"],
|
||||
default='float')
|
||||
common_group.add_argument('--transform',
|
||||
help='Apply additional transformations. ' +
|
||||
'Usage: "--transform transformation_name1[args],transformation_name2..." ' +
|
||||
'where [args] is key=value pairs separated by semicolon. ' +
|
||||
'Examples: "--transform LowLatency" or ' +
|
||||
' "--transform LowLatency[num_iterations=2]" ' +
|
||||
'Available transformations: "LowLatency"',
|
||||
default="")
|
||||
common_group.add_argument('--disable_fusing',
|
||||
help='Turn off fusing of linear operations to Convolution',
|
||||
action=DeprecatedStoreTrue)
|
||||
@@ -1127,6 +1134,95 @@ def get_absolute_path(path_to_file: str) -> str:
|
||||
return file_path
|
||||
|
||||
|
||||
def isfloat(value):
|
||||
try:
|
||||
float(value)
|
||||
return True
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def convert_string_to_real_type(value: str):
|
||||
values = value.split(',')
|
||||
for i in range(len(values)):
|
||||
value = values[i]
|
||||
if value.isdigit():
|
||||
values[i] = int(value)
|
||||
elif isfloat(value):
|
||||
values[i] = float(value)
|
||||
|
||||
return values[0] if len(values) == 1 else values
|
||||
|
||||
|
||||
def parse_transform(transform: str) -> list:
|
||||
transforms = []
|
||||
|
||||
if len(transform) == 0:
|
||||
return transforms
|
||||
|
||||
all_transforms = re.findall(r"([a-zA-Z0-9]+)(\[([^\]]+)\])*(,|$)", transform)
|
||||
|
||||
# Check that all characters were matched otherwise transform key value is invalid
|
||||
key_len = len(transform)
|
||||
for transform in all_transforms:
|
||||
# In regexp we have 4 groups where 1st group - transformation_name,
|
||||
# 2nd group - [args],
|
||||
# 3rd group - args, <-- nested group
|
||||
# 4th group - EOL
|
||||
# And to check that regexp matched all string we decrease total length by the length of matched groups (1,2,4)
|
||||
# In case if no arguments were given to transformation then 2nd and 3rd groups will be empty.
|
||||
if len(transform) != 4:
|
||||
raise Error("Unexpected transform key structure: {}".format(transform))
|
||||
key_len -= len(transform[0]) + len(transform[1]) + len(transform[3])
|
||||
|
||||
if key_len != 0:
|
||||
raise Error("Unexpected transform key structure: {}".format(transform))
|
||||
|
||||
for transform in all_transforms:
|
||||
name = transform[0]
|
||||
args = transform[2]
|
||||
|
||||
args_dict = {}
|
||||
|
||||
if len(args) != 0:
|
||||
for arg in args.split(';'):
|
||||
m = re.match(r"^([_a-zA-Z]+)=(.+)$", arg)
|
||||
if not m:
|
||||
raise Error("Unrecognized attributes for transform key: {}".format(transform))
|
||||
|
||||
args_dict[m.group(1)] = convert_string_to_real_type(m.group(2))
|
||||
|
||||
transforms.append((name, args_dict))
|
||||
|
||||
return transforms
|
||||
|
||||
|
||||
def check_available_transforms(transforms: list, ie_is_available: bool):
|
||||
"""
|
||||
This function check that transformations specified by user are available.
|
||||
:param transforms: list of user specified transformations
|
||||
:param ie_is_available: True if IE Python API is available and False if it is not
|
||||
:return: raises an Error if IE or transformation is not available
|
||||
"""
|
||||
if not ie_is_available and len(transforms) != 0:
|
||||
raise Error('Can not apply {} transformations due to missing Inference Engine Python API'.format(
|
||||
','.join([name for name, _ in transforms])))
|
||||
|
||||
from mo.back.offline_transformations import get_available_transformations
|
||||
available_transforms = get_available_transformations()
|
||||
|
||||
missing_transformations = []
|
||||
for name, _ in transforms:
|
||||
if name not in available_transforms.keys():
|
||||
missing_transformations.append(name)
|
||||
|
||||
if len(missing_transformations) != 0:
|
||||
raise Error('Following transformations ({}) are not available. '
|
||||
'List with available transformations ({})'.format(','.join(missing_transformations),
|
||||
','.join(available_transforms.keys())))
|
||||
return True
|
||||
|
||||
|
||||
def check_positive(value):
|
||||
try:
|
||||
int_value = int(value)
|
||||
|
||||
@@ -65,7 +65,9 @@ def get_simplified_ie_version(env=dict(), version=None):
|
||||
version = subprocess.check_output([sys.executable, os.path.join(os.path.dirname(__file__), "ie_version.py")], timeout=2, env=env).strip().decode()
|
||||
except:
|
||||
return "ie not found"
|
||||
|
||||
# To support legacy IE versions
|
||||
m = re.match(r"^([0-9]+).([0-9]+).(.*)", version)
|
||||
if m and len(m.groups()) == 3:
|
||||
return simplify_version(m.group(3))
|
||||
return "custom"
|
||||
return simplify_version(version)
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_caffe_cli_parser
|
||||
|
||||
sys.exit(main(get_caffe_cli_parser(), 'caffe'))
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework='caffe')
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_kaldi_cli_parser
|
||||
|
||||
sys.exit(main(get_kaldi_cli_parser(), 'kaldi'))
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework='kaldi')
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_mxnet_cli_parser
|
||||
|
||||
sys.exit(main(get_mxnet_cli_parser(), 'mxnet'))
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework='mxnet')
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_onnx_cli_parser
|
||||
|
||||
sys.exit(main(get_onnx_cli_parser(), 'onnx'))
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework='onnx')
|
||||
|
||||
@@ -3,16 +3,7 @@
|
||||
# Copyright (C) 2018-2021 Intel Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import sys
|
||||
|
||||
from mo.utils.versions_checker import check_python_version
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret_code = check_python_version()
|
||||
if ret_code:
|
||||
sys.exit(ret_code)
|
||||
|
||||
from mo.main import main
|
||||
from mo.utils.cli_parser import get_tf_cli_parser
|
||||
|
||||
sys.exit(main(get_tf_cli_parser(), 'tf'))
|
||||
from mo.subprocess_main import subprocess_main
|
||||
subprocess_main(framework='tf')
|
||||
|
||||
@@ -14,7 +14,7 @@ import numpy.testing as npt
|
||||
|
||||
from mo.utils.cli_parser import get_placeholder_shapes, get_tuple_values, get_mean_scale_dictionary, get_model_name, \
|
||||
parse_tuple_pairs, check_positive, writable_dir, readable_dirs, \
|
||||
readable_file, get_freeze_placeholder_values
|
||||
readable_file, get_freeze_placeholder_values, parse_transform, check_available_transforms
|
||||
from mo.utils.error import Error
|
||||
|
||||
|
||||
@@ -898,3 +898,71 @@ class PathCheckerFunctions(unittest.TestCase):
|
||||
def test_non_readable_file(self):
|
||||
with self.assertRaises(Error) as cm:
|
||||
readable_file(__class__.NOT_EXISTING_FILE)
|
||||
|
||||
|
||||
class TransformChecker(unittest.TestCase):
|
||||
def test_empty(self):
|
||||
self.assertEqual(parse_transform(""), [])
|
||||
|
||||
def test_single_pass(self):
|
||||
self.assertEqual(parse_transform("LowLatency"), [("LowLatency", {})])
|
||||
|
||||
def test_single_pass_with_args(self):
|
||||
self.assertEqual(parse_transform("LowLatency[num_iterations=2]"),
|
||||
[("LowLatency", {"num_iterations": 2})])
|
||||
|
||||
def test_single_pass_with_multiple_args(self):
|
||||
self.assertEqual(parse_transform("LowLatency[num_iterations=2;dummy_attr=3.14]"),
|
||||
[("LowLatency", {"num_iterations": 2, "dummy_attr": 3.14})])
|
||||
|
||||
def test_multiple_passes_with_args(self):
|
||||
self.assertEqual(parse_transform("LowLatency[num_iterations=2],DummyPass[type=ReLU]"),
|
||||
[("LowLatency", {"num_iterations": 2}),
|
||||
("DummyPass", {"type": "ReLU"})])
|
||||
|
||||
def test_multiple_passes_with_args2(self):
|
||||
self.assertEqual(parse_transform("LowLatency[num_iterations=2,3,4.15],DummyPass1,DummyPass2[types=ReLU,PReLU;values=1,2,3]"),
|
||||
[("LowLatency", {"num_iterations": [2,3,4.15]}),
|
||||
("DummyPass1", {}),
|
||||
("DummyPass2", {"types": ["ReLU", "PReLU"], "values": [1,2,3]})])
|
||||
|
||||
def test_multiple_passes_no_args(self):
|
||||
self.assertEqual(parse_transform("DummyPass,LowLatency2"),
|
||||
[("DummyPass", {}), ("LowLatency2", {})])
|
||||
|
||||
def test_single_pass_neg(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency!")
|
||||
|
||||
def test_multiple_passes_neg(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency;DummyPass")
|
||||
|
||||
def test_single_pass_with_args_neg1(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[=2]")
|
||||
|
||||
def test_single_pass_with_args_neg2(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[key=]")
|
||||
|
||||
def test_single_pass_with_args_neg3(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[]")
|
||||
|
||||
def test_single_pass_with_args_neg4(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[key=value;]")
|
||||
|
||||
def test_single_pass_with_args_neg5(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[value]")
|
||||
|
||||
def test_single_pass_with_args_neg6(self):
|
||||
self.assertRaises(Error, parse_transform, "LowLatency[key=value")
|
||||
|
||||
@patch("mo.back.offline_transformations.get_available_transformations")
|
||||
def test_check_low_latency_is_available(self, available_transformations):
|
||||
available_transformations.return_value = {"LowLatency": None}
|
||||
try:
|
||||
check_available_transforms([("LowLatency" ,"")], True)
|
||||
except Error as e:
|
||||
self.assertTrue(False, "Exception \"{}\" is unexpected".format(e))
|
||||
|
||||
@patch("mo.back.offline_transformations.get_available_transformations")
|
||||
def test_check_dummy_pass_is_available(self, available_transformations):
|
||||
available_transformations.return_value = {"LowLatency": None}
|
||||
self.assertRaises(Error, check_available_transforms, [("DummyPass", "")], True)
|
||||
|
||||
@@ -52,11 +52,14 @@ class TestingVersion(unittest.TestCase):
|
||||
mock_open.return_value.__enter__ = mock_open
|
||||
self.assertEqual(get_simplified_mo_version(), "custom")
|
||||
|
||||
def test_simplify_ie_version_release(self):
|
||||
def test_simplify_ie_version_release_legacy(self):
|
||||
self.assertEqual(get_simplified_ie_version(version="2.1.custom_releases/2021/3_4c8eae"), "2021.3")
|
||||
|
||||
def test_simplify_ie_version_release_neg(self):
|
||||
self.assertEqual(get_simplified_ie_version(version="custom_releases/2021/3_4c8eae"), "custom")
|
||||
def test_simplify_ie_version_release(self):
|
||||
self.assertEqual(get_simplified_ie_version(version="custom_releases/2021/3_4c8eae"), "2021.3")
|
||||
|
||||
def test_simplify_ie_version_custom_legacy(self):
|
||||
self.assertEqual(get_simplified_ie_version(version="2.1.custom_my/branch/3_4c8eae"), "custom")
|
||||
|
||||
def test_simplify_ie_version_custom(self):
|
||||
self.assertEqual(get_simplified_ie_version(version="2.1.custom_my/branch/3_4c8eae"), "custom")
|
||||
self.assertEqual(get_simplified_ie_version(version="custom_my/branch/3_4c8eae"), "custom")
|
||||
Reference in New Issue
Block a user