コード例 #1
0
    def extract(cls, node):
        pb = node.parameters
        try:
            collect_until_token(pb, b'<InputDim>')
        except Error:
            raise Error("<InputDim> was not found")
        in_dim = read_binary_integer32_token(pb)

        try:
            collect_until_token(pb, b'<OutputDim>')
        except Error:
            raise Error("<OutputDim> was not found")
        out_dim = read_binary_integer32_token(pb)

        assert in_dim % out_dim == 0

        group = in_dim / out_dim

        try:
            collect_until_token(pb, b'<P>')
        except Error:
            raise Error("<P> was not found")
        p = read_binary_float_token(pb)

        attrs = {
            'group': group,
            'p': p,
        }

        PNormOp.update_node_stat(node, attrs)
        return cls.enabled
コード例 #2
0
def guess_source_layouts_by_mean_scale(ov_function: Model, layout_values,
                                       mean_scale_values: dict):
    """
    Internal function. Try to guess source layout for input by its shape and/or framework
    :param: ov_function Original model
    :param: layout_values Existing source/target layout items specified by user
    :param: mean_scale_values Dictionary with mean/scale values defined for each argument
    :return: updated layout items with guessed layouts
    """
    for ms_name, mean_scale in mean_scale_values.items():
        num_channels_mean = len(
            mean_scale['mean']) if mean_scale['mean'] is not None else 0
        num_channels_scale = len(mean_scale['scale']) if hasattr(
            mean_scale['scale'], '__len__') else 0

        if num_channels_mean > 1 and \
                num_channels_scale > 1 and \
                num_channels_mean is not num_channels_scale:
            raise Error(
                'Mean/Scale values for {} have different sizes: {} {}'.format(
                    ms_name, num_channels_mean, num_channels_scale))

        need_guess_channels = num_channels_mean > 1 or num_channels_scale > 1
        if not need_guess_channels:  # Mean/scale is complex and needs 'channels' specified in layout
            continue

        num_channels = num_channels_mean if num_channels_mean > 1 else num_channels_scale

        for i in range(0, len(ov_function.inputs)):
            ov_input = ov_function.input(i)

            if not ov_function.get_parameters()[i].layout.empty:
                continue

            if ms_name not in ov_input.get_tensor().get_names():
                continue

            layout_item = None
            for name in ov_input.get_tensor().get_names():
                if name in layout_values:
                    layout_item = layout_values[name]
                    break

            if layout_item is not None:
                # User specified some layout, skip guessing
                continue

            # Guess layout is applicable only when number of channels is '3'
            if num_channels != 3:
                raise Error('Can\'t determine channels dimension for {}. '
                            'When number of mean/scale values is {} (not 3), '
                            'please specify layout for input manually'.format(
                                ms_name, num_channels))

            layout_values = find_channels_dimension(
                shape=ov_input.get_partial_shape(),
                num_channels=num_channels,
                name=ms_name,
                layout_values=layout_values)
    return layout_values
コード例 #3
0
def check_keys_valid(ov_function: Model, keys: list, search_outputs: bool):
    """
    Internal function: checks if keys from cmd line arguments correspond to ov_function's inputs/outputs
    Throws if some key is not found
    Throws if some different keys point to the same actual input/output
    """
    nodes_used = {}
    nodes = ov_function.inputs
    if search_outputs:
        nodes += ov_function.outputs

    for name in keys:
        node_found = False
        for ov_node in nodes:
            if name in ov_node.get_tensor().get_names():
                if ov_node in nodes_used:
                    raise Error(
                        'Key for {} and {} point to same model input/output.'.
                        format(name, nodes_used[ov_node]))
                nodes_used[ov_node] = name
                node_found = True
                break

        if not node_found:
            if not search_outputs:
                raise Error('Input with name {} wasn\'t found! {}'.format(
                    name, refer_to_faq_msg(83)))
            else:
                raise Error(
                    'Input/Output with name {} wasn\'t found! {}'.format(
                        name, refer_to_faq_msg(83)))
コード例 #4
0
def parse_custom_replacement_config_file(file_name: str):
    """
    Reads custom replacement configuration file file_name.
    :param file_name: name of the file to read from.
    :return: The dictionary where key is the layer id and value is an instance of the CustomLayerDescriptor object.
    """
    if not os.path.exists(file_name):
        raise Error("Custom replacements configuration file '{}' does not exist. ".format(file_name) +
                    refer_to_faq_msg(69))

    data = load_and_validate_json_config(file_name)
    result = list()
    validation_errors = list()
    for attrs in data:
        if 'id' not in attrs:
            raise Error('One of the custom replacements in the configuration file "{}" does not contain attribute '
                        '"id". '.format(file_name) +
                        refer_to_faq_msg(71))
        if 'match_kind' not in attrs:
            raise Error('One of the custom replacements in the configuration file "{}" does not contain attribute '
                        '"match_kind". Possible values are "points", "scope" and "general". '.format(file_name) +
                        refer_to_faq_msg(71))
        desc = CustomReplacementDescriptor.create_instance(attrs['match_kind'], attrs['id'], attrs)
        validation_errors.extend(desc.validate_data())
        result.append(desc)
    if len(validation_errors) > 0:
        raise Error("File '{}' validation failed:\n{}. ".format(file_name, "\n".join(validation_errors)) +
                    refer_to_faq_msg(72))
    return result
コード例 #5
0
    def _update_param_using_rule(self, params: dict, rule: [str, tuple]):
        if isinstance(rule, str):
            if rule in params:
                self._model_params[rule] = params[rule]
                log.debug('Found value "{}" for path "{}"'.format(
                    params[rule], rule))
        elif isinstance(rule, tuple):
            if len(rule) != 2 and len(rule) != 3:
                raise Error(
                    'Invalid rule length. Rule must be a tuple with two elements: key and path, or three '
                    'elements: key, path, default_value.')
            value = __class__._get_value_by_path(params, rule[1].split('/'))
            if value is not None:
                log.debug('Found value "{}" for path "{}"'.format(
                    value, rule[1]))
                self._model_params[rule[0]] = value
            elif len(rule) == 3:
                self._model_params[rule[0]] = rule[2]
                log.debug(
                    'There is no value path "{}". Set default value "{}"'.
                    format(value, rule[2]))

        else:
            raise Error(
                'Invalid rule type. Rule can be either string or tuple')
コード例 #6
0
ファイル: graph.py プロジェクト: yury-intel/openvino
def extract_port_from_string(node_name: str):
    """
    Extracts port and node name from string

    Raises if node name was not provided in the expected format:
    NODE:OUT_PORT
        or
    IN_PORT:NODE

    :param node_name: string value provided by user
    :return: node name, input port and output port
    """
    parts = node_name.split(':')
    if len(parts) > 2:
        raise Error(
            "Please provide only one port number for {}. Expected format is NODE:OUT_PORT or IN_PORT:NODE, "
            "where IN_PORT and OUTPUT_PORT are integers".format(node_name))
    if len(parts) == 1:
        return node_name, None, None
    else:
        in_port, out_port, name = None, None, None
        try:
            in_port, name = int(parts[0]), parts[1]
        except ValueError:
            try:
                out_port, name = int(parts[1]), parts[0]
            except ValueError:
                raise Error(
                    "Non integer port number in {}. Expected format is NODE:OUT_PORT or IN_PORT:NODE, where "
                    "IN_PORT and OUTPUT_PORT are integers".format(node_name))
        return name, in_port, out_port
コード例 #7
0
ファイル: loader.py プロジェクト: mateusztabaka/openvino
def load_symbol_def(input_model_name,
                    input_symbol,
                    input_names: str = '',
                    nd_prefix_name: str = '',
                    pretrained_model_name: str = '',
                    legacy_mxnet_model: bool = False):
    if not nd_prefix_name and not pretrained_model_name:
        # model name always has extension 'param'
        try:
            model_name, iteration_number = parse_input_model(input_model_name)
        except ValueError as err:
            raise Error(
                'Input model name {} is not in an expected format, cannot extract iteration number. '
                + refer_to_faq_msg(48), input_model_name)

        if input_names:
            model_params = load_params(input_model_name,
                                       data_names=input_names.split(','))
        else:
            model_params = load_params(input_model_name)

    elif nd_prefix_name and pretrained_model_name and input_symbol:
        model_name, iteration_number = parse_input_model(pretrained_model_name)
        model_name = '-'.join(input_symbol.split('-')[:-1])
        model_params = build_params_file(nd_prefix_name, pretrained_model_name,
                                         input_names)
    else:
        raise Error(
            "Arguments --nd_prefix_name, --pretrained_model_name and --input_symbol should be provided. Please provide all or do not use any. "
            + refer_to_faq_msg(81))

    model_nodes = load_symbol_nodes(model_name, input_symbol,
                                    legacy_mxnet_model)

    return model_nodes, model_params, model_name, iteration_number
コード例 #8
0
    def infer(node: Node):
        in_shape = node.in_node().shape
        if in_shape.size != 4:
            raise Error('TensorFlow SpaceToDepth operation is supported for 4D \'NHWC\' input layout only. '
                        'Current input shape is \'{}\''.format(in_shape))

        layout = node.graph.graph['layout']
        N = in_shape[get_batch_dim(layout, 4)]
        H = in_shape[get_height_dim(layout, 4)]
        W = in_shape[get_width_dim(layout, 4)]
        C = in_shape[get_features_dim(layout, 4)]

        block_size = node['block_size']
        if (H is not dynamic_dimension and H % block_size) or (W is not dynamic_dimension and W % block_size):
            raise Error('Spatial dimensions of input tensor of SpaceToDepth operation have to be divisible by '
                        'SpaceToDepth \'block_size\' parameter. Input tensor shape = {}. Spatial dimensions = {},{}. '
                        'block_size = {}'.format(in_shape, H, W, block_size))

        out_shape = shape_for_layout(layout,
                                     batch=N,
                                     features=C * (block_size ** 2),
                                     height=H // block_size,
                                     width=W // block_size)

        node.out_port(0).data.set_shape(out_shape)
コード例 #9
0
ファイル: connection.py プロジェクト: XinWangIntel/openvino
    def add_destination(self, port):
        # In this method we are adding destination port with type 'in' for a connection.
        # See detailed example below.
        #
        # SOURCE - Op1(out_port:0)
        #
        # DESTINATIONS - Op2(in_port:0)
        #
        # NEW PORT - Op3(in_port:0)
        #
        # CONNECTION
        #               Op1(out_port:0)--->Op2(in_port:0)
        #
        # When we set destination for connection we disconnect destination port if exists and connect source to
        # the new given port with type='in'.
        #
        # UPDATED CONNECTION
        #                                 ,-->Op3(in_port:0)
        #               Op1(out_port:0)--->Op2(in_port:0)
        #

        if self.control_flow is True:
            raise Error("Cannot operate with connection with control_flow=True")

        if self.source is None:
            raise Error("Can not add destination for connection without source port!")

        if self.graph.stage == 'front':
            node = self.source.node
            self.graph.create_edge(node, port.node, out_port=self.source.idx, in_port=port.idx)
        else:
            data_node = self.source._create_data_if_necessary()
            self.graph.add_edge(data_node.id, port.node.id, **{'in': port.idx})

        self.destinations.append(port)
コード例 #10
0
 def replace_pattern(graph: Graph, match: dict):
     nodes = [
         ('input_unsqueezed'),
         ('squeeze', dict(op='Reshape')),
         ('input_squeezed'),
         ('input_hidden'),
         ('input_cell'),
         ('weights'),
         ('biases'),
         ('lstm', dict(op='LSTMCell')),
         ('output_hidden'),
         ('output_cell'),
         ('unsqueeze', dict(op='Reshape')),
         ('output_unsqueezed'),
     ]
     edges = [
         ('input_unsqueezed', 'squeeze'),
         ('squeeze', 'input_squeezed'),
         ('input_squeezed', 'lstm', {
             'in': 0
         }),
         ('input_hidden', 'lstm', {
             'in': 1
         }),
         ('input_cell', 'lstm', {
             'in': 2
         }),
         ('weights', 'lstm', {
             'in': 3
         }),
         ('biases', 'lstm', {
             'in': 4
         }),
         ('lstm', 'output_hidden', {
             'out': 0
         }),
         ('lstm', 'output_cell', {
             'out': 1
         }),
         ('output_hidden', 'unsqueeze'),
         ('unsqueeze', 'output_unsqueezed'),
     ]
     ti = match['ti']
     isomorphisms = find_isomorphisms(ti.body, nodes, edges)
     if len(list(isomorphisms)) != 1:
         raise Error(
             'Unsupported TensorIterator layer {} was found: either its body, ports or '
             'edges are not supported by Inference Engine. '
             'Only TensorIterator with LSTMCell in a body of strict form is supported. '
             'Please modify the original network '
             'to meet the requirements.'.format(ti.soft_get('name')))
     body_match = isomorphisms[0]
     if body_match['input_hidden'].has_valid(
             'value') or body_match['input_cell'].has_valid('value'):
         raise Error(
             'Unsupported TensorIterator layer {} was found: initial hidden and/or cell states '
             'for LSTMCell are constants. This is not supported. '
             'Only TensorIterator with LSTMCell in a body of strict form is supported. '
             'Please modify the original network '
             'to meet the requirements.'.format(ti.soft_get('name')))
コード例 #11
0
ファイル: loader.py プロジェクト: liubo-intel/openvino
def deducing_metagraph_path(meta_graph_file: str):
    match = re.search(r'^(.*)\.(data-\d*-of-\d*|index|meta)$', meta_graph_file)
    if match is not None:
        deduced_meta_graph_file = match.group(1) + '.meta'
        if not os.path.isfile(deduced_meta_graph_file):
            raise Error(
                '\n\nMetaGraph freezing mechanism was enabled. '
                '\n{} file does not represent MetaGraph. '
                '\n{} path to MetaGraph was deduced, but it does not exist'
                '\n\nModel with MetaGraph consists of 3-4 files:'
                '\n1. model_name.meta'
                '\n2. model_name.index'
                '\n3. model_name.data-00000-of-00001 (digit part may vary)'
                '\n4. checkpoint (optional)'.format(meta_graph_file,
                                                    deduced_meta_graph_file))
        else:
            meta_graph_file = deduced_meta_graph_file
    else:
        raise Error('\n\nMetaGraph freezing mechanism was enabled. '
                    '\n{} file does not represent MetaGraph. '
                    '\n\nModel with MetaGraph consists of 3-4 files:'
                    '\n1. model_name.meta'
                    '\n2. model_name.index'
                    '\n3. model_name.data-00000-of-00001 (digit part may vary)'
                    '\n4. checkpoint (optional)'
                    '\n\nTo load this model, simply run:'
                    '\npython3 mo_tf.py --input_meta_graph model_name.meta'
                    ''.format(meta_graph_file))
    return meta_graph_file
コード例 #12
0
ファイル: depth_to_space.py プロジェクト: yury-intel/openvino
    def infer(node: Node):
        in_shape = node.in_port(0).data.get_shape()
        if in_shape.size != 4:
            raise Error('TensorFlow DepthToSpace operation is supported for 4D \'NHWC\' input layout only. '
                        'Current input shape is \'{}\''.format(in_shape))

        layout = node.graph.graph['layout']

        N = in_shape[get_batch_dim(layout, 4)]
        H = in_shape[get_height_dim(layout, 4)]
        W = in_shape[get_width_dim(layout, 4)]
        C = in_shape[get_features_dim(layout, 4)]

        block_size = node['block_size']
        if C is not dynamic_dimension and C % (block_size ** 2):
            raise Error('Feature dimensions of input tensor of DepthToSpace operation have to be divisible by square '
                        'of DepthToSpace \'block_size\' parameter. Input tensor shape = {}. Feature dimension = {}. '
                        'block_size = {}'.format(in_shape, C, block_size))

        out_shape = shape_for_layout(layout,
                                     batch=N,
                                     features=C // (block_size * block_size),
                                     height=H * block_size,
                                     width=W * block_size)

        if is_fully_defined(in_shape) and is_fully_defined(out_shape) and np.prod(in_shape) != np.prod(out_shape):
            raise Error('Number of input elements "{}" is not equal to number of output elements "" for node "{}"'
                        ''.format(in_shape, out_shape, node.soft_get('name', node.id)))
        node.out_port(0).data.set_shape(out_shape)
コード例 #13
0
ファイル: crop.py プロジェクト: yury-intel/openvino
    def _one_input_infer(node: Node):
        input_shape = node.in_port(0).data.get_shape()
        node_name = node.soft_get('name', node.id)
        if input_shape is None:
            raise Error('input_shape is none for {} node'.format(node_name))

        if not node.has_valid('axis'):
            raise Error('axis attribute is missing for {} node. should be set in crop extractor'.format(node_name))

        output_shape = input_shape.copy()
        if node.has_valid('dim'):
            if len(node.dim) != len(node.axis):
                raise Error('Number of axis "{}" should match number of dim "{}" for node "{}"'
                            ''.format(node.axis, node.dim, node_name))
            output_shape[node.axis] = node.dim
        elif node.has_valid('crop_begin') and node.has_valid('crop_end'):
            if len(node.crop_begin) != len(node.axis) or len(node.crop_end) != len(node.axis):
                raise Error('number of crop_begin({})/crop_end({}) should match number of axis "{}" for node "{}"'
                            ''.format(node.crop_begin, node.crop_end, node.axis, node_name))
            if type(node.axis) in [list, tuple]:
                for i in range(len(node.axis)):
                    output_shape[node.axis[i]] = output_shape[node.axis[i]] - node.crop_begin[i] - node.crop_end[i]
            else:
                output_shape[node.axis] = output_shape[node.axis] - node.crop_begin - node.crop_end
        else:
            raise Error('Crop node {} should have either dim or crop_begin and crop_end attributes'.format(node_name))

        node.out_port(0).data.set_shape(output_shape)
        PermuteAttrs.create_permute_attrs(node, attrs=[('axis', 'input:0')])
コード例 #14
0
ファイル: layout.py プロジェクト: yury-intel/openvino
def shape_for_layout(layout: str, **kwargs):
    """
    Creates 4D or 5D tensor with the layout with specified dimension sizes.
    :param layout: layout string.
    :param kwargs: dictionary that contains the dimension sizes using the following keys: 'batch', 'features', 'depth',
    'height', 'width'.
    :return: shape_array of type np.int64 with 4 or 5 elements.
    """
    assert layout in supported_layouts
    for required_key in ('batch', 'features', 'height', 'width'):
        if required_key not in kwargs:
            raise Error(
                'Required parameter "{}" is missing.'.format(required_key))
    for key in kwargs.keys():
        if key not in ('batch', 'features', 'height', 'width', 'depth'):
            raise Error('Parameter "{}" is not supported.'.format(key))

    depth = kwargs.get('depth', None)
    shape_len = 4 + (depth is not None)
    output_shape = np.ma.ones(shape=[shape_len],
                              dtype=np.int64,
                              fill_value=dynamic_dimension_value)
    output_shape[get_batch_dim(layout, shape_len)] = kwargs['batch']
    output_shape[get_height_dim(layout, shape_len)] = kwargs['height']
    output_shape[get_width_dim(layout, shape_len)] = kwargs['width']
    output_shape[get_features_dim(layout, shape_len)] = kwargs['features']
    if depth is not None:
        output_shape[get_depth_dim(layout, shape_len)] = depth
    return output_shape
コード例 #15
0
ファイル: unsqueeze.py プロジェクト: mikhailk62/openvino
    def infer(node):
        if len(node.in_nodes()) <= 1:
            raise Error('There is no input with unsqueeze dims for the node {}'.format(node.soft_get('name')))
        unsqueeze_dims = node.in_port(1).data.get_value()
        if unsqueeze_dims is None:
            raise Error('The dimensions to unsqueeze are not defined for the node {}'.format(node.soft_get('name')))
        unsqueeze_dims = int64_array(unsqueeze_dims)

        input_value = node.in_port(0).data.get_value()
        input_shape = node.in_port(0).data.get_shape()

        # TODO remove the following line when the Inference Engine plugins support 0D tensors
        if unsqueeze_dims.ndim == 0:
            unsqueeze_dims = int64_array([unsqueeze_dims.item()])

        # make dimensions positive to correctly translate from NHWC to NCHW layout
        unsqueeze_dims = int64_array([dim + len(node.in_port(0).data.get_shape()) + 1 if dim < 0 else dim
                                      for dim in unsqueeze_dims])
        if node.in_port(1).get_source().node.op == 'Const':
            node.in_port(1).data.set_value(unsqueeze_dims)

        output_shape = input_shape.copy()
        for dim in unsqueeze_dims:
            output_shape = shape_insert(output_shape, dim, 1)

        if input_value is not None and is_fully_defined(output_shape):
            node.out_port(0).data.set_value(input_value.reshape(output_shape))
        else:
            node.out_port(0).data.set_shape(output_shape)

        PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0', 'axis')
コード例 #16
0
    def extract(cls, node):
        pb = node.parameters
        mapping_rule = {
            'context': list()
        }
        tag = find_next_tag(pb)
        if tag == '<LeftContext>':
            read_placeholder(pb, 1)
            l_context = read_binary_integer32_token(pb)
            tag = find_next_tag(pb)
            if tag != '<RightContext>':
                raise Error('Unknown token {} in SpliceComponent node {}'.format(tag, node.id))
            read_placeholder(pb, 1)
            r_context = read_binary_integer32_token(pb)
            for i in range(-l_context, r_context + 1):
                mapping_rule['context'].append(i)
        elif tag == '<Context>':
            collect_until_whitespace(pb)
            mapping_rule['context'] = read_binary_vector(pb, False, dtype=np.int32)
        else:
            raise Error('Unknown token {} in SpliceComponent node {}'.format(tag, node.id))

        tag = find_next_tag(pb)
        if tag == '<ConstComponentDim>':
            read_placeholder(pb, 1)
            const_dim = read_binary_integer32_token(pb)
            mapping_rule['const_dim'] = const_dim

        Splice.update_node_stat(node, mapping_rule)
        return cls.enabled
コード例 #17
0
    def infer(node: Node):
        node_name = node.soft_get('name', node.id)

        input_shape = node.in_port(0).data.get_shape()
        input_value = node.in_port(0).data.get_value()
        target_shape = node.in_port(1).data.get_value()
        assert target_shape is not None, 'Output shape is not defined for node "{}"'.format(
            node_name)
        assert node.has_and_set(
            'mode'), 'Broadcasting mode is not defined for node "{}"'.format(
                node_name)

        PermuteInputs().set_input_permutation(node.in_node(1), node,
                                              'output:0', 'shape')

        if input_value is not None and not node.has_and_set('stop_value_propagation') and \
                is_fully_defined(target_shape):
            if node.mode == 'numpy':
                node.out_port(0).data.set_value(
                    uni_directional_broadcasting(input_value, target_shape))
            elif node.mode == 'bidirectional':
                node.out_port(0).data.set_value(
                    bi_directional_broadcasting(input_value, target_shape))
            elif node.mode == 'explicit':
                axes_mapping = node.in_port(2).data.get_value()
                assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \
                                                 'is not supported. Node: `{}`'.format(node_name)
                PermuteInputs().set_input_permutation(node.in_node(2), node,
                                                      'output:0', 'axis')
                axes_mapping = node.in_port(2).data.get_value()
                node.out_port(0).data.set_value(
                    explicit_broadcasting(input_value, target_shape,
                                          axes_mapping))
            else:
                raise Error('The node "{}" has unsupported mode "{}"'.format(
                    node_name, node.mode))
        else:
            if node.mode == 'numpy':
                node.out_port(0).data.set_shape(
                    uni_directional_shape_broadcasting(input_shape,
                                                       target_shape))
            elif node.mode == 'bidirectional':
                node.out_port(0).data.set_shape(
                    bi_directional_shape_broadcasting(input_shape,
                                                      target_shape))
            elif node.mode == 'explicit':
                axes_mapping = node.in_port(2).data.get_value()
                assert axes_mapping is not None, 'Broadcast(mode="explicit") with dynamic axes_mapping input ' \
                                                 'is not supported. Node: `{}`'.format(node_name)
                PermuteInputs().set_input_permutation(node.in_node(2), node,
                                                      'output:0', 'axis')
                axes_mapping = node.in_port(2).data.get_value()
                new_shape, _ = explicit_shape_broadcasting(
                    input_shape, target_shape, axes_mapping)
                node.out_port(0).data.set_shape(new_shape)
            else:
                raise Error('The node "{}" has unsupported mode "{}"'.format(
                    node_name, node.mode))
コード例 #18
0
 def extract(cls, node):
     # some Dropout flavors doesn't have is_test attribute; when it is missing, interpret it as 1
     is_test = onnx_attr(node, 'is_test', 'i', 1)
     if len(node.out_nodes()) > 1:
         raise Error('Dropout node {} has more than one consumer. Unsupported.', node.name)
     if not is_test:
         raise Error('Dropout node {} has is_test: 0. This means training mode which is not supported.', node.name)
     Identity.update_node_stat(node)
     return cls.enabled
コード例 #19
0
ファイル: preprocessing.py プロジェクト: terfendail/openvino
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
    Throws if some key is not found
    Throws if some different keys point to the same actual input/output
    """
    nodes_used = {}
    nodes = ov_function.inputs
    if search_outputs:
        nodes += ov_function.outputs

    # We need to replace all node names from dict to tensor names
    rename_dict = {}
    # Find names for replacing
    for name in dict_to_validate.keys():
        for ov_node in nodes:
            if name in ov_node.get_tensor().get_names():
                break
            elif name == ov_node.get_node().get_friendly_name():
                assert len(ov_node.get_tensor().get_names()
                           ) > 0, 'Node must have at least one tensor name'
                new_name = list(ov_node.get_tensor().get_names())[0]
                rename_dict[name] = new_name
                break

    # Replace found node names with tensor names
    for name, new_name in rename_dict.items():
        assert name in dict_to_validate, 'Key {} is not in initial dict'.format(
            name)
        assert new_name not in dict_to_validate, 'Key {} is already in initial dict'.format(
            new_name)
        dict_to_validate[new_name] = dict_to_validate[name]
        del dict_to_validate[name]

    # validate the dict
    for name in dict_to_validate.keys():
        node_found = False
        for ov_node in nodes:
            if name in ov_node.get_tensor().get_names():
                if ov_node in nodes_used:
                    raise Error(
                        'Key for {} and {} point to same model input/output.'.
                        format(name, nodes_used[ov_node]))
                nodes_used[ov_node] = name
                node_found = True
                break

        if not node_found:
            if not search_outputs:
                raise Error('Input with name {} wasn\'t found! {}'.format(
                    name, refer_to_faq_msg(83)))
            else:
                raise Error(
                    'Input/Output with name {} wasn\'t found! {}'.format(
                        name, refer_to_faq_msg(83)))
コード例 #20
0
def apply_biases_to_last_layer(graph, counts):
    r"""
    When user provides counts file, it is a file that contains log-apriory probabilities,
    technically it should be subtracted from the bias of the last layer unless it is a SoftMax.

    Case 1:
        weights ---\
        biases  ---\
    some layer  ---> AffineTransform ---> SoftMax

    Then, counts are applied to biases of Affine Transform:

        weights             ---\
        (biases - counts)   ---\
    some layer              ---> AffineTransform ---> SoftMax

    Case 2:
        weights ---\
        biases  ---\
    some layer  ---> AffineTransform

    Just takes the last layer and updates biases:

        weights             ---\
        (biases - counts)   ---\
    some layer              ---> AffineTransform

    Parameters
    ----------
    graph
    counts

    Returns
    -------

    """ ""
    outputs_ids = find_outputs(graph)
    for output in outputs_ids.copy():
        node = Node(graph, output)
        if node.op != 'Assign' and node.op != "MemoryOffset":
            continue
        outputs_ids.remove(output)

    if len(outputs_ids) > 1:
        raise Error('Ambiguity in applying counts to several outputs.')
    elif len(outputs_ids) == 0:
        raise Error('No outputs were found')

    target_node = Node(graph, outputs_ids[0])
    if target_node.op == 'SoftMax':
        target_node = target_node.in_port(0).get_source().node

    sub_node = create_op_node_with_second_input(graph, Add, -counts,
                                                {'name': 'sub_counts'})
    target_node.out_port(0).get_connection().set_source(sub_node.out_port(0))
    sub_node.in_port(0).connect(target_node.out_port(0))
コード例 #21
0
    def extract(cls, node: Node) -> bool:
        """
        Extract conv parameters from node.parameters.
        node.parameters like file descriptor object.
        :param node: Convolution node
        :return:
        """
        pb = node.parameters
        kernel = read_token_value(pb, b'<PatchDim>')
        stride = read_token_value(pb, b'<PatchStep>')
        patch_stride = read_token_value(pb, b'<PatchStride>')

        read_learning_info(pb)

        collect_until_whitespace(pb)
        weights, weights_shape = read_binary_matrix(pb)

        collect_until_whitespace(pb)
        biases = read_binary_vector(pb)

        if (patch_stride - kernel) % stride != 0:
            raise Error(
                'Kernel size and stride does not correspond to `patch_stride` attribute of Convolution layer. ' +
                refer_to_faq_msg(93))

        output = biases.shape[0]
        if weights_shape[0] != output:
            raise Error('Weights shape does not correspond to the `output` attribute of Convolution layer. ' +
                        refer_to_faq_msg(93))

        mapping_rule = {
            'output': output,
            'patch_stride': patch_stride,
            'bias_term': None,
            'pad': np.array([[0, 0], [0, 0], [0, 0], [0, 0]], dtype=np.int64),
            'pad_spatial_shape': np.array([[0, 0], [0, 0]], dtype=np.int64),
            'dilation': np.array([1, 1, 1, 1], dtype=np.int64),
            'kernel': np.array([1, 1, 1, kernel], dtype=np.int64),
            'stride': np.array([1, 1, 1, stride], dtype=np.int64),
            'kernel_spatial': np.array([1, kernel], dtype=np.int64),
            'input_feature_channel': 1,
            'output_feature_channel': 0,
            'kernel_spatial_idx': [2, 3],
            'group': 1,
            'reshape_kernel': True,
        }

        mapping_rule.update(layout_attrs())
        embed_input(mapping_rule, 1, 'weights', weights)
        embed_input(mapping_rule, 2, 'biases', biases)

        mapping_rule['bias_addable'] = len(biases) > 0

        Convolution.update_node_stat(node, mapping_rule)
        return cls.enabled
コード例 #22
0
    def extract(cls, node):
        onnx_opset_version = get_onnx_opset_version(node)
        if onnx_opset_version is not None and onnx_opset_version >= 9:
            mode = onnx_attr(node,
                             'mode',
                             's',
                             default='nearest',
                             dst_type=lambda x: x.decode())
            ONNXResize10.update_node_stat(node, {'mode': mode})
        else:
            mode = onnx_attr(node,
                             'mode',
                             's',
                             default='nearest',
                             dst_type=lambda x: x.decode())
            scales = onnx_attr(
                node,
                'scales',
                'floats',
                dst_type=lambda x: np.array(x, dtype=np.float32))
            width_scale = onnx_attr(node, 'width_scale', 'f')
            height_scale = onnx_attr(node, 'height_scale', 'f')

            supported_modes = ['nearest', 'linear']
            if mode not in supported_modes:
                raise Error(
                    'Error decoding Upsample node {}, mode = {} is not in the list of supported modes {}.',
                    node.name, mode, supported_modes)

            if scales is not None:
                if scales.shape != (4, ):
                    raise Error(
                        'Upsample scales attribute is wrong for node {}. Only 4D scales are supported.',
                        node.name)
                if math.fabs(scales[0] - 1) > 1e-5 or math.fabs(scales[1] -
                                                                1) > 1e-5:
                    raise Error(
                        'Upsampling of batch and feature dimensions is not supported for node {}.',
                        node.name)
                height_scale = scales[2]
                width_scale = scales[3]

            if (width_scale is None
                    or height_scale is None) and len(node.in_nodes()) != 2:
                raise Error(
                    'One/both of widths_scale = {} and height_scale = {} is not defined for Upsample node {}.',
                    width_scale, height_scale, node.name)

            UpsampleOp.update_node_stat(
                node, {
                    'mode': mode,
                    'height_scale': height_scale,
                    'width_scale': width_scale
                })
        return cls.enabled
コード例 #23
0
ファイル: port.py プロジェクト: XinWangIntel/openvino
    def _create_data_if_necessary(self):
        if self.node.graph.stage == 'front':
            raise Error("_create_data_if_necessary method is not applicable for front Graph phase!")
        if self.type == 'in':
            raise Error("_create_data_if_necessary method is not applicable for 'in' Port type!")

        if self.idx not in self.node.out_nodes(control_flow=self.control_flow):
            from openvino.tools.mo.ops.op import Op
            Op.create_data_node(self.node.graph, self.node, out_port=self.idx)
            self.node['need_shape_inference'] = True
        return self.node.out_node(self.idx, control_flow=self.control_flow)
コード例 #24
0
    def find_and_replace_pattern(self, graph: Graph):
        values = graph.graph['cmd_params'].mean_scale_values
        input_nodes = graph.get_op_nodes(op='Parameter')

        if not isinstance(values, dict):
            # The case when input names to apply mean/scales weren't specified
            if len(values) != len(input_nodes):
                raise Error('Numbers of inputs and mean/scale values do not match. ' + refer_to_faq_msg(61))

            data = np.copy(values)
            values = {}
            for idx, node in enumerate(input_nodes):
                values.update(
                    {
                        node.soft_get('name', node.id): {
                            'mean': data[idx][0],
                            'scale': data[idx][1]
                        }
                    }
                )

        for node_name, node_mean_scale_values in values.items():
            node_id = None
            node_name = get_node_name_with_port_from_input_value(node_name)
            try:
                node_id, direction, port = get_node_id_with_ports(graph, node_name, skip_if_no_port=False)
                assert direction != 'out', 'Only input port can be specified for mean/scale application'
            except Error as e:
                log.warning('node_name {} is not found in graph'.format(node_name))
            if Node(graph, node_id) not in input_nodes:
                # if the user cutted-off input of the network then input node name specified in the --scale_values
                # or --mean_values doesn't correspond to a real input node generated by Model Optimizer. But
                # the information about initial input node name is stored in Placeholder's attribute 'initial_node_name'
                new_node_id = None
                for placeholder in input_nodes:
                    try:
                        placeholder_port = int(placeholder.id.split("_")[-1])
                    except Exception as ex:
                        log.debug('Can not get the port number from the node {}'.format(placeholder.id))
                        log.debug('Port will be defined as None')
                        port = None
                    if placeholder.has('initial_node_name') and placeholder.initial_node_name == node_id and (
                            port is None or placeholder_port == port):
                        new_node_id = placeholder.id
                        break
                if new_node_id is None:
                    raise Error('Input with name {} wasn\'t found!'.format(node_name) +
                                refer_to_faq_msg(83))
                node_id = new_node_id

            input_node = Node(graph, node_id)
            AddMeanScaleValues.apply_scale(graph, input_node, node_mean_scale_values)
            AddMeanScaleValues.apply_mean_value(graph, input_node, node_mean_scale_values)
コード例 #25
0
    def infer(node: Node):
        node_name = node.soft_get('name', node.id)
        loc_shape = node.in_port(0).data.get_shape()
        conf_shape = node.in_port(1).data.get_shape()
        prior_boxes_shape = node.in_port(2).data.get_shape()

        if loc_shape is None or conf_shape is None or prior_boxes_shape is None:
            raise Error(
                'Shapes for the Detection Output node "{}" are not defined'.
                format(node_name))

        prior_size = 4
        if node.has('normalized') and not node.normalized:
            prior_size = 5

        if is_fully_defined(prior_boxes_shape[-1]
                            ) and prior_boxes_shape[-1] % prior_size != 0:
            raise Error(
                'Amount of confidences "{}" is not divisible by {} for node "{}"'
                ''.format(prior_boxes_shape[-1], prior_size, node_name))

        num_priors = prior_boxes_shape[-1] // prior_size
        if not node.has_valid('keep_top_k') or node.keep_top_k == -1:
            node['keep_top_k'] = num_priors

        num_classes = conf_shape[-1] // num_priors
        num_loc_classes = num_classes
        if node.has_and_set('share_location') and node.share_location:
            num_loc_classes = 1

        if not compatible_dims(num_priors * num_loc_classes * 4,
                               loc_shape[-1]):
            raise Error(
                'Locations and prior boxes shapes mismatch: "{}" vs "{}" for node "{}"'
                ''.format(loc_shape, prior_boxes_shape, node_name))

        if not node.variance_encoded_in_target and not compatible_dims(
                prior_boxes_shape[-2], 2):
            raise Error(
                'The "-2" dimension of the prior boxes must be 2 but it is "{}" for node "{}".'
                ''.format(prior_boxes_shape[-2], node_name))

        if is_fully_defined(conf_shape[-1]) and is_fully_defined(
                num_priors) and conf_shape[-1] % num_priors != 0:
            raise Error(
                'Amount of confidences "{}" is not divisible by amount of priors "{}" for node "{}".'
                ''.format(conf_shape[-1], num_priors, node_name))

        node.out_port(0).data.set_shape(
            [1, 1, conf_shape[0] * node.keep_top_k, 7])

        # the line below is needed for the TF framework so the MO will not change the layout
        node.graph.node[node.out_node(0).id]['nchw_layout'] = True
コード例 #26
0
    def infer(node: Node):
        real_squeeze_dims = int64_array([])
        input_shape = node.in_port(0).data.get_shape()
        node_name = node.soft_get('name', node.id)
        if input_shape is None:
            raise Error(
                'Input shape is not defined for node {}'.format(node_name))

        output_shape = input_shape.copy()
        assert len(node.in_nodes(
        )) == 2, 'The Squeeze node {} must have 2 inputs'.format(node_name)

        # TODO remove the following 'if' statement when IE start support 0D tensors
        squeeze_dims = node.in_port(1).data.get_value()
        if squeeze_dims.ndim == 0:
            squeeze_dims = squeeze_dims.reshape([1])

        for dim in squeeze_dims:
            if output_shape[dim] == 1 or output_shape[dim] is dynamic_dimension:
                real_squeeze_dims = np.ma.append(
                    real_squeeze_dims,
                    get_canonical_axis_index(output_shape, dim))
            else:
                raise Error(
                    'Trying to squeeze dimension not equal to 1 for node "{}"'.
                    format(node_name))

        # if squeeze_dims empty then all 1s should be removed (tf specification of Squeeze op)
        if squeeze_dims.size == 0:
            for i in range(output_shape.size):
                if output_shape[i] == 1:
                    real_squeeze_dims = np.ma.append(
                        real_squeeze_dims,
                        get_canonical_axis_index(output_shape, i))

        assert is_fully_defined(
            real_squeeze_dims
        ), 'Squeeze dimension(s) is not defined for op "{}"'.format(node_name)
        output_shape = shape_delete(output_shape, real_squeeze_dims)
        node.out_port(0).data.set_shape(output_shape)

        # make dimensions positive to correctly translate from NHWC to NCHW layout
        if node.in_port(1).get_source().node.op == 'Const':
            node.in_port(1).data.set_value(real_squeeze_dims)

        if node.in_port(0).data.get_value() is not None:
            node.out_port(0).data.set_value(
                node.in_port(0).data.get_value().reshape(output_shape))

        # the squeeze_dim attribute will be converted to the second input in the end of the Middle phase
        PermuteInputs().set_input_permutation(node.in_node(1), node, 'input:0',
                                              'axis')
コード例 #27
0
def build_net(graph: Graph):
    try:
        if not hasattr(os.environ, 'GLOG_minloglevel'):
            os.environ['GLOG_minloglevel'] = '2'
        import caffe
        log.info('Partial inference via the framework is available')
    except ImportError:
        log.warning(
            'pyCaffe is not available. Partial inference via the framework is not '
            + 'possible')
        return

    try:
        net = caffe.Net(graph.proto_path, graph.caffemodel_path, caffe.TEST)
    except Exception as err:
        raise Error(
            'Error happened while constructing caffe.Net in the Caffe fallback function: {}. '
            + refer_to_faq_msg(12), str(err)) from err

    inputs_node_name = find_inputs(graph)

    reshape_flag = False
    for i in inputs_node_name:
        new_input_shape = graph.node[i]['shape'].astype(int)
        top_node = get_node_top(graph, i)
        caffe_shape = list(net.blobs[top_node].shape)
        if not np.all(caffe_shape == new_input_shape):
            net.blobs[top_node].reshape(*[int(x) for x in new_input_shape])
            reshape_flag = True

    if reshape_flag:
        net.reshape()

    try:
        net.forward()
    except KeyError as err:
        log.error('Error happened in Caffe net.forward: {}.'.format(str(err)))
        log.error(
            'It may point to the known bug in pycaffe when top and name of the layer do not match.'
        )
        log.error('Please make sure that the latest pycaffe is used.')
        raise Error(
            'Cannot infer shapes due to exception in Caffe: {}. ' +
            refer_to_faq_msg(13), str(err)) from err
    except Exception as err:
        raise Error(
            'Cannot infer shapes in Caffe net.forward due to exception: {}.' +
            refer_to_faq_msg(13), str(err)) from err

    graph.__setattr__('caffe_net', net)
コード例 #28
0
def check_and_update_ports(node, edges_data: list, in_port: bool = True):
    key = 'in' if in_port else 'out'
    key_in_edges = [key in edge_data for edge_data in edges_data]
    if all(key_in_edges):
        ports = [edge_data[key] for edge_data in edges_data]
        if len(ports) != len(set(ports)):
            raise Error("Please, provide unique {} ports for nodes".format(key))
    elif not any(key_in_edges):
        if node.has_valid('kind') and node.kind == 'data':
            return
        for i, edge_data in enumerate(edges_data):
            edge_data[key] = i
    else:
        raise Error("Please, provide all {} ports for nodes".format(key))
コード例 #29
0
ファイル: loader.py プロジェクト: Flex-plaidml-team/openvino
def parse_mean(file_path: str, in_shape: np.ndarray, mean_file_offsets: [tuple, None], caffe_pb2):
    blob = caffe_pb2.BlobProto()
    with open(file_path, 'rb') as file:
        data = file.read()

    if not data:
        raise Error('Mean file "{}" is empty.' + refer_to_faq_msg(5),
                    file_path)

    try:
        blob.ParseFromString(data)
        data = np.array(blob.data)  # pylint: disable=no-member

        if blob.HasField('channels') or blob.HasField('height') or blob.HasField('width'):
            data = data.reshape(blob.channels, blob.height, blob.width)  # pylint: disable=no-member
        else:
            data = data.reshape(blob.shape.dim)  # pylint: disable=no-member
        # crop mean image according to input size
        if in_shape[2] > data.shape[1] or in_shape[3] > data.shape[2]:
            raise Error(
                'Input image of shape {} is larger than mean image {} from file "{}". ' +
                refer_to_faq_msg(4),
                in_shape,
                data.shape,
                file_path
            )

        if mean_file_offsets is not None and len(mean_file_offsets) == 2:
            offset_x = mean_file_offsets[0]
            offset_y = mean_file_offsets[1]
        else:
            offset_x = int((data.shape[1] - in_shape[2]) / 2)
            offset_y = int((data.shape[2] - in_shape[3]) / 2)

        mean = []
        for i in range(in_shape[1]):
            data_channel = np.zeros(in_shape[2] * in_shape[3], dtype=np.float32)
            for x in range(in_shape[2]):
                for y in range(in_shape[3]):
                    data_channel[x * in_shape[3] + y] = data[i, x + offset_x, y + offset_y]
            mean.append(data_channel)

        return mean

    except Exception as err:
        raise Error(
            'While processing mean file "{}": {}. Probably mean file has incorrect format. ' +
            refer_to_faq_msg(6),
            file_path,
            str(err)) from err
コード例 #30
0
 def replace_sub_graph(self, graph: Graph, match: dict):
     ph = match['placeholder']
     if ph.name in graph.graph['freeze_placeholder']:
         name = ph.name
         if ph.has_and_set('data_type'):
             data_type = ph.data_type
         else:
             data_type = SUPPORTED_DATA_TYPES[
                 graph.graph['cmd_params'].data_type][0]
         string_value = graph.graph['freeze_placeholder'][name]
         try:
             if data_type != np.bool:
                 value = mo_array(string_value, dtype=data_type)
             # TODO: investigate why boolean type is allowed only for TensorFlow
             elif data_type == np.bool and graph.graph['fw'] == 'tf':
                 from openvino.tools.mo.front.tf.common import tf_data_type_cast
                 if isinstance(string_value, list):
                     casted_list = list()
                     for v in mo_array(string_value):
                         casted_list.append(
                             tf_data_type_cast[ph.data_type](v))
                     value = mo_array(string_value, dtype=data_type)
                 else:
                     value = tf_data_type_cast[ph.data_type](string_value)
             else:
                 raise Error("Cannot cast value {} to {} data_type".format(
                     string_value, data_type))
         except:
             raise Error("Cannot cast value {} to {} data_type".format(
                 string_value, data_type))
         try:
             value = np.reshape(a=value, newshape=ph.shape)
         except:
             raise Error("Can not reshape value {} to shape {}".format(
                 value, ph.shape))
         out_edges = list(graph.out_edges(ph.id, data=True))
         new_node = Const(graph).create_node(
             attrs={
                 'value': value,
                 'data_type': type(value),
                 'name': name + '/const_placeholder',
                 'shape': ph.shape
             })
         graph.erase_node(ph)
         graph.add_edges_from([(new_node.id, v, attrs)
                               for u, v, attrs in out_edges])
         log.info(
             "Placeholder node \"{}\" was replaced with Const node \"{}\" with value \"{}\""
             .format(name, new_node.name, value))