[Opset13][pyAPI] Python API FakeConvert-13 (#21155)

* [Opset13][pyAPI] Python API FakeConvert-13

* Fix typo

* Add experimental warning

* Add missing py opset in docs

* Fix flake

* Apply suggestions from code review

Co-authored-by: Anastasia Kuporosova <anastasia.kuporosova@intel.com>

* Apply suggestions from code review

Co-authored-by: Katarzyna Mitrus <katarzyna.mitrus@intel.com>

* Apply requested changes

---------

Co-authored-by: Anastasia Kuporosova <anastasia.kuporosova@intel.com>
Co-authored-by: Katarzyna Mitrus <katarzyna.mitrus@intel.com>
This commit is contained in:
Mateusz Mikolajczyk
2023-11-21 15:25:02 +01:00
committed by GitHub
parent 4237de6bf1
commit 54a68c8a13
4 changed files with 104 additions and 1 deletions

View File

@@ -56,6 +56,7 @@ from openvino.runtime.opset1.ops import equal
from openvino.runtime.opset1.ops import erf
from openvino.runtime.opset1.ops import exp
from openvino.runtime.opset9.ops import eye
from openvino.runtime.opset13.ops import fake_convert
from openvino.runtime.opset1.ops import fake_quantize
from openvino.runtime.opset1.ops import floor
from openvino.runtime.opset1.ops import floor_mod

View File

@@ -4,7 +4,7 @@
"""Factory functions for ops added to openvino opset13."""
from functools import partial
from typing import Optional, Union
from typing import Literal, Optional, Union
import logging
import numpy as np
@@ -117,6 +117,39 @@ def bitwise_xor(
)
@nameable_op
def fake_convert(
data: NodeInput,
scale: NodeInput,
shift: Optional[NodeInput] = None,
destination_type: Literal["f8e4m3", "f8e5m2"] = "f8e4m3",
name: Optional[str] = None,
) -> Node:
"""Return a node which performs FakeConvert.
FakeConvert is experimental and may change in the future.
.. warning:: FakeConvert is experimental and may change in the future.
:param data: The node with data tensor with FP16, BF16 or FP32 datatype.
:param scale: Tensor with a scale factor for the data input value,
of the same type as the data, and shape Numpy-broadcastable to data.
:param shift: Optional tensor with value to subtract before and add after conversion of the data input value,
of the same type as the data, and shape Numpy-broadcastable to data.
:param destination_type: Type to emulate, string of either "f8e4m3" or "f8e5m2".
:param name: The optional new name for output node.
:return: The new node performing FakeConvert operation.
"""
nodes = [data, scale]
if shift is not None:
nodes.append(shift)
return _get_node_factory_opset13().create(
"FakeConvert",
as_nodes(*nodes),
{"destination_type": destination_type},
)
@nameable_op
def multinomial(
probs: NodeInput,

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2018-2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import numpy as np
import pytest
import openvino.runtime.opset13 as ops
from openvino.runtime import PartialShape, Type
@pytest.mark.parametrize(
("data_shape", "scale_shape", "shift_shape", "input_type", "destination_type"),
[
([2, 3, 8, 6], [], None, np.float32, None),
([2, 3, -1, 6], [], [], np.float16, "f8e4m3"),
([4, 4], [4], [4], np.float16, "f8e5m2"),
],
)
def test_fake_convert_param_inputs(data_shape, scale_shape, shift_shape, input_type, destination_type):
data = ops.parameter(data_shape, dtype=input_type)
scale = ops.parameter(scale_shape, dtype=input_type)
input_kwargs = {"data": data, "scale": scale}
if shift_shape is not None:
input_kwargs["shift"] = ops.parameter(shift_shape, dtype=input_type)
if destination_type:
input_kwargs["destination_type"] = destination_type
op = ops.fake_convert(**input_kwargs)
assert op.get_output_size() == 1
assert op.get_type_name() == "FakeConvert"
assert op.get_output_partial_shape(0) == PartialShape(data_shape)
assert op.get_output_element_type(0) == Type(input_type)
@pytest.mark.parametrize(
("data_array", "scale_array", "shift_array", "input_type", "destination_type"),
[
(np.random.random([2, 3, 8, 6]), np.random.random([]), None, np.float32, None),
(np.random.random([2, 3, 1, 6]), np.random.random([]), np.random.random([]), np.float16, "f8e4m3"),
(np.random.random([4, 4]), np.random.random([4]), np.random.random([4]), np.float16, "f8e5m2"),
],
)
def test_fake_convert_const_inputs(data_array, scale_array, shift_array, input_type, destination_type):
data = ops.constant(data_array, dtype=input_type)
scale = ops.constant(scale_array, dtype=input_type)
input_kwargs = {"data": data, "scale": scale}
if shift_array is not None:
input_kwargs["shift"] = ops.constant(shift_array, dtype=input_type)
if destination_type:
input_kwargs["destination_type"] = destination_type
op = ops.fake_convert(**input_kwargs)
assert op.get_output_size() == 1
assert op.get_type_name() == "FakeConvert"
assert op.get_output_partial_shape(0) == PartialShape(data_array.shape)
assert op.get_output_element_type(0) == Type(input_type)