예제 #1
0
    def __call__(self, *input_values: NumericData) -> List[NumericData]:
        """Run computation on input values and return result."""
        input_values = [np.array(input_value) for input_value in input_values]
        input_shapes = [get_shape(input_value) for input_value in input_values]

        param_names = [param.friendly_name for param in self.parameters]

        if self.network_cache.get(str(input_shapes)) is None:
            capsule = Function.to_capsule(self.function)
            cnn_network = IENetwork(capsule)
            if self.function.is_dynamic():
                cnn_network.reshape(dict(zip(param_names, input_shapes)))
            # Convert unsupported inputs of the network
            _convert_inputs(cnn_network)
            self.network_cache[str(input_shapes)] = cnn_network
        else:
            cnn_network = self.network_cache[str(input_shapes)]

        executable_network = self.runtime.backend.load_network(
            cnn_network, self.runtime.backend_name)

        # Input validation
        if len(input_values) != len(self.parameters):
            raise UserInputError("Expected %s parameters, received %s.",
                                 len(self.parameters), len(input_values))
        for parameter, input in zip(self.parameters, input_values):
            parameter_shape = parameter.get_output_partial_shape(0)
            input_shape = PartialShape(input.shape)
            if len(input.shape) > 0 and not parameter_shape.compatible(
                    input_shape):
                raise UserInputError(
                    "Provided tensor's shape: %s does not match the expected: %s.",
                    input_shape,
                    parameter_shape,
                )

        request = executable_network.requests[0]
        request.infer(dict(zip(param_names, input_values)))

        # Set order of output blobs compatible with nG Function
        result_buffers = [
            self.__get_ie_output_blob_buffer(request.output_blobs, result)
            for result in self.results
        ]

        # Since OV overwrite result data type we have to convert results to the original one.
        original_dtypes = [
            get_dtype(result.get_output_element_type(0))
            for result in self.results
        ]
        converted_buffers = [
            buffer.astype(original_dtype)
            for buffer, original_dtype in zip(result_buffers, original_dtypes)
        ]
        return converted_buffers
예제 #2
0
def assert_list_of_ints(value_list: Iterable[int], message: str) -> None:
    """! Verify that the provided value is an iterable of integers."""
    try:
        for value in value_list:
            if not isinstance(value, int):
                raise TypeError
    except TypeError:
        log.warning(message)
        raise UserInputError(message, value_list)
예제 #3
0
    def __call__(self, *input_values: NumericData) -> List[NumericData]:
        """Run computation on input values and return result."""
        input_values = [np.array(input_value) for input_value in input_values]

        # Input validation
        if len(input_values) != len(self.parameters):
            raise UserInputError("Expected %s parameters, received %s.",
                                 len(self.parameters), len(input_values))
        for parameter, input in zip(self.parameters, input_values):
            parameter_shape = parameter.get_output_shape(0)
            if len(input.shape) > 0 and list(parameter_shape) != list(
                    input.shape):
                raise UserInputError(
                    "Provided tensor's shape: %s does not match the expected: %s.",
                    list(input.shape),
                    list(parameter_shape),
                )

        request = self.executable_network.requests[0]
        request.infer(dict(zip(request._inputs_list, input_values)))
        return [blob.buffer for blob in request.output_blobs.values()]
예제 #4
0
    def __call__(self, *input_values: NumericData) -> List[NumericData]:
        """Run computation on input values and return result."""
        input_values = [np.array(input_value) for input_value in input_values]
        input_shapes = [get_shape(input_value) for input_value in input_values]

        if self.network_cache.get(str(input_shapes)) is None:
            capsule = Function.to_capsule(self.function)
            cnn_network = IENetwork(capsule)
            if self.function.is_dynamic():
                param_names = [
                    param.friendly_name for param in self.parameters
                ]
                cnn_network.reshape(dict(zip(param_names, input_shapes)))
            self.network_cache[str(input_shapes)] = cnn_network
        else:
            cnn_network = self.network_cache[str(input_shapes)]

        executable_network = self.runtime.backend.load_network(
            cnn_network, self.runtime.backend_name)

        # Input validation
        if len(input_values) != len(self.parameters):
            raise UserInputError("Expected %s parameters, received %s.",
                                 len(self.parameters), len(input_values))
        for parameter, input in zip(self.parameters, input_values):
            parameter_shape = parameter.get_output_partial_shape(0)
            input_shape = PartialShape(input.shape)
            if len(input.shape) > 0 and not parameter_shape.compatible(
                    input_shape):
                raise UserInputError(
                    "Provided tensor's shape: %s does not match the expected: %s.",
                    input_shape,
                    parameter_shape,
                )

        request = executable_network.requests[0]

        request.infer(dict(zip(request._inputs_list, input_values)))
        return [blob.buffer for blob in request.output_blobs.values()]
예제 #5
0
def import_onnx_model(
        onnx_protobuf):  # type: (onnx.ModelProto) -> List[Function]
    """
    Import an ONNX Protocol Buffers model and convert it into a list of ngraph Functions.

    :param onnx_protobuf: ONNX Protocol Buffers model (onnx_pb2.ModelProto object)
    :return: list of ngraph Functions representing computations for each output.
    """
    if not isinstance(onnx_protobuf, onnx.ModelProto):
        raise UserInputError(
            'Input does not seem to be a properly formatted ONNX model.')

    return onnx_import.import_onnx_model(onnx_protobuf.SerializeToString())
예제 #6
0
def _check_value(op_name, attr_key, value, val_type, cond=None):
    # type: (str, str, Any, Type, Optional[Callable[[Any], bool]]) -> bool
    """! Check whether provided value satisfies specified criteria.

    @param      op_name:        The operator name which attributes are checked.
    @param      attr_key:       The attribute name.
    @param      value:          The value to check.
    @param      val_type:       Required value type.
    @param      cond:           The optional function running additional checks.

    :raises     UserInputError:
    @return    True if attribute satisfies all criterias. Otherwise False.
    """
    if not np.issubdtype(type(value), val_type):
        raise UserInputError(
            '{} operator attribute "{}" value must by of type {}.'.format(
                op_name, attr_key, val_type))
    if cond is not None and not cond(value):
        raise UserInputError(
            '{} operator attribute "{}" value does not satisfy provided condition.'
            .format(op_name, attr_key))
    return True
예제 #7
0
def import_onnx_file(filename):  # type: (str) -> List[Function]
    """
    Import ONNX model from a Protocol Buffers file and convert to ngraph functions.

    :param filename: path to an ONNX file
    :return: List of imported ngraph Functions (see docs for import_onnx_model).
    """
    try:
        onnx_protobuf = onnx.load(filename)
    except DecodeError:
        raise UserInputError(
            'The provided file doesn\'t contain a properly formatted ONNX model.'
        )

    return onnx_import.import_onnx_model(onnx_protobuf.SerializeToString())
예제 #8
0
파일: rt_map.py 프로젝트: zcayetan/openvino
def _convert_to_variant(item: Any) -> Variant:
    """Convert value to Variant class, otherwise throw error."""
    if isinstance(item, Variant):
        return item
    variant_mapping = {
        int: VariantInt,
        str: VariantString,
    }

    new_type = variant_mapping.get(type(item), None)

    if new_type is None:
        raise UserInputError("Cannot map value to any of registered Variant classes", str(item))

    return new_type(item)
예제 #9
0
def infer_dimensions(node_name, input_shape, output_shape):
    # type: (str, Shape, Shape) -> List[int]
    """Infer `output_shape` dimension values.

    :param node_name: The input node name.
    :param input_shape: The input data shape.
    :param output_shape: The requested output shape for the input node data.
    """
    input_shape = list(input_shape)
    output_shape = list(output_shape)
    # If an output dimension is equal to zero its actual value is copied from the input shape
    # argument.
    for idx, dim in enumerate(output_shape):
        if dim == 0:
            try:
                output_shape[idx] = input_shape[idx]
            except IndexError:
                raise UserInputError(
                    'Reshape node (%s): can not copy dimension from the shape '
                    'argument since requested index is out of range.',
                    node_name)

    # Check whether there are dimensions equal to -1 in output_shape. There may be at most one
    # such case. Its value is then inferred from the size of the tensor and the remaining
    # dimensions.
    if output_shape.count(-1) > 1:
        raise UserInputError(
            'Reshape node (%s): more than one dimension is set to (-1). Only one '
            'dimension value can be inferred.', node_name)
    elif -1 in output_shape:
        idx = output_shape.index(-1)
        output_shape[idx] = 1
        output_shape[idx] = int(
            np.product(input_shape) / np.product(output_shape))

    return output_shape
예제 #10
0
def reorder_axes(node,
                 axes_order):  # type: (NgraphNode, List[int]) -> NgraphNode
    """Permute axes according to specified axes_order parameter.

    :param node: The node which axes we want to permute.
    :param axes_order: The permutation of node tensor axes.
    :return: New node with permuted axes.
    """
    out_shape = list(node.shape)
    if axes_order is None:
        axes_order = list(range(len(node.shape)))
    elif len(axes_order) != len(node.shape):
        raise UserInputError(
            'Node (%s): provided axes count is different than '
            'input tensor rank.', node.name)
    else:
        for idx, axis in enumerate(axes_order):
            try:
                out_shape[idx] = node.shape[axis]
            except IndexError:
                raise UserInputError(
                    'Node (%s): provided axes indices are out '
                    'of range.', node.name)
    return ng.reshape(node, out_shape, axes_order)
예제 #11
0
파일: runtime.py 프로젝트: setuncay/ngraph
    def _write_ndarray_to_tensor_view(value, tensor_view):
        # type: (np.ndarray, TensorViewType) -> None
        tensor_view_dtype = get_dtype(tensor_view.element_type)
        if list(tensor_view.shape) != list(value.shape) and len(
                value.shape) > 0:
            raise UserInputError(
                'Provided tensor\'s shape: %s does not match the expected: %s.',
                list(value.shape), list(tensor_view.shape))
        if value.dtype != tensor_view_dtype:
            log.warning(
                'Attempting to write a %s value to a %s tensor. Will attempt type conversion.',
                value.dtype, tensor_view.element_type)
            value = value.astype(tensor_view_dtype)

        buffer_size = Computation._get_buffer_size(tensor_view.element_type,
                                                   tensor_view.element_count)
        tensor_view.write(util.numpy_to_c(np.ascontiguousarray(value)), 0,
                          buffer_size)
예제 #12
0
def check_valid_attribute(op_name,
                          attr_dict,
                          attr_key,
                          val_type,
                          cond=None,
                          required=False):
    # type: (str, dict, str, Type, Optional[Callable[[Any], bool]], Optional[bool]) -> bool
    """! Check whether specified attribute satisfies given criteria.

    @param  op_name:    The operator name which attributes are checked.
    @param attr_dict:   Dictionary containing key-value attributes to check.
    @param attr_key:    Key value for validated attribute.
    @param val_type:    Value type for validated attribute.
    @param cond:        Any callable wich accept attribute value and returns True or False.
    @param required:    Whether provided attribute key is not required. This mean it may be missing
                        from provided dictionary.

    :raises     UserInputError:

    @return True if attribute satisfies all criterias. Otherwise False.
    """
    result = True

    if required and attr_key not in attr_dict:
        raise UserInputError(
            'Provided dictionary is missing {} operator required attribute "{}"'
            .format(op_name, attr_key))

    if attr_key not in attr_dict:
        return result

    attr_value = attr_dict[attr_key]

    if np.isscalar(attr_value):
        result = result and _check_value(op_name, attr_key, attr_value,
                                         val_type, cond)
    else:
        for v in attr_value:
            result = result and _check_value(op_name, attr_key, v, val_type,
                                             cond)

    return result
예제 #13
0
    def __init__(self, model_proto):  # type: (onnx.ModelProto) -> None
        self._proto = model_proto

        if not isinstance(model_proto, onnx.ModelProto):
            raise UserInputError(
                'Input does not seem to be a properly formatted ONNX file.')

        # Parse op sets listed in model
        ai_onnx_opset_version = None
        for opset in model_proto.opset_import:
            if opset.domain in ['ai.onnx', '']:
                ai_onnx_opset_version = opset.version
            else:
                raise NotImplementedError(
                    'Operator set for domain %s '
                    'is not supported', opset.domain)

        self.node_factory = get_node_factory(
            opset_version=ai_onnx_opset_version)
        self.graph = GraphWrapper(model_proto.graph, self)
        super(ModelWrapper, self).__init__(model_proto, self.graph)
예제 #14
0
    def _write_ndarray_to_tensor_view(value: np.ndarray,
                                      tensor_view: Tensor) -> None:
        tensor_view_dtype = get_dtype(tensor_view.element_type)
        if list(tensor_view.shape) != list(value.shape) and len(
                value.shape) > 0:
            raise UserInputError(
                "Provided tensor's shape: %s does not match the expected: %s.",
                list(value.shape),
                list(tensor_view.shape),
            )
        if value.dtype != tensor_view_dtype:
            log.warning(
                "Attempting to write a %s value to a %s tensor. Will attempt type conversion.",
                value.dtype,
                tensor_view.element_type,
            )
            value = value.astype(tensor_view_dtype)

        buffer_size = Computation._get_buffer_size(tensor_view.element_type,
                                                   tensor_view.element_count)

        nparray = np.ascontiguousarray(value)
        tensor_view.write(util.numpy_to_c(nparray), buffer_size)
예제 #15
0
def numpy_style_broadcast_output_shape(shape_a, shape_b):
    # type: (TensorShape, TensorShape) -> Tuple[TensorShape, TensorShape, TensorShape]
    """Calculate output shape of numpy-style broadcast operation.

    :param shape_a: shape of first input tensor
    :param shape_b: shape of the second input tensor
    :return: shape of the output tensor, full shape of input tensors
    """
    output_shape = []  # type: List[int]

    shape_a = list(shape_a)
    shape_b = list(shape_b)
    rank_a = len(shape_a)
    rank_b = len(shape_b)
    max_rank = max(rank_a, rank_b)

    # left-pad A's shape with 1s until it also has p dimensions
    if rank_a < max_rank:
        for idx in range(max_rank - rank_a):
            shape_a.insert(0, 1)

    # left-pad B's shape with 1s until is also has p dimensions
    elif rank_b < max_rank:
        for idx in range(max_rank - rank_b):
            shape_b.insert(0, 1)

    for idx in range(max_rank - 1, -1, -1):
        idx_dim_a = shape_a[idx]
        idx_dim_b = shape_b[idx]
        if idx_dim_a != 1 and idx_dim_b != 1 and idx_dim_a != idx_dim_b:
            raise UserInputError(
                'Shapes %s and %s are incompatible for broadcasting.', shape_a,
                shape_b)
        output_shape.insert(0, max(idx_dim_a, idx_dim_b))

    return output_shape, shape_a, shape_b
예제 #16
0
def numpy_style_broadcast_for_binary_operation(onnx_node, ng_inputs):
    # type: (NodeWrapper, List[NgraphNode]) -> NgraphNode
    """
    Cast shape of two nodes to make them compatible for an element-wise binary operation.

    :param onnx_node: a wrapped ONNX node
    :param ng_inputs: left and right node (inputs of the binary op)
    :return: left and right node after broadcasting
    """
    left = ng_inputs[0]
    right = ng_inputs[1]

    dimensions_identical = list(left.shape) == list(right.shape)
    if dimensions_identical:
        return left, right

    try:
        output_shape, left_full_shape, right_full_shape = numpy_style_broadcast_output_shape(
            left.shape, right.shape)
    except UserInputError:
        raise UserInputError(
            '%s node (%s): Unable to broadcast shapes %s and %s.',
            onnx_node.op_type, onnx_node.name, left.shape, right.shape)

    if list(right.shape) != output_shape:
        one_pos = [i for i, dim in enumerate(right_full_shape) if dim == 1]
        right = ng.reshape(right,
                           [dim for dim in right.shape if dim != 1])  # Squeeze
        right = ng.broadcast(right, output_shape, broadcast_axes=one_pos)

    if list(left.shape) != output_shape:
        one_pos = [i for i, dim in enumerate(left_full_shape) if dim == 1]
        left = ng.reshape(left, [dim for dim in left.shape if dim != 1])
        left = ng.broadcast(left, output_shape, broadcast_axes=one_pos)

    return left, right
예제 #17
0
def i420_to_rgb(
    arg: NodeInput,
    arg_u: Optional[NodeInput] = None,
    arg_v: Optional[NodeInput] = None,
    name: Optional[str] = None,
) -> Node:
    """Return a node which performs I420toRGB operation.

    :param  arg: The node providing single or Y plane data.
    :param  arg_u: The node providing U plane data. Required for separate planes.
    :param  arg_v: The node providing V plane data. Required for separate planes.
    :param  name: The optional name for the created output node.
    :return: The new node performing I420toRGB operation.
    """
    if arg_u is None and arg_v is None:
        inputs = as_nodes(arg)
    elif arg_u is not None and arg_v is not None:
        inputs = as_nodes(arg, arg_u, arg_v)
    else:
        raise UserInputError(
            "Operation I420toRGB must have one (single plane) or three (separate planes) inputs provided."
        )

    return _get_node_factory_opset8().create("I420toRGB", inputs)
예제 #18
0
    def create(
        self,
        op_type_name: str,
        arguments: Optional[List[Union[Node, Output]]] = None,
        attributes: Optional[Dict[str, Any]] = None,
    ) -> Node:
        """Create node object from provided description.

        The user does not have to provide all node's attributes, but only required ones.

        :param      op_type_name:  The operator type name.
        :param      arguments:     The operator arguments.
        :param      attributes:    The operator attributes.

        returns   Node object representing requested operator with attributes set.
        """
        if arguments is None and attributes is None:
            node = self.factory.create(op_type_name)
            node._attr_cache = {}
            node._attr_cache_valid = False
            return node

        if arguments is None and attributes is not None:
            raise UserInputError(
                'Error: cannot create "{}" op without arguments.'.format(
                    op_type_name))

        if attributes is None:
            attributes = {}

        assert arguments is not None

        arguments = self._arguments_as_outputs(arguments)
        node = self.factory.create(op_type_name, arguments, attributes)

        # Currently we don't support any attribute getters & setters for TensorIterator node.
        if node.get_type_name() == "TensorIterator":
            return node

        # Set getters and setters for each node's attribute.
        #   node.get_attribute_name()
        #   node.set_attribute_name()
        # For compound (with more than one level of nesting) attributes of form ie.:
        # node.class_member_name.some_metric.attr_name:
        #   node.get_some_metric_attr_name()
        #   node.set_some_metric_attr_name()
        # Please see test_dyn_attributes.py for more usage examples.
        all_attributes = node.get_attributes()
        for attr_name in all_attributes.keys():
            setattr(
                node,
                self._normalize_attr_name_getter(attr_name),
                partial(NodeFactory._get_node_attr_value, node, attr_name),
            )
            setattr(
                node,
                self._normalize_attr_name_setter(attr_name),
                partial(NodeFactory._set_node_attr_value, node, attr_name),
            )

        # Setup helper members for caching attribute values.
        # The cache would be lazily populated at first access attempt.
        node._attr_cache = {}
        node._attr_cache_valid = False

        return node