Skip to content

Commit 37eacb0

Browse files
authored
[OpenVINO Backend] : add support for numpy.nan_to_num (#21186)
* feat: add support for numpy.nan_to_num Signed-off-by: 11happy <[email protected]> * use np.inf Signed-off-by: 11happy <[email protected]> * correct implementation based on new tests Signed-off-by: 11happy <[email protected]> * use np only torch having import errors Signed-off-by: 11happy <[email protected]> * use inf approach Signed-off-by: 11happy <[email protected]> * refactor code Signed-off-by: 11happy <[email protected]> --------- Signed-off-by: 11happy <[email protected]>
1 parent d94e91f commit 37eacb0

File tree

3 files changed

+64
-5
lines changed

3 files changed

+64
-5
lines changed

keras/src/backend/openvino/core.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,38 @@
4141
"string": ov.Type.string,
4242
}
4343

44+
DTYPES_MAX = {
45+
ov.Type.bf16: 3.38953139e38,
46+
ov.Type.f16: np.finfo(np.float16).max,
47+
ov.Type.f32: np.finfo(np.float32).max,
48+
ov.Type.f64: np.finfo(np.float64).max,
49+
ov.Type.u8: np.iinfo(np.uint8).max,
50+
ov.Type.u16: np.iinfo(np.uint16).max,
51+
ov.Type.u32: np.iinfo(np.uint32).max,
52+
ov.Type.u64: np.iinfo(np.uint64).max,
53+
ov.Type.i8: np.iinfo(np.int8).max,
54+
ov.Type.i16: np.iinfo(np.int16).max,
55+
ov.Type.i32: np.iinfo(np.int32).max,
56+
ov.Type.i64: np.iinfo(np.int64).max,
57+
ov.Type.boolean: 1,
58+
}
59+
60+
DTYPES_MIN = {
61+
ov.Type.bf16: -3.38953139e38,
62+
ov.Type.f16: np.finfo(np.float16).min,
63+
ov.Type.f32: np.finfo(np.float32).min,
64+
ov.Type.f64: np.finfo(np.float64).min,
65+
ov.Type.u8: np.iinfo(np.uint8).min,
66+
ov.Type.u16: np.iinfo(np.uint16).min,
67+
ov.Type.u32: np.iinfo(np.uint32).min,
68+
ov.Type.u64: np.iinfo(np.uint64).min,
69+
ov.Type.i8: np.iinfo(np.int8).min,
70+
ov.Type.i16: np.iinfo(np.int16).min,
71+
ov.Type.i32: np.iinfo(np.int32).min,
72+
ov.Type.i64: np.iinfo(np.int64).min,
73+
ov.Type.boolean: 0,
74+
}
75+
4476

4577
def align_operand_types(x1, x2, op_name):
4678
x1_type = x1.element_type

keras/src/backend/openvino/excluded_concrete_tests.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ NumpyDtypeTest::test_meshgrid
3838
NumpyDtypeTest::test_minimum_python_types
3939
NumpyDtypeTest::test_moveaxis
4040
NumpyDtypeTest::test_multiply
41-
NumpyDtypeTest::test_nan
4241
NumpyDtypeTest::test_outer_
4342
NumpyDtypeTest::test_power
4443
NumpyDtypeTest::test_prod
@@ -95,7 +94,6 @@ NumpyOneInputOpsCorrectnessTest::test_mean
9594
NumpyOneInputOpsCorrectnessTest::test_median
9695
NumpyOneInputOpsCorrectnessTest::test_meshgrid
9796
NumpyOneInputOpsCorrectnessTest::test_moveaxis
98-
NumpyOneInputOpsCorrectnessTest::test_nan_to_num
9997
NumpyOneInputOpsCorrectnessTest::test_pad_float16_constant_2
10098
NumpyOneInputOpsCorrectnessTest::test_pad_float32_constant_2
10199
NumpyOneInputOpsCorrectnessTest::test_pad_float64_constant_2

keras/src/backend/openvino/numpy.py

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from keras.src.backend import config
66
from keras.src.backend.common import dtypes
77
from keras.src.backend.common.variables import standardize_dtype
8+
from keras.src.backend.openvino.core import DTYPES_MAX
9+
from keras.src.backend.openvino.core import DTYPES_MIN
810
from keras.src.backend.openvino.core import OPENVINO_DTYPES
911
from keras.src.backend.openvino.core import OpenVINOKerasTensor
1012
from keras.src.backend.openvino.core import (
@@ -1079,9 +1081,36 @@ def moveaxis(x, source, destination):
10791081

10801082

10811083
def nan_to_num(x, nan=0.0, posinf=None, neginf=None):
1082-
raise NotImplementedError(
1083-
"`nan_to_num` is not supported with openvino backend"
1084-
)
1084+
x = get_ov_output(x)
1085+
dtype = x.get_element_type()
1086+
if dtype.is_integral():
1087+
return OpenVINOKerasTensor(x)
1088+
isfloat64 = True if dtype == Type.f64 else False
1089+
if isfloat64: # conversion to f32 due to https://github.com/openvinotoolkit/openvino/issues/30264
1090+
x = ov_opset.convert(x, Type.f32).output(0)
1091+
dtype = Type.f32
1092+
nan_val = ov_opset.constant(nan, dtype).output(0)
1093+
posinf_val = ov_opset.constant(
1094+
posinf if posinf is not None else DTYPES_MAX[dtype], dtype
1095+
).output(0)
1096+
neginf_val = ov_opset.constant(
1097+
neginf if neginf is not None else DTYPES_MIN[dtype], dtype
1098+
).output(0)
1099+
posinf_mask = ov_opset.is_inf(
1100+
x,
1101+
{"detect_positive": True, "detect_negative": False},
1102+
).output(0)
1103+
neginf_mask = ov_opset.is_inf(
1104+
x,
1105+
{"detect_positive": False, "detect_negative": True},
1106+
).output(0)
1107+
nan_mask = ov_opset.is_nan(x).output(0)
1108+
x = ov_opset.select(nan_mask, nan_val, x).output(0)
1109+
x = ov_opset.select(posinf_mask, posinf_val, x).output(0)
1110+
x = ov_opset.select(neginf_mask, neginf_val, x).output(0)
1111+
if isfloat64:
1112+
x = ov_opset.convert(x, Type.f64).output(0)
1113+
return OpenVINOKerasTensor(x)
10851114

10861115

10871116
def ndim(x):

0 commit comments

Comments
 (0)