From 3374880963313ee94eb0d5221e22820b5a658683 Mon Sep 17 00:00:00 2001 From: Mesmer Gebrealfa Date: Wed, 18 Jun 2025 16:40:36 -0700 Subject: [PATCH 1/3] Fix(OpenVINO): Ensure numpy.prod passes tests and handles boolean inputs correctly. --- .gitignore | 3 +- .../openvino/excluded_concrete_tests.txt | 2 - keras/src/backend/openvino/numpy.py | 46 ++++++++++++++++++- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index afd700b49952..d32832d09635 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ examples/**/*.jpg .python-version .coverage *coverage.xml -.ruff_cache \ No newline at end of file +.ruff_cache +my_clean_keras_env_py310/ diff --git a/keras/src/backend/openvino/excluded_concrete_tests.txt b/keras/src/backend/openvino/excluded_concrete_tests.txt index 48dd1ffb49e9..15504179dcd7 100644 --- a/keras/src/backend/openvino/excluded_concrete_tests.txt +++ b/keras/src/backend/openvino/excluded_concrete_tests.txt @@ -43,7 +43,6 @@ NumpyDtypeTest::test_meshgrid NumpyDtypeTest::test_minimum_python_types NumpyDtypeTest::test_multiply NumpyDtypeTest::test_power -NumpyDtypeTest::test_prod NumpyDtypeTest::test_quantile NumpyDtypeTest::test_repeat NumpyDtypeTest::test_roll @@ -104,7 +103,6 @@ NumpyOneInputOpsCorrectnessTest::test_pad_int16_constant_2 NumpyOneInputOpsCorrectnessTest::test_pad_int8_constant_2 NumpyOneInputOpsCorrectnessTest::test_pad_uint8_constant_2 NumpyOneInputOpsCorrectnessTest::test_pad_int32_constant_2 -NumpyOneInputOpsCorrectnessTest::test_prod NumpyOneInputOpsCorrectnessTest::test_real NumpyOneInputOpsCorrectnessTest::test_repeat NumpyOneInputOpsCorrectnessTest::test_reshape diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 4f9fae1c986f..791af9f94918 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1262,8 +1262,52 @@ def pad(x, pad_width, mode="constant", constant_values=None): def prod(x, axis=None, keepdims=False, dtype=None): - raise NotImplementedError("`prod` is not supported with openvino backend") + if axis == () or axis == []: + return x + + x = get_ov_output(x) + + if axis is None: + flatten_shape = ov_opset.constant([-1], Type.i32).output(0) + x = ov_opset.reshape(x, flatten_shape, False).output(0) + axis = 0 + elif isinstance(axis, tuple): + axis = list(axis) + + axis = ov_opset.constant(axis, Type.i32).output(0) + + x_type = x.get_element_type() + + promotion_map = { + Type.bf16: Type.bf16, + Type.f16: Type.f16, + Type.f32: Type.f32, + Type.f64: Type.f64, + Type.i8: Type.i32, + Type.i16: Type.i32, + Type.i32: Type.i32, + Type.i64: Type.i64, + Type.u8: Type.u32, + Type.u16: Type.u32, + Type.u32: Type.u32, + Type.u64: Type.u64, + } + + if x_type == Type.boolean: + result_node = ov_opset.reduce_logical_and(x, axis, keepdims).output(0) + final_result = ov_opset.convert(result_node, Type.i32).output(0) + return OpenVINOKerasTensor(final_result) + + target_type = None + if dtype is None: + target_type = promotion_map.get(x_type, x_type) + else: + dtype_string = standardize_dtype(dtype) + target_type = OPENVINO_DTYPES[dtype_string] + temporary_result = ov_opset.reduce_prod(x, axis, keepdims).output(0) + final_result = ov_opset.convert(temporary_result, target_type).output(0) + return OpenVINOKerasTensor(final_result) def quantile(x, q, axis=None, method="linear", keepdims=False): raise NotImplementedError( From 69b37e08851575d3530f76c22eb54e7086ee6542 Mon Sep 17 00:00:00 2001 From: Mesmer Gebrealfa Date: Thu, 19 Jun 2025 10:06:17 -0700 Subject: [PATCH 2/3] feat(openvino): Implement numpy.prod and apply formatting --- .gitignore | 3 +-- keras/src/backend/openvino/numpy.py | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index d32832d09635..d60111a20eed 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,4 @@ examples/**/*.jpg .python-version .coverage *coverage.xml -.ruff_cache -my_clean_keras_env_py310/ + diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 791af9f94918..a82f71ad207f 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1278,7 +1278,7 @@ def prod(x, axis=None, keepdims=False, dtype=None): x_type = x.get_element_type() - promotion_map = { + /*promotion_map = { Type.bf16: Type.bf16, Type.f16: Type.f16, Type.f32: Type.f32, @@ -1291,8 +1291,28 @@ def prod(x, axis=None, keepdims=False, dtype=None): Type.u16: Type.u32, Type.u32: Type.u32, Type.u64: Type.u64, + }*/ + + OPENVINO_DTYPES = { + "float16": ov.Type.f16, + "float32": ov.Type.f32, + "float64": ov.Type.f64, + "uint8": ov.Type.u8, + "uint16": ov.Type.u16, + "uint32": ov.Type.u32, + "uint64": ov.Type.u64, + "int8": ov.Type.i8, + "int16": ov.Type.i16, + "int32": ov.Type.i32, + "int64": ov.Type.i64, + "bfloat16": ov.Type.bf16, + "bool": ov.Type.boolean, + "float8_e4m3fn": ov.Type.f8e4m3, + "float8_e5m2": ov.Type.f8e5m2, + "string": ov.Type.string, } + if x_type == Type.boolean: result_node = ov_opset.reduce_logical_and(x, axis, keepdims).output(0) final_result = ov_opset.convert(result_node, Type.i32).output(0) @@ -1300,7 +1320,7 @@ def prod(x, axis=None, keepdims=False, dtype=None): target_type = None if dtype is None: - target_type = promotion_map.get(x_type, x_type) + target_type = OPENVINO_DTYPES.get(x_type, x_type) else: dtype_string = standardize_dtype(dtype) target_type = OPENVINO_DTYPES[dtype_string] @@ -1309,6 +1329,7 @@ def prod(x, axis=None, keepdims=False, dtype=None): final_result = ov_opset.convert(temporary_result, target_type).output(0) return OpenVINOKerasTensor(final_result) + def quantile(x, q, axis=None, method="linear", keepdims=False): raise NotImplementedError( "`quantile` is not supported with openvino backend" From f2daee3e935d41a722155b55c40e5bfb5b16aae4 Mon Sep 17 00:00:00 2001 From: Mesmer Gebrealfa Date: Fri, 20 Jun 2025 09:35:59 -0700 Subject: [PATCH 3/3] Updated promotion handling --- keras/src/backend/openvino/numpy.py | 47 +++++------------------------ 1 file changed, 8 insertions(+), 39 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index a82f71ad207f..ba82d965bb16 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1278,41 +1278,6 @@ def prod(x, axis=None, keepdims=False, dtype=None): x_type = x.get_element_type() - /*promotion_map = { - Type.bf16: Type.bf16, - Type.f16: Type.f16, - Type.f32: Type.f32, - Type.f64: Type.f64, - Type.i8: Type.i32, - Type.i16: Type.i32, - Type.i32: Type.i32, - Type.i64: Type.i64, - Type.u8: Type.u32, - Type.u16: Type.u32, - Type.u32: Type.u32, - Type.u64: Type.u64, - }*/ - - OPENVINO_DTYPES = { - "float16": ov.Type.f16, - "float32": ov.Type.f32, - "float64": ov.Type.f64, - "uint8": ov.Type.u8, - "uint16": ov.Type.u16, - "uint32": ov.Type.u32, - "uint64": ov.Type.u64, - "int8": ov.Type.i8, - "int16": ov.Type.i16, - "int32": ov.Type.i32, - "int64": ov.Type.i64, - "bfloat16": ov.Type.bf16, - "bool": ov.Type.boolean, - "float8_e4m3fn": ov.Type.f8e4m3, - "float8_e5m2": ov.Type.f8e5m2, - "string": ov.Type.string, - } - - if x_type == Type.boolean: result_node = ov_opset.reduce_logical_and(x, axis, keepdims).output(0) final_result = ov_opset.convert(result_node, Type.i32).output(0) @@ -1320,16 +1285,20 @@ def prod(x, axis=None, keepdims=False, dtype=None): target_type = None if dtype is None: - target_type = OPENVINO_DTYPES.get(x_type, x_type) + if x_type in [Type.i8, Type.i16]: + target_type = Type.i32 + elif x_type in [Type.u8, Type.u16]: + target_type = Type.u32 + else: + target_type = x_type else: dtype_string = standardize_dtype(dtype) target_type = OPENVINO_DTYPES[dtype_string] - temporary_result = ov_opset.reduce_prod(x, axis, keepdims).output(0) - final_result = ov_opset.convert(temporary_result, target_type).output(0) + prod_result = ov_opset.reduce_prod(x, axis, keepdims).output(0) + final_result = ov_opset.convert(prod_result, target_type).output(0) return OpenVINOKerasTensor(final_result) - def quantile(x, q, axis=None, method="linear", keepdims=False): raise NotImplementedError( "`quantile` is not supported with openvino backend"