From 8c54ebdd485cb0229a9b846b4fe68f10ac42b893 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 11:41:44 +0200 Subject: [PATCH 1/8] Implement numpy.logspace for OpenVINO backend --- .../openvino/excluded_concrete_tests.txt | 2 - keras/src/backend/openvino/numpy.py | 44 +++++++++++++++++-- pytest.ini | 3 ++ 3 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 pytest.ini diff --git a/keras/src/backend/openvino/excluded_concrete_tests.txt b/keras/src/backend/openvino/excluded_concrete_tests.txt index aa3f70f1605d..cc49c1b3c017 100644 --- a/keras/src/backend/openvino/excluded_concrete_tests.txt +++ b/keras/src/backend/openvino/excluded_concrete_tests.txt @@ -31,7 +31,6 @@ NumpyDtypeTest::test_isinf NumpyDtypeTest::test_isnan NumpyDtypeTest::test_linspace NumpyDtypeTest::test_logaddexp -NumpyDtypeTest::test_logspace NumpyDtypeTest::test_matmul_ NumpyDtypeTest::test_max NumpyDtypeTest::test_mean @@ -145,7 +144,6 @@ NumpyTwoInputOpsCorrectnessTest::test_divide_no_nan NumpyTwoInputOpsCorrectnessTest::test_einsum NumpyTwoInputOpsCorrectnessTest::test_inner NumpyTwoInputOpsCorrectnessTest::test_linspace -NumpyTwoInputOpsCorrectnessTest::test_logspace NumpyTwoInputOpsCorrectnessTest::test_outer NumpyTwoInputOpsCorrectnessTest::test_quantile NumpyTwoInputOpsCorrectnessTest::test_take_along_axis diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 493d48ce1059..ba9a5bde59dc 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1011,9 +1011,47 @@ def logical_or(x1, x2): def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): - raise NotImplementedError( - "`logspace` is not supported with openvino backend" - ) + start = get_ov_output(start) + stop = get_ov_output(stop) + num = get_ov_output(num) + base = get_ov_output(base) + + if dtype is not None: + ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)] + else: + ov_type = OPENVINO_DTYPES[config.floatx()] + + start = ov_opset.convert(start, ov_type).output(0) + stop = ov_opset.convert(stop, ov_type).output(0) + + if endpoint: + step = ov_opset.divide( + ov_opset.subtract(stop, start), + ov_opset.subtract(num, ov_opset.constant(1, Type.i32)) + ).output(0) + else: + step = ov_opset.divide( + ov_opset.subtract(stop, start), + num + ).output(0) + + indices = ov_opset.range( + ov_opset.constant(0, Type.i32), + num, + ov_opset.constant(1, Type.i32), + ov_type + ).output(0) + + linear_space = ov_opset.add( + start, + ov_opset.multiply(indices, step) + ).output(0) + + base = ov_opset.convert(base, ov_type).output(0) + + result = ov_opset.power(base, linear_space).output(0) + + return OpenVINOKerasTensor(result) def maximum(x1, x2): diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000000..83635a5b7b9b --- /dev/null +++ b/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +env = + KERAS_BACKEND=openvino \ No newline at end of file From fa99c110809c051945ff0e9567face5abd0d7401 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 12:16:39 +0200 Subject: [PATCH 2/8] fix numpy.logspace error: Arguments do not have the same element type (arg0 element type: f32, arg1 element type: i32) --- keras/src/backend/openvino/numpy.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index ba9a5bde59dc..d78b6243face 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1023,16 +1023,19 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): start = ov_opset.convert(start, ov_type).output(0) stop = ov_opset.convert(stop, ov_type).output(0) - + + num_float = ov_opset.convert(num, ov_type).output(0) + if endpoint: + one = ov_opset.constant(1, ov_type).output(0) step = ov_opset.divide( ov_opset.subtract(stop, start), - ov_opset.subtract(num, ov_opset.constant(1, Type.i32)) + ov_opset.subtract(num_float, one) ).output(0) else: step = ov_opset.divide( ov_opset.subtract(stop, start), - num + num_float ).output(0) indices = ov_opset.range( From a86a503b00e76d9632d527e6e35db48d50b220db Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 12:31:34 +0200 Subject: [PATCH 3/8] fix numpy.logspace error: Argument shapes are inconsistent.) --- keras/src/backend/openvino/numpy.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index d78b6243face..434b0fb0680c 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1023,9 +1023,11 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): start = ov_opset.convert(start, ov_type).output(0) stop = ov_opset.convert(stop, ov_type).output(0) - num_float = ov_opset.convert(num, ov_type).output(0) - + + start_shape = start.get_partial_shape().to_shape() + is_scalar_or_vector = len(start_shape) <= 1 + if endpoint: one = ov_opset.constant(1, ov_type).output(0) step = ov_opset.divide( @@ -1039,19 +1041,29 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): ).output(0) indices = ov_opset.range( - ov_opset.constant(0, Type.i32), - num, - ov_opset.constant(1, Type.i32), + ov_opset.constant(0, ov_type), + num_float, + ov_opset.constant(1, ov_type), ov_type ).output(0) + if not is_scalar_or_vector: + indices_shape = [int(num)] + for _ in range(len(start_shape)): + indices_shape.append(1) + + indices = ov_opset.reshape( + indices, + ov_opset.constant(indices_shape, Type.i32), + special_zero=False + ).output(0) + linear_space = ov_opset.add( start, ov_opset.multiply(indices, step) ).output(0) - - base = ov_opset.convert(base, ov_type).output(0) + base = ov_opset.convert(base, ov_type).output(0) result = ov_opset.power(base, linear_space).output(0) return OpenVINOKerasTensor(result) From 91cc5b2cadfc1ec8afcdbf7228db9e8048ddf974 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 14:20:48 +0200 Subject: [PATCH 4/8] fix numpy.logspace error: Argument shapes are inconsistent --- keras/src/backend/openvino/numpy.py | 55 +++++++++++------------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 434b0fb0680c..5598565cf030 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1015,57 +1015,44 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): stop = get_ov_output(stop) num = get_ov_output(num) base = get_ov_output(base) - + if dtype is not None: ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)] else: ov_type = OPENVINO_DTYPES[config.floatx()] - + start = ov_opset.convert(start, ov_type).output(0) stop = ov_opset.convert(stop, ov_type).output(0) num_float = ov_opset.convert(num, ov_type).output(0) - - start_shape = start.get_partial_shape().to_shape() - is_scalar_or_vector = len(start_shape) <= 1 - + base = ov_opset.convert(base, ov_type).output(0) + if endpoint: one = ov_opset.constant(1, ov_type).output(0) - step = ov_opset.divide( - ov_opset.subtract(stop, start), - ov_opset.subtract(num_float, one) - ).output(0) + divisor = ov_opset.subtract(num_float, one) else: - step = ov_opset.divide( - ov_opset.subtract(stop, start), - num_float - ).output(0) - + divisor = num_float + + step = ov_opset.divide(ov_opset.subtract(stop, start), divisor).output(0) + indices = ov_opset.range( - ov_opset.constant(0, ov_type), - num_float, - ov_opset.constant(1, ov_type), + ov_opset.constant(0, ov_type), + num_float, + ov_opset.constant(1, ov_type), ov_type ).output(0) - - if not is_scalar_or_vector: - indices_shape = [int(num)] - for _ in range(len(start_shape)): - indices_shape.append(1) - + + start_shape = start.get_partial_shape() + if start_shape.rank.is_static() and start_shape.rank.get_length() > 0: + indices_shape = [int(num)] + [1] * start_shape.rank.get_length() indices = ov_opset.reshape( - indices, - ov_opset.constant(indices_shape, Type.i32), + indices, + ov_opset.constant(indices_shape, dtype=Type.i32), special_zero=False ).output(0) - - linear_space = ov_opset.add( - start, - ov_opset.multiply(indices, step) - ).output(0) - - base = ov_opset.convert(base, ov_type).output(0) + + linear_space = ov_opset.add(start, ov_opset.multiply(indices, step)).output(0) result = ov_opset.power(base, linear_space).output(0) - + return OpenVINOKerasTensor(result) From 50c3ea059a872fbe8059750fa8b3a54628e07dd9 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 14:28:29 +0200 Subject: [PATCH 5/8] fix numpy.logspace error: TypeError: 'bool' object is not callable --- keras/src/backend/openvino/numpy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 5598565cf030..3402e5f37af5 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1047,7 +1047,6 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): indices = ov_opset.reshape( indices, ov_opset.constant(indices_shape, dtype=Type.i32), - special_zero=False ).output(0) linear_space = ov_opset.add(start, ov_opset.multiply(indices, step)).output(0) From 0710aa4153d566afc543cb3aab38533a0ff2da08 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 14:58:32 +0200 Subject: [PATCH 6/8] fix numpy.logspace error: TypeError: 'bool' object is not callable --- keras/src/backend/openvino/numpy.py | 74 ++++++++++++++++------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index 3402e5f37af5..b4b795de7085 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1011,48 +1011,54 @@ def logical_or(x1, x2): def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): - start = get_ov_output(start) - stop = get_ov_output(stop) - num = get_ov_output(num) - base = get_ov_output(base) - - if dtype is not None: - ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)] - else: - ov_type = OPENVINO_DTYPES[config.floatx()] - - start = ov_opset.convert(start, ov_type).output(0) - stop = ov_opset.convert(stop, ov_type).output(0) - num_float = ov_opset.convert(num, ov_type).output(0) - base = ov_opset.convert(base, ov_type).output(0) + num_value = int(num) + + start_t = ov_opset.convert(get_ov_output(start), + OPENVINO_DTYPES[standardize_dtype(dtype)] + if dtype is not None + else OPENVINO_DTYPES[config.floatx()]).output(0) + stop_t = ov_opset.convert(get_ov_output(stop), + OPENVINO_DTYPES[standardize_dtype(dtype)] + if dtype is not None + else OPENVINO_DTYPES[config.floatx()]).output(0) + num_t = ov_opset.convert(get_ov_output(num), + OPENVINO_DTYPES[config.floatx()]).output(0) + base_t = ov_opset.convert(get_ov_output(base), + OPENVINO_DTYPES[config.floatx()]).output(0) if endpoint: - one = ov_opset.constant(1, ov_type).output(0) - divisor = ov_opset.subtract(num_float, one) + one = ov_opset.constant(1, OPENVINO_DTYPES[config.floatx()]).output(0) + divisor = ov_opset.subtract(num_t, one) else: - divisor = num_float - - step = ov_opset.divide(ov_opset.subtract(stop, start), divisor).output(0) - - indices = ov_opset.range( - ov_opset.constant(0, ov_type), - num_float, - ov_opset.constant(1, ov_type), - ov_type + divisor = num_t + step_t = ov_opset.divide(ov_opset.subtract(stop_t, start_t), divisor).output(0) + + indices_t = ov_opset.range( + ov_opset.constant(0, OPENVINO_DTYPES[config.floatx()]), + num_t, + ov_opset.constant(1, OPENVINO_DTYPES[config.floatx()]), + OPENVINO_DTYPES[config.floatx()] ).output(0) - start_shape = start.get_partial_shape() - if start_shape.rank.is_static() and start_shape.rank.get_length() > 0: - indices_shape = [int(num)] + [1] * start_shape.rank.get_length() - indices = ov_opset.reshape( - indices, - ov_opset.constant(indices_shape, dtype=Type.i32), + static_shape = start_t.get_partial_shape().to_shape() # tuple di int + if len(static_shape) > 0: + reshape_shape = [num_value] + [1] * len(static_shape) + indices_t = ov_opset.reshape( + indices_t, + ov_opset.constant(reshape_shape, dtype=Type.i32), + special_zero=False ).output(0) - linear_space = ov_opset.add(start, ov_opset.multiply(indices, step)).output(0) - result = ov_opset.power(base, linear_space).output(0) + step_t = ov_opset.reshape( + step_t, + ov_opset.constant([1] + list(static_shape), dtype=Type.i32), + special_zero=False + ).output(0) - return OpenVINOKerasTensor(result) + linear_t = ov_opset.add(start_t, ov_opset.multiply(indices_t, step_t)).output(0) + result_t = ov_opset.power(base_t, linear_t).output(0) + + return OpenVINOKerasTensor(result_t) def maximum(x1, x2): From cfff887ec023a6f5262035a29ce3162caba4e473 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Thu, 8 May 2025 16:50:26 +0200 Subject: [PATCH 7/8] fix numpy.logspace error: Arguments do not have the same element type (arg0 element type: f64, arg1 element type: f32). --- keras/src/backend/openvino/numpy.py | 49 +++++++++++++++-------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index b4b795de7085..493f46f58b61 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1011,51 +1011,52 @@ def logical_or(x1, x2): def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): - num_value = int(num) - - start_t = ov_opset.convert(get_ov_output(start), - OPENVINO_DTYPES[standardize_dtype(dtype)] - if dtype is not None - else OPENVINO_DTYPES[config.floatx()]).output(0) - stop_t = ov_opset.convert(get_ov_output(stop), - OPENVINO_DTYPES[standardize_dtype(dtype)] - if dtype is not None - else OPENVINO_DTYPES[config.floatx()]).output(0) - num_t = ov_opset.convert(get_ov_output(num), - OPENVINO_DTYPES[config.floatx()]).output(0) - base_t = ov_opset.convert(get_ov_output(base), - OPENVINO_DTYPES[config.floatx()]).output(0) + if dtype is not None: + ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)] + else: + ov_type = OPENVINO_DTYPES[config.floatx()] + + start_t = ov_opset.convert(get_ov_output(start), ov_type).output(0) + stop_t = ov_opset.convert(get_ov_output(stop), ov_type).output(0) + num_t = ov_opset.convert(get_ov_output(num), ov_type).output(0) + base_t = ov_opset.convert(get_ov_output(base), ov_type).output(0) + if isinstance(num, (int, float)): + num_value = int(num) + else: + num_value = 50 + if endpoint: - one = ov_opset.constant(1, OPENVINO_DTYPES[config.floatx()]).output(0) - divisor = ov_opset.subtract(num_t, one) + one = ov_opset.constant(1, ov_type).output(0) + divisor = ov_opset.subtract(num_t, one).output(0) else: divisor = num_t - step_t = ov_opset.divide(ov_opset.subtract(stop_t, start_t), divisor).output(0) + + step_t = ov_opset.divide(ov_opset.subtract(stop_t, start_t).output(0), divisor).output(0) indices_t = ov_opset.range( - ov_opset.constant(0, OPENVINO_DTYPES[config.floatx()]), + ov_opset.constant(0, ov_type).output(0), num_t, - ov_opset.constant(1, OPENVINO_DTYPES[config.floatx()]), - OPENVINO_DTYPES[config.floatx()] + ov_opset.constant(1, ov_type).output(0), + ov_type ).output(0) - static_shape = start_t.get_partial_shape().to_shape() # tuple di int + static_shape = start_t.get_partial_shape().to_shape() if len(static_shape) > 0: reshape_shape = [num_value] + [1] * len(static_shape) indices_t = ov_opset.reshape( indices_t, - ov_opset.constant(reshape_shape, dtype=Type.i32), + ov_opset.constant(reshape_shape, dtype=Type.i32).output(0), special_zero=False ).output(0) step_t = ov_opset.reshape( step_t, - ov_opset.constant([1] + list(static_shape), dtype=Type.i32), + ov_opset.constant([1] + list(static_shape), dtype=Type.i32).output(0), special_zero=False ).output(0) - linear_t = ov_opset.add(start_t, ov_opset.multiply(indices_t, step_t)).output(0) + linear_t = ov_opset.add(start_t, ov_opset.multiply(indices_t, step_t).output(0)).output(0) result_t = ov_opset.power(base_t, linear_t).output(0) return OpenVINOKerasTensor(result_t) From 5809ee1299742dc1cf8a2af5126e3a5f8c060006 Mon Sep 17 00:00:00 2001 From: sanleo-wq Date: Fri, 9 May 2025 17:08:12 +0200 Subject: [PATCH 8/8] fix format errors --- .gitignore | 3 ++- keras/src/backend/openvino/numpy.py | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index afd700b49952..33ff550eab92 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 +venv/ \ No newline at end of file diff --git a/keras/src/backend/openvino/numpy.py b/keras/src/backend/openvino/numpy.py index c9881cf9835a..0b2c5d96614f 100644 --- a/keras/src/backend/openvino/numpy.py +++ b/keras/src/backend/openvino/numpy.py @@ -1037,20 +1037,22 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): num_value = int(num) else: num_value = 50 - + if endpoint: one = ov_opset.constant(1, ov_type).output(0) divisor = ov_opset.subtract(num_t, one).output(0) else: divisor = num_t - - step_t = ov_opset.divide(ov_opset.subtract(stop_t, start_t).output(0), divisor).output(0) + + step_t = ov_opset.divide( + ov_opset.subtract(stop_t, start_t).output(0), divisor + ).output(0) indices_t = ov_opset.range( ov_opset.constant(0, ov_type).output(0), num_t, ov_opset.constant(1, ov_type).output(0), - ov_type + ov_type, ).output(0) static_shape = start_t.get_partial_shape().to_shape() @@ -1059,16 +1061,20 @@ def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0): indices_t = ov_opset.reshape( indices_t, ov_opset.constant(reshape_shape, dtype=Type.i32).output(0), - special_zero=False + special_zero=False, ).output(0) step_t = ov_opset.reshape( step_t, - ov_opset.constant([1] + list(static_shape), dtype=Type.i32).output(0), - special_zero=False + ov_opset.constant([1] + list(static_shape), dtype=Type.i32).output( + 0 + ), + special_zero=False, ).output(0) - linear_t = ov_opset.add(start_t, ov_opset.multiply(indices_t, step_t).output(0)).output(0) + linear_t = ov_opset.add( + start_t, ov_opset.multiply(indices_t, step_t).output(0) + ).output(0) result_t = ov_opset.power(base_t, linear_t).output(0) return OpenVINOKerasTensor(result_t)