Commit 6dfc7789 authored by Alexey Suhov's avatar Alexey Suhov

Publishing 2019 R3.1 content

parent 1798ac0d
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
- [Build Steps](#build-steps-2) - [Build Steps](#build-steps-2)
- [Additional Build Options](#additional-build-options-3) - [Additional Build Options](#additional-build-options-3)
- [Use Custom OpenCV Builds for Inference Engine](#use-custom-opencv-builds-for-inference-engine) - [Use Custom OpenCV Builds for Inference Engine](#use-custom-opencv-builds-for-inference-engine)
- [Adding Inference Engine to your project](#adding-inference-engine-to-your-project)
- [(Optional) Additional Installation Steps for the Intel® Movidius™ Neural Compute Stick and Neural Compute Stick 2](#optional-additional-installation-steps-for-the-intel-movidius-neural-compute-stick-and-neural-compute-stick-2) - [(Optional) Additional Installation Steps for the Intel® Movidius™ Neural Compute Stick and Neural Compute Stick 2](#optional-additional-installation-steps-for-the-intel-movidius-neural-compute-stick-and-neural-compute-stick-2)
- [For Linux, Raspbian Stretch* OS](#for-linux-raspbian-stretch-os) - [For Linux, Raspbian Stretch* OS](#for-linux-raspbian-stretch-os)
- [For Windows](#for-windows-1) - [For Windows](#for-windows-1)
...@@ -62,7 +63,13 @@ The software was validated on: ...@@ -62,7 +63,13 @@ The software was validated on:
git submodule init git submodule init
git submodule update --recursive git submodule update --recursive
``` ```
2. Install build dependencies using the `install_dependencies.sh` script in the project root folder. 2. Install build dependencies using the `install_dependencies.sh` script in the project root folder:
```sh
chmod +x install_dependencies.sh
```
```sh
./install_dependencies.sh
```
3. By default, the build enables the Inference Engine GPU plugin to infer models on your Intel® Processor Graphics. This requires you to [Install Intel® Graphics Compute Runtime for OpenCL™ Driver package 19.04.12237](https://github.com/intel/compute-runtime/releases/tag/19.04.12237) before running the build. If you don't want to use the GPU plugin, use the `-DENABLE_CLDNN=OFF` CMake build option and skip the installation of the Intel® Graphics Compute Runtime for OpenCL™ Driver. 3. By default, the build enables the Inference Engine GPU plugin to infer models on your Intel® Processor Graphics. This requires you to [Install Intel® Graphics Compute Runtime for OpenCL™ Driver package 19.04.12237](https://github.com/intel/compute-runtime/releases/tag/19.04.12237) before running the build. If you don't want to use the GPU plugin, use the `-DENABLE_CLDNN=OFF` CMake build option and skip the installation of the Intel® Graphics Compute Runtime for OpenCL™ Driver.
4. Create a build folder: 4. Create a build folder:
```sh ```sh
...@@ -90,33 +97,20 @@ You can use the following additional build options: ...@@ -90,33 +97,20 @@ You can use the following additional build options:
- If the CMake-based build script can not find and download the OpenCV package that is supported on your platform, or if you want to use a custom build of the OpenCV library, refer to the [Use Custom OpenCV Builds](#use-custom-opencv-builds-for-inference-engine) section for details. - If the CMake-based build script can not find and download the OpenCV package that is supported on your platform, or if you want to use a custom build of the OpenCV library, refer to the [Use Custom OpenCV Builds](#use-custom-opencv-builds-for-inference-engine) section for details.
- To build the Python API wrapper, use the `-DENABLE_PYTHON=ON` option. To specify an exact Python version, use the following options: - To build the Python API wrapper:
```sh 1. Install all additional packages listed in the `/inference-engine/ie_bridges/python/requirements.txt` file:
-DPYTHON_EXECUTABLE=`which python3.7` \ ```sh
-DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.7m.so \ pip install -r requirements.txt
-DPYTHON_INCLUDE_DIR=/usr/include/python3.7 ```
``` 2. use the `-DENABLE_PYTHON=ON` option. To specify an exact Python version, use the following options:
```sh
-DPYTHON_EXECUTABLE=`which python3.7` \
-DPYTHON_LIBRARY=/usr/lib/x86_64-linux-gnu/libpython3.7m.so \
-DPYTHON_INCLUDE_DIR=/usr/include/python3.7
```
- To switch off/on the CPU and GPU plugins, use the `cmake` options `-DENABLE_MKL_DNN=ON/OFF` and `-DENABLE_CLDNN=ON/OFF` respectively. - To switch off/on the CPU and GPU plugins, use the `cmake` options `-DENABLE_MKL_DNN=ON/OFF` and `-DENABLE_CLDNN=ON/OFF` respectively.
5. Adding to your project
For CMake projects, set an environment variable `InferenceEngine_DIR`:
```sh
export InferenceEngine_DIR=/path/to/dldt/inference-engine/build/
```
Then you can find Inference Engine by `find_package`:
```cmake
find_package(InferenceEngine)
include_directories(${InferenceEngine_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${InferenceEngine_LIBRARIES} dl)
```
## Build for Raspbian Stretch* OS ## Build for Raspbian Stretch* OS
> **NOTE**: Only the MYRIAD plugin is supported. > **NOTE**: Only the MYRIAD plugin is supported.
...@@ -371,7 +365,13 @@ The software was validated on: ...@@ -371,7 +365,13 @@ The software was validated on:
git submodule init git submodule init
git submodule update --recursive git submodule update --recursive
``` ```
2. Install build dependencies using the `install_dependencies.sh` script in the project root folder. 2. Install build dependencies using the `install_dependencies.sh` script in the project root folder:
```sh
chmod +x install_dependencies.sh
```
```sh
./install_dependencies.sh
```
3. Create a build folder: 3. Create a build folder:
```sh ```sh
mkdir build mkdir build
...@@ -419,6 +419,22 @@ After you got the built OpenCV library, perform the following preparation steps ...@@ -419,6 +419,22 @@ After you got the built OpenCV library, perform the following preparation steps
1. Set the `OpenCV_DIR` environment variable to the directory where the `OpenCVConfig.cmake` file of you custom OpenCV build is located. 1. Set the `OpenCV_DIR` environment variable to the directory where the `OpenCVConfig.cmake` file of you custom OpenCV build is located.
2. Disable the package automatic downloading with using the `-DENABLE_OPENCV=OFF` option for CMake-based build script for Inference Engine. 2. Disable the package automatic downloading with using the `-DENABLE_OPENCV=OFF` option for CMake-based build script for Inference Engine.
## Adding Inference Engine to your project
For CMake projects, set the `InferenceEngine_DIR` environment variable:
```sh
export InferenceEngine_DIR=/path/to/dldt/inference-engine/build/
```
Then you can find Inference Engine by `find_package`:
```cmake
find_package(InferenceEngine)
include_directories(${InferenceEngine_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${InferenceEngine_LIBRARIES} dl)
```
## (Optional) Additional Installation Steps for the Intel® Movidius™ Neural Compute Stick and Neural Compute Stick 2 ## (Optional) Additional Installation Steps for the Intel® Movidius™ Neural Compute Stick and Neural Compute Stick 2
> **NOTE**: These steps are only required if you want to perform inference on Intel® Movidius™ Neural Compute Stick or the Intel® Neural Compute Stick 2 using the Inference Engine MYRIAD Plugin. See also [Intel® Neural Compute Stick 2 Get Started](https://software.intel.com/en-us/neural-compute-stick/get-started) > **NOTE**: These steps are only required if you want to perform inference on Intel® Movidius™ Neural Compute Stick or the Intel® Neural Compute Stick 2 using the Inference Engine MYRIAD Plugin. See also [Intel® Neural Compute Stick 2 Get Started](https://software.intel.com/en-us/neural-compute-stick/get-started)
...@@ -461,7 +477,7 @@ For Intel® Movidius™ Neural Compute Stick and Intel® Neural Compute Stick 2, ...@@ -461,7 +477,7 @@ For Intel® Movidius™ Neural Compute Stick and Intel® Neural Compute Stick 2,
1. Go to the `<DLDT_ROOT_DIR>/inference-engine/thirdparty/movidius/MovidiusDriver` directory, where the `DLDT_ROOT_DIR` is the directory to which the DLDT repository was cloned. 1. Go to the `<DLDT_ROOT_DIR>/inference-engine/thirdparty/movidius/MovidiusDriver` directory, where the `DLDT_ROOT_DIR` is the directory to which the DLDT repository was cloned.
2. Right click on the `Movidius_VSC_Device.inf` file and choose **Install** from the pop up menu. 2. Right click on the `Movidius_VSC_Device.inf` file and choose **Install** from the pop up menu.
You have installed the driver for your Intel® Movidius™ Neural Compute Stick or Intel® Neural Compute Stick 2. You have installed the driver for your Intel® Movidius™ Neural Compute Stick or Intel® Neural Compute Stick 2.
## Next Steps ## Next Steps
......
...@@ -9,6 +9,10 @@ ...@@ -9,6 +9,10 @@
#include <vector> #include <vector>
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief Neural network builder API
*/
namespace Builder { namespace Builder {
/** /**
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief GPU plugin configuration
*/
namespace CLDNNConfigParams { namespace CLDNNConfigParams {
/** /**
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief DLIA plugin metrics
*/
namespace DliaMetrics { namespace DliaMetrics {
/** /**
...@@ -37,6 +40,9 @@ DECLARE_DLIA_METRIC_VALUE(INPUT_STREAMING); ...@@ -37,6 +40,9 @@ DECLARE_DLIA_METRIC_VALUE(INPUT_STREAMING);
} // namespace DliaMetrics } // namespace DliaMetrics
/**
* @brief DLIA plugin configuration
*/
namespace DLIAConfigParams { namespace DLIAConfigParams {
/** /**
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
// //
/** /**
* @brief A header that defines advanced related properties for VPU plugins. * @brief A header that defines advanced related properties for GNA plugin.
* These properties should be used in SetConfig() and LoadNetwork() methods of plugins * These properties should be used in SetConfig() and LoadNetwork() methods of plugins
* *
* @file vpu_plugin_config.hpp * @file gna_config.hpp
*/ */
#pragma once #pragma once
...@@ -16,9 +16,20 @@ ...@@ -16,9 +16,20 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief GNA plugin configuration
*/
namespace GNAConfigParams { namespace GNAConfigParams {
/**
* @def GNA_CONFIG_KEY(name)
* @brief Shortcut for defining configuration keys
*/
#define GNA_CONFIG_KEY(name) InferenceEngine::GNAConfigParams::_CONFIG_KEY(GNA_##name) #define GNA_CONFIG_KEY(name) InferenceEngine::GNAConfigParams::_CONFIG_KEY(GNA_##name)
/**
* @def GNA_CONFIG_VALUE(name)
* @brief Shortcut for defining configuration values
*/
#define GNA_CONFIG_VALUE(name) InferenceEngine::GNAConfigParams::GNA_##name #define GNA_CONFIG_VALUE(name) InferenceEngine::GNAConfigParams::GNA_##name
#define DECLARE_GNA_CONFIG_KEY(name) DECLARE_CONFIG_KEY(GNA_##name) #define DECLARE_GNA_CONFIG_KEY(name) DECLARE_CONFIG_KEY(GNA_##name)
......
...@@ -18,6 +18,9 @@ ...@@ -18,6 +18,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief Heterogeneous plugin configuration
*/
namespace HeteroConfigParams { namespace HeteroConfigParams {
/** /**
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief %Metrics
*/
namespace Metrics { namespace Metrics {
#ifndef DECLARE_METRIC_KEY_IMPL #ifndef DECLARE_METRIC_KEY_IMPL
...@@ -144,6 +147,9 @@ DECLARE_EXEC_NETWORK_METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS, unsigned int); ...@@ -144,6 +147,9 @@ DECLARE_EXEC_NETWORK_METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS, unsigned int);
} // namespace Metrics } // namespace Metrics
/**
* @brief Generic plugin configuration
*/
namespace PluginConfigParams { namespace PluginConfigParams {
/** /**
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
#include <cpp/ie_executable_network.hpp> #include <cpp/ie_executable_network.hpp>
#include <ie_version.hpp> #include <ie_version.hpp>
/**
* @brief Inference Engine API
*/
namespace InferenceEngine { namespace InferenceEngine {
/** /**
* @brief Gets the top n results from a tblob * @brief Gets the top n results from a tblob
......
...@@ -16,6 +16,9 @@ ...@@ -16,6 +16,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief Multi Device plugin configuration
*/
namespace MultiDeviceConfigParams { namespace MultiDeviceConfigParams {
/** /**
......
...@@ -37,6 +37,9 @@ ...@@ -37,6 +37,9 @@
namespace InferenceEngine { namespace InferenceEngine {
/**
* @brief VPU plugin configuration
*/
namespace VPUConfigParams { namespace VPUConfigParams {
// //
......
...@@ -136,7 +136,7 @@ Command line: ...@@ -136,7 +136,7 @@ Command line:
python collect_statistics.py --config ~/inception_v1.yml -d ~/defenitions.yml -M /home/user/intel/openvino/deployment_tools/model_optimizer --models ~/models --source /media/user/calibration/datasets --annotations ~/annotations --converted_models ~/models python collect_statistics.py --config ~/inception_v1.yml -d ~/defenitions.yml -M /home/user/intel/openvino/deployment_tools/model_optimizer --models ~/models --source /media/user/calibration/datasets --annotations ~/annotations --converted_models ~/models
``` ```
Result model has statistics which allow you to infer this model in INT8 precision. To measure performance, you can use the [Benchmark App](./inference-engine/ie_bridges/python/sample/benchmark_app/README.md). Result model has statistics which allow you to infer this model in INT8 precision. To measure performance, you can use the [Benchmark App](./inference-engine/tools/benchmark_tool/README.md).
### Calibrate the Model ### Calibrate the Model
During calibration process, the model is adjusted for efficient quantization and minimization of accuracy drop on calibration dataset. Calibration tool produces calibrated model which will be executed in low precision 8-bit quantized mode after loading into CPU plugin. During calibration process, the model is adjusted for efficient quantization and minimization of accuracy drop on calibration dataset. Calibration tool produces calibrated model which will be executed in low precision 8-bit quantized mode after loading into CPU plugin.
...@@ -180,4 +180,6 @@ To run the Calibration Tool in the simplified mode, use the following command: ...@@ -180,4 +180,6 @@ To run the Calibration Tool in the simplified mode, use the following command:
```sh ```sh
python3 calibrate.py -sm -m <path-to-ir.xml> -s <path-to-dataset> -ss <images-number> -e <path-to-extensions-folder> -td <target-device> -precision <output-ir-precision> --output-dir <output-directory-path> python3 calibrate.py -sm -m <path-to-ir.xml> -s <path-to-dataset> -ss <images-number> -e <path-to-extensions-folder> -td <target-device> -precision <output-ir-precision> --output-dir <output-directory-path>
``` ```
It accepts models with FP32, FP16 precisions and image files as the dataset. Input:
\ No newline at end of file - FP32 and FP16 models
- image files as a dataset
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import logging as log
import numpy as np
from mo.graph.graph import Graph
from mo.utils.model_analysis import AnalyzeAction
class InputsAnalysis(AnalyzeAction):
"""
The analyser gets information about model inputs and their default values if any.
"""
@classmethod
def fifo_queue_analysis(cls, graph: Graph, inputs_desc: dict):
"""
The FIFOQueue with QueueDeque has a separate input that specifies the size of batch to extract from queue. This
input is redundant and should be remove from the model analysis output.
"""
inputs_to_ignore = set()
for fifo_queue in graph.get_op_nodes(op='FIFOQueueV2'):
if len(fifo_queue.get_outputs({'out': 0})) != 1:
log.debug('The FIFOQueue operation "{}" has more than 1 consumers'.format(fifo_queue.id))
continue
queue_deque = fifo_queue.out_node(0)
if queue_deque.op in ['QueueDequeueMany', 'QueueDequeueManyV2', 'QueueDequeueUpTo', 'QueueDequeueUpToV2']:
queue_deque_input_1 = queue_deque.in_node(1)
if queue_deque_input_1.op in ['Parameter', 'PlaceholderWithDefault']:
log.debug('Adding node "{}" to placeholder ignore list'.format(queue_deque_input_1.id))
inputs_to_ignore.add(queue_deque_input_1.id)
# create input per each QueueDeque output port
for port_ind in range(len(queue_deque.out_nodes())):
inputs_desc["{}:{}".format(queue_deque.id, port_ind)] = {'shape': fifo_queue.shapes[port_ind].tolist(),
'value': None,
'data_type': fifo_queue.types[port_ind]}
return inputs_to_ignore
@classmethod
def ignore_mxnet_softmax_inputs(cls, graph: Graph):
"""
MxNet Softmax layers may have additional inputs which should be ignored. Refer to the
extensions/front/mxnet/check_softmax_node_inputs.py.
"""
inputs_to_ignore = set()
softmax_nodes = []
[softmax_nodes.extend(graph.get_op_nodes(op=op)) for op in ('SoftMax', 'SoftmaxActivation', 'SoftmaxOutput')]
for softmax_node in softmax_nodes:
for i in range(1, len(softmax_node.in_nodes())):
if softmax_node.in_node(i).has_valid('op') and softmax_node.in_node(i).op == 'Parameter':
inputs_to_ignore.add(softmax_node.in_node(i).id)
return inputs_to_ignore
def analyze(self, graph: Graph):
inputs_desc = dict()
inputs_to_ignore = InputsAnalysis.fifo_queue_analysis(graph, inputs_desc)
if graph.graph['fw'] == 'mxnet':
inputs_to_ignore.update(InputsAnalysis.ignore_mxnet_softmax_inputs(graph))
inputs = graph.get_op_nodes(op='Parameter')
for input in inputs:
inputs_desc[input.name] = {'shape': input.soft_get('shape', None),
'data_type': input.soft_get('data_type', None),
'value': None,
}
placeholders_with_default = graph.get_op_nodes(op='PlaceholderWithDefault')
for input in placeholders_with_default:
inputs_desc[input.name] = {'shape': input.soft_get('shape', None),
'data_type': input.soft_get('data_type', None),
'value': input.in_node(0).value if 0 in input.in_nodes() and
input.in_node(0).has_valid('value') else None}
for input_to_ignore in inputs_to_ignore:
del inputs_desc[input_to_ignore]
# workaround for the ONNX models case where input shape is specified as string value like: "width", "height".
# In this case the string value is converted to 0, but in fact it is an arbitrary value so should be -1
if graph.graph['fw'] == 'onnx':
for inp in inputs_desc.values():
inp['shape'] = [-1 if item == 0 else item for item in inp['shape']]
return {'inputs': inputs_desc}
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import json
import sys
import numpy as np
from extensions.front.user_data_repack import UserDataRepack
from mo.graph.graph import Graph
from mo.middle.passes.convert_data_type import np_data_type_to_precision
from mo.utils.model_analysis import AnalyzeAction, AnalysisCollectorAnchor
def prepare_obj_for_dump(obj: object):
if isinstance(obj, dict):
return {k: prepare_obj_for_dump(v) for k, v in obj.items()}
elif isinstance(obj, np.ndarray) or isinstance(obj, list):
return [prepare_obj_for_dump(elem) for elem in obj]
elif isinstance(obj, type):
return np_data_type_to_precision(obj)
elif isinstance(obj, np.generic):
return obj.item()
else:
return obj
class AnalysisJSONPrint(AnalyzeAction):
"""
The action prints the analysis results in JSON format.
"""
enabled = False
id = 'ANALYSIS_JSON_PRINT'
def run_before(self):
return [UserDataRepack]
def run_after(self):
return [AnalysisCollectorAnchor]
def analyze(self, graph: Graph):
if 'analysis_results' in graph.graph and graph.graph['analysis_results'] is not None:
print(json.dumps(prepare_obj_for_dump(graph.graph['analysis_results'])))
sys.exit(0)
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from mo.graph.graph import Graph
from mo.utils.model_analysis import AnalyzeAction
class IntermediatesNodesAnalysis(AnalyzeAction):
"""
The analyser gets node names, their shapes and values (if possible) of all nodes in the model.
"""
def analyze(self, graph: Graph):
outputs_desc = dict()
for node in graph.get_op_nodes():
outputs_desc[node.id] = {'shape': node.soft_get('shape', None),
'data_type': None,
'value': None,
}
return {'intermediate': outputs_desc}
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import logging as log
from mo.graph.graph import Graph
from mo.utils.model_analysis import AnalyzeAction, graph_contains_scope
from mo.utils.utils import files_by_pattern, get_mo_root_dir
class TensorFlowObjectDetectionAPIAnalysis(AnalyzeAction):
"""
The analyser checks if the provided model is TF OD API model from
https://github.com/tensorflow/models/tree/master/research/object_detection/g3doc/detection_model_zoo.md of one of 4
supported flavors: SSD, RFCN, Faster RCNN, Mask RCNN.
"""
graph_condition = [lambda graph: graph.graph['fw'] == 'tf']
model_scopes = [('MaskRCNN', ['Preprocessor',
'FirstStageFeatureExtractor',
'SecondStageFeatureExtractor',
'SecondStageBoxPredictor',
'SecondStageBoxPredictor_1',
'SecondStageFeatureExtractor_1',
]),
('RFCN', ['Preprocessor',
'FirstStageFeatureExtractor',
'SecondStageFeatureExtractor',
'SecondStageBoxPredictor',
'SecondStageBoxPredictor/map',
'SecondStageBoxPredictor/map_1',
'SecondStagePostprocessor',
]),
('FasterRCNN', ['Preprocessor',
'FirstStageFeatureExtractor',
'SecondStageFeatureExtractor',
'SecondStageBoxPredictor',
'SecondStagePostprocessor',
]),
('SSD', ['Preprocessor',
'FeatureExtractor',
'Postprocessor',
]),
]
file_patterns = {'MaskRCNN': 'mask_rcnn_support.*\\.json',
'RFCN': 'rfcn_support.*\\.json',
'FasterRCNN': 'faster_rcnn_support.*\\.json',
'SSD': 'ssd.*_support.*\\.json',
}
def analyze(self, graph: Graph):
if any([name not in graph.nodes() for name in ['image_tensor', 'detection_classes', 'detection_boxes',
'detection_scores']]):
log.debug('The model does not contain nodes that must exist in the TF OD API models')
return None
for flavor, scopes in __class__.model_scopes:
if all([graph_contains_scope(graph, scope) for scope in scopes]):
result = dict()
result['flavor'] = flavor
result['mandatory_parameters'] = {'tensorflow_use_custom_operations_config':
files_by_pattern(get_mo_root_dir() + '/extensions/front/tf',
__class__.file_patterns[flavor],
add_prefix=True),
'tensorflow_object_detection_api_pipeline_config': None,
}
return {'model_type': {'TF_OD_API': result}}
return None
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from mo.graph.graph import Graph
from mo.middle.pattern_match import apply_pattern
from mo.utils.model_analysis import AnalyzeAction, graph_contains_scope
YOLO_PATTERN = {
'nodes': [
('pad', dict(op='Pad')),
('conv', dict(op='Conv2D')),
('sub', dict(op='Sub')),
('div', dict(op='Div')),
('mul', dict(op='Mul')),
('bias_add', dict(op='Add')),
('mul_2', dict(op='Mul')),
('max', dict(op='Maximum')),
],
'edges': [
('pad', 'conv', {'out': 0}),
('conv', 'sub', {'out': 0}),
('sub', 'div', {'out': 0}),
('div', 'mul', {'out': 0}),
('mul', 'bias_add', {'out': 0}),
('bias_add', 'mul_2', {'out': 0}),
('bias_add', 'max', {'out': 0}),
('mul_2', 'max', {'out': 0}),
]
}
def pattern_instance_counter(graph: Graph, match: dict):
pattern_instance_counter.counter += 1
pattern_instance_counter.counter = 0
YOLO_CONFIGS = {'YOLOV2Full': ['extensions/front/tf/yolo_v2.json', 'extensions/front/tf/yolo_v2_voc.json'],
'YOLOV3Full': ['extensions/front/tf/yolo_v3.json', 'extensions/front/tf/yolo_v3_voc.json'],
'YOLOV2Tiny': ['extensions/front/tf/yolo_v2_tiny.json', 'extensions/front/tf/yolo_v2_tiny_voc.json'],
'YOLOV3Tiny': ['extensions/front/tf/yolo_v3_tiny.json', 'extensions/front/tf/yolo_v3_tiny_voc.json'],
}
def get_YOLO_params_by_flavor(flavor: str):
result = dict()
result['flavor'] = flavor
result['mandatory_parameters'] = {'tensorflow_use_custom_operations_config': YOLO_CONFIGS[flavor]}
return result
class TensorFlowYOLOV1V2Analysis(AnalyzeAction):
"""
The analyser checks if the provided model is TensorFlow YOLO models from https://github.com/thtrieu/darkflow .
"""
graph_condition = [lambda graph: graph.graph['fw'] == 'tf']
def analyze(self, graph: Graph):
pattern_instance_counter.counter = 0
apply_pattern(graph, **YOLO_PATTERN, action=pattern_instance_counter)
flavor = None
if pattern_instance_counter.counter > 0:
if pattern_instance_counter.counter == 22:
flavor = 'YOLOV2Full'
elif pattern_instance_counter.counter == 8:
flavor = 'YOLOV2Tiny'
if flavor is not None:
return {'model_type': {'YOLO': get_YOLO_params_by_flavor(flavor)}}
else:
return None
class TensorFlowYOLOV3Analysis(AnalyzeAction):
"""
The analyser checks if the provided model is TensorFlow YOLO models from
https://github.com/mystic123/tensorflow-yolo-v3.
"""
graph_condition = [lambda graph: graph.graph['fw'] == 'tf']
def analyze(self, graph: Graph):
flavor = None
if graph_contains_scope(graph, 'detector/yolo-v3') and graph_contains_scope(graph, 'detector/darknet-53'):
flavor = 'YOLOV3Full'
elif graph_contains_scope(graph, 'detector/yolo-v3-tiny'):
flavor = 'YOLOV3Tiny'
if flavor is not None:
return {'model_type': {'YOLO': get_YOLO_params_by_flavor(flavor)}}
else:
return None
...@@ -65,6 +65,7 @@ class FIFOQueue(FrontReplacementSubgraph): ...@@ -65,6 +65,7 @@ class FIFOQueue(FrontReplacementSubgraph):
""" """
true_placeholder_shape = match['placeholder'].shape true_placeholder_shape = match['placeholder'].shape
placeholder_shape = match['fifo_queue'].shapes[0] placeholder_shape = match['fifo_queue'].shapes[0]
placeholder_data_type = match['fifo_queue'].types[0]
assert true_placeholder_shape.ndim <= 1 assert true_placeholder_shape.ndim <= 1
if true_placeholder_shape.ndim == 1 and len(true_placeholder_shape) > 1: if true_placeholder_shape.ndim == 1 and len(true_placeholder_shape) > 1:
log.warning( log.warning(
...@@ -81,7 +82,8 @@ class FIFOQueue(FrontReplacementSubgraph): ...@@ -81,7 +82,8 @@ class FIFOQueue(FrontReplacementSubgraph):
graph.remove_node(out.out_node().id) graph.remove_node(out.out_node().id)
graph.remove_node(out.id) graph.remove_node(out.id)
graph.remove_node(match['batch_join'].id) graph.remove_node(match['batch_join'].id)
placeholder = Parameter(graph, {'name': placeholder_name, 'shape': placeholder_shape}).create_node() placeholder = Parameter(graph, {'name': placeholder_name, 'shape': placeholder_shape,
'data_type': placeholder_data_type}).create_node()
graph.create_edge(placeholder, match['image_batch']) graph.create_edge(placeholder, match['image_batch'])
log.info("FIFOQueueV2 pattern was detected. New shape of placeholder {} is {}. Use -b to set batch size if " log.info("FIFOQueueV2 pattern was detected. New shape of placeholder {} is {}. Use -b to set batch size if "
"needed".format(placeholder.id, placeholder['shape'])) "needed".format(placeholder.id, placeholder['shape']))
......
...@@ -27,7 +27,7 @@ class TestFIFOQueueReplacement(unittest.TestCase): ...@@ -27,7 +27,7 @@ class TestFIFOQueueReplacement(unittest.TestCase):
nodes = { nodes = {
'placeholder': {'op': 'Parameter', 'data_type': np.int32, 'kind': 'op', 'shape': np.array(1)}, 'placeholder': {'op': 'Parameter', 'data_type': np.int32, 'kind': 'op', 'shape': np.array(1)},
'batch_join/fifo_queue': {'op': 'FIFOQueueV2', 'name': 'batch_join/fifo_queue', 'batch_join/fifo_queue': {'op': 'FIFOQueueV2', 'name': 'batch_join/fifo_queue',
'shapes': np.array([[1, 2, 3]]), 'kind': 'op'}, 'shapes': np.array([[1, 2, 3]]), 'types': np.array([np.float32]), 'kind': 'op'},
'batch_join': {'op': 'QueueDequeueUpToV2', 'kind': 'op'}, 'batch_join': {'op': 'QueueDequeueUpToV2', 'kind': 'op'},
'image_batch': {'op': 'Identity', 'data_type': np.float32, 'kind': 'op'}, 'image_batch': {'op': 'Identity', 'data_type': np.float32, 'kind': 'op'},
'label_batch': {'op': 'Identity', 'kind': 'op'}, 'label_batch': {'op': 'Identity', 'kind': 'op'},
...@@ -56,7 +56,7 @@ class TestFIFOQueueReplacement(unittest.TestCase): ...@@ -56,7 +56,7 @@ class TestFIFOQueueReplacement(unittest.TestCase):
nodes_no_label = { nodes_no_label = {
'placeholder': {'op': 'Parameter', 'data_type': np.int32, 'kind': 'op', 'shape': np.array(0)}, 'placeholder': {'op': 'Parameter', 'data_type': np.int32, 'kind': 'op', 'shape': np.array(0)},
'batch_join/fifo_queue': {'op': 'FIFOQueueV2', 'name': 'batch_join/fifo_queue', 'batch_join/fifo_queue': {'op': 'FIFOQueueV2', 'name': 'batch_join/fifo_queue',
'shapes': np.array([[1, 2, 3]]), 'kind': 'op'}, 'shapes': np.array([[1, 2, 3]]), 'types': np.array([np.float32]), 'kind': 'op'},
'batch_join': {'op': 'QueueDequeueUpToV2', 'kind': 'op'}, 'batch_join': {'op': 'QueueDequeueUpToV2', 'kind': 'op'},
'image_batch': {'op': 'Identity', 'data_type': np.float32, 'kind': 'op'}, 'image_batch': {'op': 'Identity', 'data_type': np.float32, 'kind': 'op'},
} }
......
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from mo.front.extractor import FrontExtractorOp
from mo.front.tf.extractors.utils import tf_dtype_extractor, tf_tensor_shape
from mo.ops.op import Op
class PlaceholderWithDefaultExtractor(FrontExtractorOp):
op = 'PlaceholderWithDefault'
enabled = True
@staticmethod
def extract(node):
attrs = {
'data_type': tf_dtype_extractor(node.pb.attr["dtype"].type),
'shape': tf_tensor_shape(node.pb.attr["shape"].shape),
'identity': True,
}
Op.update_node_stat(node, attrs)
return __class__.enabled
...@@ -82,7 +82,6 @@ tf_op_extractors = { ...@@ -82,7 +82,6 @@ tf_op_extractors = {
'SpaceToBatchND': node_pb_arg(tf_space_to_batch_ext), 'SpaceToBatchND': node_pb_arg(tf_space_to_batch_ext),
'BatchToSpaceND': node_pb_arg(tf_batch_to_space_ext), 'BatchToSpaceND': node_pb_arg(tf_batch_to_space_ext),
'ReadVariableOp': node_pb_arg(make_tf_eltwise(lambda v: v, attrs={'identity': True})), 'ReadVariableOp': node_pb_arg(make_tf_eltwise(lambda v: v, attrs={'identity': True})),
'PlaceholderWithDefault': node_pb_arg(make_tf_eltwise(lambda v: v, attrs={'identity': True}))
} }
......
...@@ -175,10 +175,6 @@ def driver(argv: argparse.Namespace): ...@@ -175,10 +175,6 @@ def driver(argv: argparse.Namespace):
if ret_code: if ret_code:
return ret_code return ret_code
if is_mxnet and not argv.input_shape:
raise Error('Input shape is required to convert MXNet model. Please provide it with --input_shape. ' +
refer_to_faq_msg(16))
mean_file_offsets = None mean_file_offsets = None
if is_caffe and argv.mean_file and argv.mean_values: if is_caffe and argv.mean_file and argv.mean_values:
raise Error('Both --mean_file and mean_values are specified. Specify either mean file or mean values. ' + raise Error('Both --mean_file and mean_values are specified. Specify either mean file or mean values. ' +
...@@ -279,7 +275,7 @@ def driver(argv: argparse.Namespace): ...@@ -279,7 +275,7 @@ def driver(argv: argparse.Namespace):
if ret_res != 0: if ret_res != 0:
return ret_res return ret_res
if not (is_tf and argv.tensorflow_custom_operations_config_update): if not (is_tf and argv.tensorflow_custom_operations_config_update) and not argv.silent:
output_dir = argv.output_dir if argv.output_dir != '.' else os.getcwd() output_dir = argv.output_dir if argv.output_dir != '.' else os.getcwd()
print('\n[ SUCCESS ] Generated IR model.') print('\n[ SUCCESS ] Generated IR model.')
print('[ SUCCESS ] XML file: {}.xml'.format(os.path.join(output_dir, model_name))) print('[ SUCCESS ] XML file: {}.xml'.format(os.path.join(output_dir, model_name)))
......
...@@ -30,6 +30,7 @@ SUPPORTED_DATA_TYPES = { ...@@ -30,6 +30,7 @@ SUPPORTED_DATA_TYPES = {
'uint8': (np.uint8, 'UI8'), 'uint8': (np.uint8, 'UI8'),
'int32': (np.int32, 'I32'), 'int32': (np.int32, 'I32'),
'int64': (np.int64, 'I64'), 'int64': (np.int64, 'I64'),
'bool': (np.bool, 'BOOL'),
} }
......
...@@ -24,6 +24,7 @@ from mo.back.replacement import BackReplacementPattern ...@@ -24,6 +24,7 @@ from mo.back.replacement import BackReplacementPattern
from mo.middle.replacement import MiddleReplacementPattern from mo.middle.replacement import MiddleReplacementPattern
from mo.ops.op import Op from mo.ops.op import Op
from mo.utils.class_registration import _check_unique_ids, update_registration, get_enabled_and_disabled_transforms from mo.utils.class_registration import _check_unique_ids, update_registration, get_enabled_and_disabled_transforms
from mo.utils.model_analysis import AnalyzeAction
def import_by_path(path: str, middle_names: list = ()): def import_by_path(path: str, middle_names: list = ()):
...@@ -73,6 +74,7 @@ def load_dir(framework: str, path: str, get_front_classes: callable): ...@@ -73,6 +74,7 @@ def load_dir(framework: str, path: str, get_front_classes: callable):
front_classes = get_front_classes() front_classes = get_front_classes()
internal_dirs = { internal_dirs = {
('ops', ): [Op], ('ops', ): [Op],
('analysis',): [AnalyzeAction],
('front', ): front_classes, ('front', ): front_classes,
('front', framework): front_classes, ('front', framework): front_classes,
('middle', ): [MiddleReplacementPattern], ('middle', ): [MiddleReplacementPattern],
......
"""
Copyright (c) 2019 Intel Corporation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
from extensions.front.user_data_repack import UserDataRepack
from mo.graph.graph import Graph
from mo.utils import class_registration
from mo.utils.error import Error
class AnalyzeAction(object):
registered_cls = []
registered_ops = {}
excluded_replacers = []
run_not_recursively = True
def find_and_replace_pattern(self, graph: Graph):
if 'analysis_results' not in graph.graph:
graph.graph['analysis_results'] = {'failed_analysers': []}
try:
result = self.analyze(graph) # pylint: disable=assignment-from-no-return
except SystemExit:
# the analysis transformation printing analysis results to the screen calls sys.exit(0) which in fact raises
# SystemExit exception, so we handle it here
sys.exit(0)
except:
graph.graph['analysis_results']['failed_analysers'].append(str(self.__class__))
result = None
if result is not None:
graph.graph['analysis_results'].update(result)
def analyze(self, graph: Graph):
raise Error('The method must be implemented in the sub-class')
def run_before(self):
"""
Returns list of replacer classes which this replacer must be run before.
:return: list of classes
"""
return [AnalysisCollectorAnchor, UserDataRepack]
def run_after(self):
"""
Returns list of replacer classes which this replacer must be run after.
:return: list of classes
"""
return []
@classmethod
def class_type(cls):
return class_registration.ClassType.FRONT_REPLACER
class AnalysisCollectorAnchor(AnalyzeAction):
"""
All analyzers should depend on this one which is an anchor analyzer to develop custom post-processor of all
analyzers results.
"""
def run_before(self):
return []
def analyze(self, graph: Graph):
pass
def graph_contains_scope(graph: Graph, scope: str):
"""
Checks whether the graph contains node(s) which name starts with "scope" string.
:param graph: graph to check
:param scope: string defining the scope
:return: the result of the check (True/False)
"""
if scope[-1] != '/':
scope += '/'
return any([node.soft_get('name').startswith(scope) for node in graph.get_op_nodes()])
...@@ -14,8 +14,10 @@ ...@@ -14,8 +14,10 @@
limitations under the License. limitations under the License.
""" """
import functools import functools
import os
import re
import warnings import warnings
import logging as log
import numpy as np import numpy as np
...@@ -77,3 +79,30 @@ def shrink_str_value(value: np.array, max_symbols=100): ...@@ -77,3 +79,30 @@ def shrink_str_value(value: np.array, max_symbols=100):
if len(value) > max_symbols: if len(value) > max_symbols:
value = value.strip('\n')[:max_symbols - 3] + '...' value = value.strip('\n')[:max_symbols - 3] + '...'
return value return value
def files_by_pattern(dir: str, pattern: str, files_only=True, add_prefix=False):
"""
Return a list of files and directories (or only files if the files_only is set to True) in the directory dir that
match pattern string pattern.
:param dir: Directory to search for files
:param pattern: string defining pattern name
:param files_only: flag to include only files (not directories) to the result
:param add_prefix: flag to include the prefix string to the file names
:return: list of file and directory names
"""
pattern_compiled = re.compile(pattern)
matched_file_names = []
for file_name in os.listdir(dir):
if re.match(pattern_compiled, file_name) and (not files_only or os.path.isfile(os.path.join(dir, file_name))):
matched_file_names.append(os.path.join(dir, file_name) if add_prefix else file_name)
return matched_file_names
def get_mo_root_dir():
"""
Return the absolute path to the Model Optimizer root directory (where mo.py file is located)
:return: path to the MO root directory
"""
return os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(os.path.realpath(__file__))), os.pardir,
os.pardir))
tensorflow>=1.2.0,<2.0.0 tensorflow>=1.2.0,<2.0.0
mxnet>=1.0.0,<=1.3.1 mxnet>=1.0.0,<=1.3.1
networkx>=1.11 networkx>=1.11,<2.4
numpy>=1.12.0 numpy>=1.12.0
protobuf==3.6.1 protobuf==3.6.1
onnx>=1.1.2 onnx>=1.1.2
......
networkx>=1.11 networkx>=1.11,<2.4
numpy>=1.12.0 numpy>=1.12.0
protobuf==3.6.1 protobuf==3.6.1
defusedxml>=0.5.0 defusedxml>=0.5.0
networkx>=1.11 networkx>=1.11,<2.4
numpy==1.13.0 numpy==1.13.0
defusedxml>=0.5.0 defusedxml>=0.5.0
mxnet>=1.0.0,<=1.3.1 mxnet>=1.0.0,<=1.3.1
networkx>=1.11 networkx>=1.11,<2.4
numpy>=1.12.0 numpy>=1.12.0
defusedxml>=0.5.0 defusedxml>=0.5.0
onnx>=1.1.2 onnx>=1.1.2
networkx>=1.11 networkx>=1.11,<2.4
numpy>=1.12.0 numpy>=1.12.0
defusedxml>=0.5.0 defusedxml>=0.5.0
tensorflow>=1.2.0,<2.0.0 tensorflow>=1.2.0,<2.0.0
networkx>=1.11 networkx>=1.11,<2.4
numpy>=1.12.0 numpy>=1.12.0
defusedxml>=0.5.0 defusedxml>=0.5.0
...@@ -91,7 +91,7 @@ logging.config.dictConfig(_LOGGING_CONFIGURATION) ...@@ -91,7 +91,7 @@ logging.config.dictConfig(_LOGGING_CONFIGURATION)
default_logger = logging.getLogger(_DEFAULT_LOGGER_NAME) default_logger = logging.getLogger(_DEFAULT_LOGGER_NAME)
def _warning_handler(message, category, filename, lineno): def _warning_handler(message, category, filename, lineno, *args, **kwargs):
s = warnings.formatwarning(message, category, filename, lineno) s = warnings.formatwarning(message, category, filename, lineno)
default_logger.warning(s) default_logger.warning(s)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment