Publishing 2019 R1 content
[platform/upstream/dldt.git] / model-optimizer / mo / front / common / partial_infer / caffe_fallback.py
1 """
2  Copyright (c) 2018-2019 Intel Corporation
3
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7
8       http://www.apache.org/licenses/LICENSE-2.0
9
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 """
16
17 import logging as log
18 import os
19
20 import networkx as nx
21 import numpy as np
22
23 from mo.graph.graph import Node, Graph
24 from mo.utils.error import Error
25 from mo.utils.find_inputs import find_inputs
26 from mo.utils.utils import refer_to_faq_msg
27
28
29 def get_node_top(graph: Graph, name: str):
30     node = Node(graph, name)
31     return node.out_edge()['name'] if node else None
32
33
34 def build_net(graph: Graph):
35     try:
36         if not hasattr(os.environ, 'GLOG_minloglevel'):
37             os.environ['GLOG_minloglevel'] = '2'
38         import caffe
39         log.info('Partial inference via the framework is available')
40     except ImportError:
41         log.warning('pyCaffe is not available. Partial inference via the framework is not ' +
42                     'possible')
43         return
44
45     try:
46         net = caffe.Net(graph.proto_path, graph.caffemodel_path, caffe.TEST)
47     except Exception as err:
48         raise Error(
49             'Error happened while constructing caffe.Net in the Caffe fallback function: {}. ' +
50             refer_to_faq_msg(12),
51             str(err)
52         ) from err
53
54     inputs_node_name = find_inputs(graph)
55
56     reshape_flag = False
57     for i in inputs_node_name:
58         new_input_shape = graph.node[i]['shape'].astype(int)
59         top_node = get_node_top(graph, i)
60         caffe_shape = list(net.blobs[top_node].shape)
61         if not np.all(caffe_shape == new_input_shape):
62             net.blobs[top_node].reshape(*[int(x) for x in new_input_shape])
63             reshape_flag = True
64
65     if reshape_flag:
66         net.reshape()
67
68     try:
69         net.forward()
70     except KeyError as err:
71         log.error('Error happened in Caffe net.forward: {}.'.format(str(err)))
72         log.error('It may point to the known bug in pycaffe when top and name of the layer do not match.')
73         log.error('Please make sure that the latest pycaffe is used.')
74         raise Error('Cannot infer shapes due to exception in Caffe: {}. ' +
75                     refer_to_faq_msg(13), str(err)) from err
76     except Exception as err:
77         raise Error('Cannot infer shapes in Caffe net.forward due to exception: {}.' +
78                     refer_to_faq_msg(13), str(err)) from err
79
80     graph.__setattr__('caffe_net', net)
81
82
83 def get_net(graph: Graph):
84     if not graph:
85         return None
86
87     if graph and not hasattr(graph, 'caffe_net'):
88         build_net(graph)
89     return getattr(graph, 'caffe_net', None)
90
91
92 def caffe_native_node_infer(node: Node):
93     """
94     Infers shape of the unknown operation via Caffe if it is available.
95     Requires graph to contain paths to both prototxt and caffemodel files.
96     When it is visited for the first time, net object is created and written to graph.
97     Next time, it just takes the built net from graph.
98
99     Parameters
100     ----------
101     node node to infer the shape for
102
103     """
104     log.error("Caffe fallback is deprecated. It will be removed in future releases. Please use extensions for unsupported layers.\n" +
105               "See more information in the \"Custom Layers in the Model Optimizer\" chapter of the Model Optimizer Developer Guide",
106               extra={'is_warning': True})
107     log.info('Called "caffe_native_node_infer" for node "{}"'.format(node.id))
108
109     graph = node.graph
110     net = get_net(graph)
111     if not net:
112         raise Error(
113             'Cannot infer shape for node "{}" because there is no Caffe available. ' +
114             'Please register python infer function for op = {} or use Caffe for shape inference. ' +
115             refer_to_faq_msg(14),
116             node.soft_get('name'),
117             node.soft_get('op')
118         )
119
120     for iout in range(len(node.out_nodes())):
121         output_shape = np.array(net.blobs[node.top].data.shape, dtype=np.int64)
122         node.out_node(iout).shape = output_shape