keras-nightly 3.12.0.dev2025100503__py3-none-any.whl → 3.14.0.dev2026011604__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- keras/__init__.py +1 -0
- keras/_tf_keras/keras/__init__.py +1 -0
- keras/_tf_keras/keras/callbacks/__init__.py +3 -0
- keras/_tf_keras/keras/distillation/__init__.py +16 -0
- keras/_tf_keras/keras/distribution/__init__.py +3 -0
- keras/_tf_keras/keras/dtype_policies/__init__.py +3 -0
- keras/_tf_keras/keras/layers/__init__.py +21 -0
- keras/_tf_keras/keras/ops/__init__.py +13 -0
- keras/_tf_keras/keras/ops/image/__init__.py +1 -0
- keras/_tf_keras/keras/ops/linalg/__init__.py +1 -0
- keras/_tf_keras/keras/ops/nn/__init__.py +3 -0
- keras/_tf_keras/keras/ops/numpy/__init__.py +9 -0
- keras/_tf_keras/keras/quantizers/__init__.py +13 -0
- keras/callbacks/__init__.py +3 -0
- keras/distillation/__init__.py +16 -0
- keras/distribution/__init__.py +3 -0
- keras/dtype_policies/__init__.py +3 -0
- keras/layers/__init__.py +21 -0
- keras/ops/__init__.py +13 -0
- keras/ops/image/__init__.py +1 -0
- keras/ops/linalg/__init__.py +1 -0
- keras/ops/nn/__init__.py +3 -0
- keras/ops/numpy/__init__.py +9 -0
- keras/quantizers/__init__.py +13 -0
- keras/src/applications/imagenet_utils.py +4 -1
- keras/src/backend/common/backend_utils.py +30 -6
- keras/src/backend/common/name_scope.py +2 -1
- keras/src/backend/common/variables.py +30 -15
- keras/src/backend/jax/core.py +92 -3
- keras/src/backend/jax/distribution_lib.py +16 -2
- keras/src/backend/jax/linalg.py +4 -0
- keras/src/backend/jax/nn.py +509 -29
- keras/src/backend/jax/numpy.py +59 -8
- keras/src/backend/jax/trainer.py +14 -2
- keras/src/backend/numpy/linalg.py +4 -0
- keras/src/backend/numpy/nn.py +311 -1
- keras/src/backend/numpy/numpy.py +65 -2
- keras/src/backend/openvino/__init__.py +1 -0
- keras/src/backend/openvino/core.py +2 -23
- keras/src/backend/openvino/linalg.py +4 -0
- keras/src/backend/openvino/nn.py +271 -20
- keras/src/backend/openvino/numpy.py +943 -189
- keras/src/backend/tensorflow/layer.py +43 -9
- keras/src/backend/tensorflow/linalg.py +24 -0
- keras/src/backend/tensorflow/nn.py +545 -1
- keras/src/backend/tensorflow/numpy.py +250 -50
- keras/src/backend/torch/core.py +3 -1
- keras/src/backend/torch/linalg.py +4 -0
- keras/src/backend/torch/nn.py +125 -0
- keras/src/backend/torch/numpy.py +80 -2
- keras/src/callbacks/__init__.py +1 -0
- keras/src/callbacks/model_checkpoint.py +5 -0
- keras/src/callbacks/orbax_checkpoint.py +332 -0
- keras/src/callbacks/terminate_on_nan.py +54 -5
- keras/src/datasets/cifar10.py +5 -0
- keras/src/distillation/__init__.py +1 -0
- keras/src/distillation/distillation_loss.py +390 -0
- keras/src/distillation/distiller.py +598 -0
- keras/src/distribution/distribution_lib.py +14 -0
- keras/src/dtype_policies/__init__.py +2 -0
- keras/src/dtype_policies/dtype_policy.py +90 -1
- keras/src/export/__init__.py +2 -0
- keras/src/export/export_utils.py +39 -2
- keras/src/export/litert.py +248 -0
- keras/src/export/openvino.py +1 -1
- keras/src/export/tf2onnx_lib.py +3 -0
- keras/src/layers/__init__.py +13 -0
- keras/src/layers/activations/softmax.py +9 -4
- keras/src/layers/attention/multi_head_attention.py +4 -1
- keras/src/layers/core/dense.py +241 -111
- keras/src/layers/core/einsum_dense.py +316 -131
- keras/src/layers/core/embedding.py +84 -94
- keras/src/layers/core/input_layer.py +1 -0
- keras/src/layers/core/reversible_embedding.py +399 -0
- keras/src/layers/input_spec.py +17 -17
- keras/src/layers/layer.py +45 -15
- keras/src/layers/merging/dot.py +4 -1
- keras/src/layers/pooling/adaptive_average_pooling1d.py +65 -0
- keras/src/layers/pooling/adaptive_average_pooling2d.py +62 -0
- keras/src/layers/pooling/adaptive_average_pooling3d.py +63 -0
- keras/src/layers/pooling/adaptive_max_pooling1d.py +65 -0
- keras/src/layers/pooling/adaptive_max_pooling2d.py +62 -0
- keras/src/layers/pooling/adaptive_max_pooling3d.py +63 -0
- keras/src/layers/pooling/base_adaptive_pooling.py +63 -0
- keras/src/layers/preprocessing/discretization.py +6 -5
- keras/src/layers/preprocessing/feature_space.py +8 -4
- keras/src/layers/preprocessing/image_preprocessing/aug_mix.py +2 -2
- keras/src/layers/preprocessing/image_preprocessing/random_contrast.py +3 -3
- keras/src/layers/preprocessing/image_preprocessing/resizing.py +10 -0
- keras/src/layers/preprocessing/index_lookup.py +19 -1
- keras/src/layers/preprocessing/normalization.py +14 -1
- keras/src/layers/regularization/dropout.py +43 -1
- keras/src/layers/rnn/rnn.py +19 -0
- keras/src/losses/loss.py +1 -1
- keras/src/losses/losses.py +24 -0
- keras/src/metrics/confusion_metrics.py +7 -6
- keras/src/models/cloning.py +4 -0
- keras/src/models/functional.py +11 -3
- keras/src/models/model.py +172 -34
- keras/src/ops/image.py +257 -20
- keras/src/ops/linalg.py +93 -0
- keras/src/ops/nn.py +258 -0
- keras/src/ops/numpy.py +569 -36
- keras/src/optimizers/muon.py +65 -31
- keras/src/optimizers/schedules/learning_rate_schedule.py +4 -3
- keras/src/quantizers/__init__.py +14 -1
- keras/src/quantizers/awq.py +361 -0
- keras/src/quantizers/awq_config.py +140 -0
- keras/src/quantizers/awq_core.py +217 -0
- keras/src/quantizers/gptq.py +2 -8
- keras/src/quantizers/gptq_config.py +36 -1
- keras/src/quantizers/gptq_core.py +65 -79
- keras/src/quantizers/quantization_config.py +246 -0
- keras/src/quantizers/quantizers.py +127 -61
- keras/src/quantizers/utils.py +23 -0
- keras/src/random/seed_generator.py +6 -4
- keras/src/saving/file_editor.py +81 -6
- keras/src/saving/orbax_util.py +26 -0
- keras/src/saving/saving_api.py +37 -14
- keras/src/saving/saving_lib.py +1 -1
- keras/src/testing/__init__.py +1 -0
- keras/src/testing/test_case.py +45 -5
- keras/src/utils/backend_utils.py +31 -4
- keras/src/utils/dataset_utils.py +234 -35
- keras/src/utils/file_utils.py +49 -11
- keras/src/utils/image_utils.py +14 -2
- keras/src/utils/jax_layer.py +244 -55
- keras/src/utils/module_utils.py +29 -0
- keras/src/utils/progbar.py +10 -2
- keras/src/utils/rng_utils.py +9 -1
- keras/src/utils/tracking.py +5 -5
- keras/src/version.py +1 -1
- {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/METADATA +16 -6
- {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/RECORD +136 -115
- {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/WHEEL +0 -0
- {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/top_level.txt +0 -0
|
@@ -4,6 +4,7 @@ from openvino import Type
|
|
|
4
4
|
|
|
5
5
|
from keras.src.backend import config
|
|
6
6
|
from keras.src.backend.common import dtypes
|
|
7
|
+
from keras.src.backend.common.backend_utils import canonicalize_axis
|
|
7
8
|
from keras.src.backend.common.variables import standardize_dtype
|
|
8
9
|
from keras.src.backend.openvino.core import DTYPES_MAX
|
|
9
10
|
from keras.src.backend.openvino.core import DTYPES_MIN
|
|
@@ -76,25 +77,81 @@ def multiply(x1, x2):
|
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
def mean(x, axis=None, keepdims=False):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
x_ov = get_ov_output(x)
|
|
81
|
+
x_type = x_ov.get_element_type()
|
|
82
|
+
|
|
83
|
+
was_axis_none = axis is None
|
|
84
|
+
x_resolved, axis_resolved = _resolve_axis(x_ov, axis)
|
|
85
|
+
|
|
86
|
+
if axis_resolved is None:
|
|
87
|
+
return OpenVINOKerasTensor(x_ov)
|
|
88
|
+
|
|
89
|
+
if x_type.is_integral():
|
|
90
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
91
|
+
x_resolved = ov_opset.convert(x_resolved, ov_type).output(0)
|
|
92
|
+
|
|
93
|
+
result = ov_opset.reduce_mean(x_resolved, axis_resolved, keepdims).output(0)
|
|
94
|
+
|
|
95
|
+
if keepdims and was_axis_none:
|
|
96
|
+
rank = x.get_partial_shape().rank.get_length()
|
|
97
|
+
result_shape = [1] * rank
|
|
98
|
+
result = ov_opset.reshape(
|
|
99
|
+
result,
|
|
100
|
+
ov_opset.constant(result_shape, Type.i32).output(0),
|
|
101
|
+
False,
|
|
102
|
+
).output(0)
|
|
103
|
+
|
|
104
|
+
return OpenVINOKerasTensor(result)
|
|
87
105
|
|
|
88
106
|
|
|
89
107
|
def max(x, axis=None, keepdims=False, initial=None):
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
return _compute_extrema(x, "max", axis, keepdims, initial)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _compute_extrema(x, operation, axis=None, keepdims=False, initial=None):
|
|
112
|
+
if operation == "min":
|
|
113
|
+
reduction_op = ov_opset.reduce_min
|
|
114
|
+
elementwise_op = ov_opset.minimum
|
|
115
|
+
elif operation == "max":
|
|
116
|
+
reduction_op = ov_opset.reduce_max
|
|
117
|
+
elementwise_op = ov_opset.maximum
|
|
118
|
+
else:
|
|
119
|
+
raise ValueError(
|
|
120
|
+
f"Operation must be 'min' or 'max', received {operation}"
|
|
121
|
+
)
|
|
122
|
+
|
|
93
123
|
x = get_ov_output(x)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
124
|
+
x_type = x.get_element_type()
|
|
125
|
+
x_for_rank = x
|
|
126
|
+
|
|
127
|
+
is_bool = x_type == Type.boolean
|
|
128
|
+
if is_bool:
|
|
129
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
130
|
+
x_type = Type.i32
|
|
131
|
+
|
|
132
|
+
if isinstance(axis, tuple) and len(axis) == 0:
|
|
133
|
+
return OpenVINOKerasTensor(x)
|
|
134
|
+
|
|
135
|
+
was_axis_none = axis is None
|
|
136
|
+
x, axis = _resolve_axis(x, axis)
|
|
137
|
+
|
|
138
|
+
result = reduction_op(x, axis, keepdims).output(0)
|
|
139
|
+
|
|
140
|
+
if initial is not None:
|
|
141
|
+
initial_tensor = ov_opset.constant(initial, x_type).output(0)
|
|
142
|
+
result = elementwise_op(result, initial_tensor).output(0)
|
|
143
|
+
|
|
144
|
+
if keepdims and was_axis_none:
|
|
145
|
+
orig_shape = ov_opset.shape_of(x_for_rank, Type.i32).output(0)
|
|
146
|
+
orig_rank_shape = ov_opset.shape_of(orig_shape, Type.i32).output(0)
|
|
147
|
+
one = ov_opset.constant(1, Type.i32).output(0)
|
|
148
|
+
result_shape = ov_opset.broadcast(one, orig_rank_shape).output(0)
|
|
149
|
+
result = ov_opset.reshape(result, result_shape, False).output(0)
|
|
150
|
+
|
|
151
|
+
if is_bool:
|
|
152
|
+
result = ov_opset.convert(result, Type.boolean).output(0)
|
|
153
|
+
|
|
154
|
+
return OpenVINOKerasTensor(result)
|
|
98
155
|
|
|
99
156
|
|
|
100
157
|
def ones(shape, dtype=None):
|
|
@@ -125,6 +182,9 @@ def zeros(shape, dtype=None):
|
|
|
125
182
|
|
|
126
183
|
def absolute(x):
|
|
127
184
|
x = get_ov_output(x)
|
|
185
|
+
x_type = x.get_element_type()
|
|
186
|
+
if x_type == Type.boolean:
|
|
187
|
+
return OpenVINOKerasTensor(x)
|
|
128
188
|
return OpenVINOKerasTensor(ov_opset.absolute(x).output(0))
|
|
129
189
|
|
|
130
190
|
|
|
@@ -135,11 +195,10 @@ def abs(x):
|
|
|
135
195
|
|
|
136
196
|
def all(x, axis=None, keepdims=False):
|
|
137
197
|
x = get_ov_output(x)
|
|
198
|
+
x, axis = _resolve_axis(x, axis)
|
|
138
199
|
if axis is None:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
axis = 0
|
|
142
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
200
|
+
return OpenVINOKerasTensor(x)
|
|
201
|
+
x = ov_opset.convert(x, Type.boolean).output(0)
|
|
143
202
|
return OpenVINOKerasTensor(
|
|
144
203
|
ov_opset.reduce_logical_and(x, axis, keepdims).output(0)
|
|
145
204
|
)
|
|
@@ -151,28 +210,21 @@ def angle(x):
|
|
|
151
210
|
|
|
152
211
|
def any(x, axis=None, keepdims=False):
|
|
153
212
|
x = get_ov_output(x)
|
|
213
|
+
x, axis = _resolve_axis(x, axis)
|
|
154
214
|
if axis is None:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
axis = 0
|
|
158
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
215
|
+
return OpenVINOKerasTensor(x)
|
|
216
|
+
x = ov_opset.convert(x, Type.boolean).output(0)
|
|
159
217
|
return OpenVINOKerasTensor(
|
|
160
218
|
ov_opset.reduce_logical_or(x, axis, keepdims).output(0)
|
|
161
219
|
)
|
|
162
220
|
|
|
163
221
|
|
|
164
222
|
def amax(x, axis=None, keepdims=False):
|
|
165
|
-
if axis == () or axis == []:
|
|
166
|
-
return x
|
|
167
223
|
x = get_ov_output(x)
|
|
168
224
|
x_type = x.get_element_type()
|
|
225
|
+
x, axis = _resolve_axis(x, axis)
|
|
169
226
|
if axis is None:
|
|
170
|
-
|
|
171
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
172
|
-
axis = 0
|
|
173
|
-
if isinstance(axis, tuple):
|
|
174
|
-
axis = list(axis)
|
|
175
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
227
|
+
return OpenVINOKerasTensor(x)
|
|
176
228
|
if x_type == Type.boolean:
|
|
177
229
|
return OpenVINOKerasTensor(
|
|
178
230
|
ov_opset.reduce_logical_or(x, axis, keepdims).output(0)
|
|
@@ -181,10 +233,21 @@ def amax(x, axis=None, keepdims=False):
|
|
|
181
233
|
|
|
182
234
|
|
|
183
235
|
def amin(x, axis=None, keepdims=False):
|
|
184
|
-
if axis == () or axis == []:
|
|
185
|
-
return x
|
|
186
236
|
x = get_ov_output(x)
|
|
187
237
|
x_type = x.get_element_type()
|
|
238
|
+
x, axis = _resolve_axis(x, axis)
|
|
239
|
+
if axis is None:
|
|
240
|
+
return OpenVINOKerasTensor(x)
|
|
241
|
+
if x_type == Type.boolean:
|
|
242
|
+
return OpenVINOKerasTensor(
|
|
243
|
+
ov_opset.reduce_logical_and(x, axis, keepdims).output(0)
|
|
244
|
+
)
|
|
245
|
+
return OpenVINOKerasTensor(ov_opset.reduce_min(x, axis, keepdims).output(0))
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def _resolve_axis(x, axis):
|
|
249
|
+
if axis == () or axis == []:
|
|
250
|
+
return x, None
|
|
188
251
|
if axis is None:
|
|
189
252
|
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
190
253
|
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
@@ -192,11 +255,18 @@ def amin(x, axis=None, keepdims=False):
|
|
|
192
255
|
if isinstance(axis, tuple):
|
|
193
256
|
axis = list(axis)
|
|
194
257
|
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
258
|
+
return x, axis
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _upcast_type_if_needed(x):
|
|
262
|
+
x_type = x.get_element_type()
|
|
195
263
|
if x_type == Type.boolean:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
199
|
-
|
|
264
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
265
|
+
elif x_type in (Type.i8, Type.i16):
|
|
266
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
267
|
+
elif x_type in (Type.u8, Type.u16):
|
|
268
|
+
x = ov_opset.convert(x, Type.u32).output(0)
|
|
269
|
+
return x
|
|
200
270
|
|
|
201
271
|
|
|
202
272
|
def append(x1, x2, axis=None):
|
|
@@ -439,6 +509,10 @@ def array(x, dtype=None):
|
|
|
439
509
|
return np.array(x)
|
|
440
510
|
|
|
441
511
|
|
|
512
|
+
def view(x, dtype=None):
|
|
513
|
+
raise NotImplementedError("`view` is not supported with openvino backend")
|
|
514
|
+
|
|
515
|
+
|
|
442
516
|
def average(x, axis=None, weights=None):
|
|
443
517
|
x = get_ov_output(x)
|
|
444
518
|
if weights is not None:
|
|
@@ -472,22 +546,79 @@ def average(x, axis=None, weights=None):
|
|
|
472
546
|
|
|
473
547
|
|
|
474
548
|
def bartlett(x):
|
|
475
|
-
|
|
476
|
-
|
|
549
|
+
x = get_ov_output(x)
|
|
550
|
+
zero_const = ov_opset.constant(0, Type.i64)
|
|
551
|
+
one_const = ov_opset.constant(1, Type.i64)
|
|
552
|
+
two_const = ov_opset.constant(2, Type.i64)
|
|
553
|
+
two_const_f64 = ov_opset.constant(2.0, Type.f64)
|
|
554
|
+
if x.get_element_type() != Type.i64:
|
|
555
|
+
x = ov_opset.convert(x, Type.i64)
|
|
556
|
+
half = ov_opset.convert(
|
|
557
|
+
ov_opset.divide(ov_opset.subtract(x, one_const), two_const), Type.f64
|
|
477
558
|
)
|
|
559
|
+
n = ov_opset.range(zero_const, x, one_const, Type.f64)
|
|
560
|
+
condition = ov_opset.less_equal(n, half)
|
|
561
|
+
first_half = ov_opset.divide(
|
|
562
|
+
ov_opset.multiply(two_const_f64, n),
|
|
563
|
+
ov_opset.convert(ov_opset.subtract(x, one_const), Type.f64),
|
|
564
|
+
)
|
|
565
|
+
second_half = ov_opset.subtract(two_const_f64, first_half)
|
|
566
|
+
window = ov_opset.select(condition, first_half, second_half)
|
|
567
|
+
window = ov_opset.convert(window, OPENVINO_DTYPES[config.floatx()]).output(
|
|
568
|
+
0
|
|
569
|
+
)
|
|
570
|
+
return OpenVINOKerasTensor(window)
|
|
478
571
|
|
|
479
572
|
|
|
480
573
|
def hamming(x):
|
|
481
|
-
|
|
482
|
-
|
|
574
|
+
m = get_ov_output(x)
|
|
575
|
+
|
|
576
|
+
m_i64 = (
|
|
577
|
+
m if m.get_element_type() == Type.i64 else ov_opset.convert(m, Type.i64)
|
|
483
578
|
)
|
|
484
579
|
|
|
580
|
+
start = ov_opset.constant(0, Type.i64)
|
|
581
|
+
step = ov_opset.constant(1, Type.i64)
|
|
582
|
+
n = ov_opset.range(start, m_i64, step, Type.f64)
|
|
485
583
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
584
|
+
one_i64 = ov_opset.constant(1, Type.i64)
|
|
585
|
+
denom_i64 = ov_opset.subtract(m_i64, one_i64)
|
|
586
|
+
denom = ov_opset.convert(denom_i64, Type.f64)
|
|
587
|
+
|
|
588
|
+
two_pi = ov_opset.constant(2.0 * np.pi, Type.f64)
|
|
589
|
+
two_pi_over_m_minus_1 = ov_opset.divide(two_pi, denom)
|
|
590
|
+
|
|
591
|
+
x = ov_opset.multiply(two_pi_over_m_minus_1, n)
|
|
592
|
+
c = ov_opset.cos(x)
|
|
593
|
+
|
|
594
|
+
# 0.54 - 0.46 * cos(...)
|
|
595
|
+
a = ov_opset.constant(0.54, Type.f64)
|
|
596
|
+
b = ov_opset.constant(0.46, Type.f64)
|
|
597
|
+
hamming_window = ov_opset.subtract(a, ov_opset.multiply(b, c))
|
|
598
|
+
hamming_window = ov_opset.convert(
|
|
599
|
+
hamming_window, OPENVINO_DTYPES[config.floatx()]
|
|
489
600
|
)
|
|
490
601
|
|
|
602
|
+
return OpenVINOKerasTensor(hamming_window.output(0))
|
|
603
|
+
|
|
604
|
+
|
|
605
|
+
def heaviside(x1, x2):
|
|
606
|
+
x1 = get_ov_output(x1)
|
|
607
|
+
x_type = x1.get_element_type()
|
|
608
|
+
x2 = get_ov_output(x2, x_type)
|
|
609
|
+
|
|
610
|
+
zero_scalar = ov_opset.constant(0, x_type).output(0)
|
|
611
|
+
one_scalar = ov_opset.constant(1, x_type).output(0)
|
|
612
|
+
|
|
613
|
+
neg = ov_opset.less(x1, zero_scalar).output(0)
|
|
614
|
+
pos = ov_opset.greater(x1, zero_scalar).output(0)
|
|
615
|
+
eq = ov_opset.equal(x1, zero_scalar).output(0)
|
|
616
|
+
|
|
617
|
+
x = ov_opset.select(neg, zero_scalar, x1).output(0)
|
|
618
|
+
x = ov_opset.select(pos, one_scalar, x).output(0)
|
|
619
|
+
x = ov_opset.select(eq, x2, x).output(0)
|
|
620
|
+
return OpenVINOKerasTensor(x)
|
|
621
|
+
|
|
491
622
|
|
|
492
623
|
def kaiser(x, beta):
|
|
493
624
|
raise NotImplementedError("`kaiser` is not supported with openvino backend")
|
|
@@ -539,9 +670,30 @@ def bincount(x, weights=None, minlength=0, sparse=False):
|
|
|
539
670
|
|
|
540
671
|
|
|
541
672
|
def blackman(x):
|
|
542
|
-
|
|
543
|
-
|
|
673
|
+
x = get_ov_output(x)
|
|
674
|
+
zero_const = ov_opset.constant(0, Type.i64)
|
|
675
|
+
one_const = ov_opset.constant(1, Type.i64)
|
|
676
|
+
two_pi = ov_opset.constant(2.0 * np.pi, Type.f64)
|
|
677
|
+
term_1 = ov_opset.constant(0.42, Type.f64)
|
|
678
|
+
term_2 = ov_opset.constant(0.5, Type.f64)
|
|
679
|
+
term_3 = ov_opset.constant(0.08, Type.f64)
|
|
680
|
+
if x.get_element_type() != Type.i64:
|
|
681
|
+
x = ov_opset.convert(x, Type.i64)
|
|
682
|
+
n = ov_opset.range(zero_const, x, one_const, Type.f64)
|
|
683
|
+
n_minus_1 = ov_opset.subtract(
|
|
684
|
+
ov_opset.convert(x, Type.f64), ov_opset.constant(1.0, Type.f64)
|
|
685
|
+
).output(0)
|
|
686
|
+
angle_2pi = ov_opset.divide(ov_opset.multiply(two_pi, n), n_minus_1)
|
|
687
|
+
angle_4pi = ov_opset.multiply(angle_2pi, ov_opset.constant(2.0, Type.f64))
|
|
688
|
+
cos_2pi = ov_opset.cos(angle_2pi)
|
|
689
|
+
cos_4pi = ov_opset.cos(angle_4pi)
|
|
690
|
+
term_2_final = ov_opset.multiply(term_2, cos_2pi)
|
|
691
|
+
term_3_final = ov_opset.multiply(term_3, cos_4pi)
|
|
692
|
+
window = ov_opset.add(ov_opset.subtract(term_1, term_2_final), term_3_final)
|
|
693
|
+
window = ov_opset.convert(window, OPENVINO_DTYPES[config.floatx()]).output(
|
|
694
|
+
0
|
|
544
695
|
)
|
|
696
|
+
return OpenVINOKerasTensor(window)
|
|
545
697
|
|
|
546
698
|
|
|
547
699
|
def broadcast_to(x, shape):
|
|
@@ -554,16 +706,32 @@ def broadcast_to(x, shape):
|
|
|
554
706
|
|
|
555
707
|
|
|
556
708
|
def cbrt(x):
|
|
557
|
-
|
|
709
|
+
x = get_ov_output(x)
|
|
710
|
+
x_type = x.get_element_type()
|
|
711
|
+
if x_type.is_integral() or x_type == Type.boolean:
|
|
712
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()]).output(0)
|
|
713
|
+
sign_x = ov_opset.sign(x)
|
|
714
|
+
abs_x = ov_opset.absolute(x)
|
|
715
|
+
one_third = ov_opset.constant(1.0 / 3.0, x.get_element_type())
|
|
716
|
+
root_abs = ov_opset.power(abs_x, one_third)
|
|
717
|
+
res = ov_opset.multiply(sign_x, root_abs)
|
|
718
|
+
return OpenVINOKerasTensor(res.output(0))
|
|
558
719
|
|
|
559
720
|
|
|
560
721
|
def ceil(x):
|
|
561
722
|
x = get_ov_output(x)
|
|
562
|
-
|
|
723
|
+
x_type = x.get_element_type()
|
|
724
|
+
if x_type.is_integral():
|
|
725
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()]).output(0)
|
|
726
|
+
ceiling = ov_opset.ceil(x).output(0)
|
|
727
|
+
return OpenVINOKerasTensor(ceiling)
|
|
563
728
|
|
|
564
729
|
|
|
565
730
|
def clip(x, x_min, x_max):
|
|
566
731
|
x = get_ov_output(x)
|
|
732
|
+
x_type = x.get_element_type()
|
|
733
|
+
if x_type == Type.boolean:
|
|
734
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
567
735
|
x_min = get_ov_output(x_min, x.get_element_type())
|
|
568
736
|
x_max = get_ov_output(x_max, x.get_element_type())
|
|
569
737
|
clip_by_min = ov_opset.maximum(x, x_min).output(0)
|
|
@@ -619,15 +787,9 @@ def count_nonzero(x, axis=None):
|
|
|
619
787
|
zero_constant = ov_opset.convert_like(zero_constant, x)
|
|
620
788
|
x = ov_opset.not_equal(x, zero_constant).output(0)
|
|
621
789
|
x = ov_opset.convert(x, Type.i32).output(0)
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
625
|
-
axis = 0
|
|
626
|
-
if isinstance(axis, tuple):
|
|
627
|
-
axis = list(axis)
|
|
628
|
-
if axis == []:
|
|
790
|
+
x, axis = _resolve_axis(x, axis)
|
|
791
|
+
if not axis:
|
|
629
792
|
return OpenVINOKerasTensor(x)
|
|
630
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
631
793
|
return OpenVINOKerasTensor(ov_opset.reduce_sum(x, axis, False).output(0))
|
|
632
794
|
|
|
633
795
|
|
|
@@ -646,11 +808,9 @@ def cumsum(x, axis=None, dtype=None):
|
|
|
646
808
|
if dtype is not None:
|
|
647
809
|
ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)]
|
|
648
810
|
x = ov_opset.convert(x, ov_type).output(0)
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
x = ov_opset.
|
|
652
|
-
axis = 0
|
|
653
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
811
|
+
x, axis = _resolve_axis(x, axis)
|
|
812
|
+
if x.get_element_type() == Type.boolean:
|
|
813
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
654
814
|
return OpenVINOKerasTensor(ov_opset.cumsum(x, axis).output(0))
|
|
655
815
|
|
|
656
816
|
|
|
@@ -676,13 +836,120 @@ def deg2rad(x):
|
|
|
676
836
|
|
|
677
837
|
|
|
678
838
|
def diag(x, k=0):
|
|
679
|
-
|
|
839
|
+
x = get_ov_output(x)
|
|
840
|
+
x_shape = x.get_partial_shape()
|
|
841
|
+
rank = x_shape.rank.get_length()
|
|
842
|
+
|
|
843
|
+
if rank == 1:
|
|
844
|
+
N_dim = x_shape[0]
|
|
845
|
+
if not N_dim.is_static:
|
|
846
|
+
raise ValueError(
|
|
847
|
+
"diag requires input with static shape for 1D input."
|
|
848
|
+
)
|
|
849
|
+
N = N_dim.get_length()
|
|
850
|
+
output_size = N + np.abs(k)
|
|
851
|
+
out_shape = ov_opset.constant(
|
|
852
|
+
[output_size, output_size], dtype=Type.i32
|
|
853
|
+
).output(0)
|
|
854
|
+
zeros_const = ov_opset.constant(0, x.get_element_type()).output(0)
|
|
855
|
+
diag_matrix = ov_opset.broadcast(zeros_const, out_shape)
|
|
856
|
+
|
|
857
|
+
indices = []
|
|
858
|
+
if k >= 0:
|
|
859
|
+
for i in range(N):
|
|
860
|
+
indices.append([i, i + k])
|
|
861
|
+
else:
|
|
862
|
+
for i in range(N):
|
|
863
|
+
indices.append([i - k, i])
|
|
864
|
+
|
|
865
|
+
indices = np.array(indices, dtype=np.int32)
|
|
866
|
+
indices_const = ov_opset.constant(indices, dtype=Type.i32).output(0)
|
|
867
|
+
updated = ov_opset.scatter_nd_update(diag_matrix, indices_const, x)
|
|
868
|
+
return OpenVINOKerasTensor(updated.output(0))
|
|
869
|
+
|
|
870
|
+
elif rank == 2:
|
|
871
|
+
M_dim = x_shape[0]
|
|
872
|
+
N_dim = x_shape[1]
|
|
873
|
+
if not M_dim.is_static or not N_dim.is_static:
|
|
874
|
+
raise ValueError(
|
|
875
|
+
"diag requires input with static shape for 2D input."
|
|
876
|
+
)
|
|
877
|
+
M = M_dim.get_length()
|
|
878
|
+
N = N_dim.get_length()
|
|
879
|
+
|
|
880
|
+
if k >= 0:
|
|
881
|
+
L = np.minimum(M, N - k) if (N - k) > 0 else 0
|
|
882
|
+
indices = [[i, i + k] for i in range(L)]
|
|
883
|
+
else:
|
|
884
|
+
L = np.minimum(M + k, N) if (M + k) > 0 else 0
|
|
885
|
+
indices = [[i - k, i] for i in range(L)]
|
|
886
|
+
|
|
887
|
+
if L <= 0:
|
|
888
|
+
keras_dtype = ov_to_keras_type(x.get_element_type())
|
|
889
|
+
np_dtype = np.dtype(keras_dtype)
|
|
890
|
+
empty_np = np.empty((0,), dtype=np_dtype)
|
|
891
|
+
empty_const = ov_opset.constant(
|
|
892
|
+
empty_np, x.get_element_type()
|
|
893
|
+
).output(0)
|
|
894
|
+
return OpenVINOKerasTensor(empty_const)
|
|
895
|
+
|
|
896
|
+
indices = np.array(indices, dtype=np.int32)
|
|
897
|
+
indices_const = ov_opset.constant(indices, dtype=Type.i32).output(0)
|
|
898
|
+
diag_vec = ov_opset.gather_nd(x, indices_const)
|
|
899
|
+
return OpenVINOKerasTensor(diag_vec.output(0))
|
|
900
|
+
|
|
901
|
+
else:
|
|
902
|
+
raise ValueError("diag supports only 1D or 2D tensors")
|
|
680
903
|
|
|
681
904
|
|
|
682
905
|
def diagonal(x, offset=0, axis1=0, axis2=1):
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
)
|
|
906
|
+
x = get_ov_output(x)
|
|
907
|
+
shape = x.get_partial_shape()
|
|
908
|
+
rank = x.get_partial_shape().rank.get_length()
|
|
909
|
+
if rank is None:
|
|
910
|
+
raise ValueError("`diagonal` requires input tensor with static rank.")
|
|
911
|
+
if rank < 2:
|
|
912
|
+
raise ValueError(
|
|
913
|
+
f"diagonal requires input tensor with rank >= 2.Given rank: {rank}"
|
|
914
|
+
)
|
|
915
|
+
axis1 = canonicalize_axis(axis1, rank)
|
|
916
|
+
axis2 = canonicalize_axis(axis2, rank)
|
|
917
|
+
if axis1 == axis2:
|
|
918
|
+
raise ValueError("`axis1` and `axis2` cannot be the same.")
|
|
919
|
+
|
|
920
|
+
perm_order = [axis1, axis2] + [
|
|
921
|
+
i for i in range(rank) if i != axis1 and i != axis2
|
|
922
|
+
]
|
|
923
|
+
perm_const = ov_opset.constant(perm_order, dtype=Type.i32).output(0)
|
|
924
|
+
x_transposed = ov_opset.transpose(x, perm_const)
|
|
925
|
+
|
|
926
|
+
N_dim = shape[axis1]
|
|
927
|
+
M_dim = shape[axis2]
|
|
928
|
+
if not N_dim.is_static or not M_dim.is_static:
|
|
929
|
+
raise ValueError(
|
|
930
|
+
"`diagonal` requires input tensor with static shape for axes "
|
|
931
|
+
f"`axis1` ({axis1}) and `axis2` ({axis2})."
|
|
932
|
+
)
|
|
933
|
+
N = N_dim.get_length()
|
|
934
|
+
M = M_dim.get_length()
|
|
935
|
+
if offset >= 0:
|
|
936
|
+
L = np.minimum(N, M - offset) if (M - offset) > 0 else 0
|
|
937
|
+
indices = [[i, i + offset] for i in range(L)]
|
|
938
|
+
else:
|
|
939
|
+
L = np.minimum(N + offset, M) if (N + offset) > 0 else 0
|
|
940
|
+
indices = [[i - offset, i] for i in range(L)]
|
|
941
|
+
|
|
942
|
+
indices = np.array(indices, dtype=np.int32).reshape(L, 2)
|
|
943
|
+
indices_const = ov_opset.constant(indices, dtype=Type.i32).output(0)
|
|
944
|
+
|
|
945
|
+
diag_gathered = ov_opset.gather_nd(x_transposed, indices_const)
|
|
946
|
+
|
|
947
|
+
out_rank = rank - 1
|
|
948
|
+
out_perm_order = list(range(1, out_rank)) + [0]
|
|
949
|
+
out_perm_const = ov_opset.constant(out_perm_order, dtype=Type.i32).output(0)
|
|
950
|
+
|
|
951
|
+
final_output = ov_opset.transpose(diag_gathered, out_perm_const)
|
|
952
|
+
return OpenVINOKerasTensor(final_output.output(0))
|
|
686
953
|
|
|
687
954
|
|
|
688
955
|
def diff(a, n=1, axis=-1):
|
|
@@ -759,9 +1026,30 @@ def diff(a, n=1, axis=-1):
|
|
|
759
1026
|
|
|
760
1027
|
|
|
761
1028
|
def digitize(x, bins):
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
)
|
|
1029
|
+
x_node = get_ov_output(x)
|
|
1030
|
+
|
|
1031
|
+
if isinstance(bins, OpenVINOKerasTensor):
|
|
1032
|
+
bins_node = get_ov_output(bins)
|
|
1033
|
+
else:
|
|
1034
|
+
bins_np = np.asarray(bins)
|
|
1035
|
+
if bins_np.ndim != 1:
|
|
1036
|
+
raise ValueError("`bins` must be 1-D array-like")
|
|
1037
|
+
bins_node = ov_opset.constant(bins_np).output(0)
|
|
1038
|
+
|
|
1039
|
+
x_node, bins_node = _align_operand_types(x_node, bins_node, "digitize()")
|
|
1040
|
+
|
|
1041
|
+
if x_node.get_element_type() == Type.boolean:
|
|
1042
|
+
x_node = ov_opset.convert(x_node, Type.f32).output(0)
|
|
1043
|
+
bins_node = ov_opset.convert(bins_node, Type.f32).output(0)
|
|
1044
|
+
|
|
1045
|
+
result = ov_opset.bucketize(
|
|
1046
|
+
x_node,
|
|
1047
|
+
bins_node,
|
|
1048
|
+
output_type=Type.i32,
|
|
1049
|
+
with_right_bound=False,
|
|
1050
|
+
).output(0)
|
|
1051
|
+
|
|
1052
|
+
return OpenVINOKerasTensor(result)
|
|
765
1053
|
|
|
766
1054
|
|
|
767
1055
|
def dot(x1, x2):
|
|
@@ -791,6 +1079,10 @@ def empty(shape, dtype=None):
|
|
|
791
1079
|
return OpenVINOKerasTensor(empty_tensor)
|
|
792
1080
|
|
|
793
1081
|
|
|
1082
|
+
def empty_like(x, dtype=None):
|
|
1083
|
+
return zeros_like(x, dtype=dtype)
|
|
1084
|
+
|
|
1085
|
+
|
|
794
1086
|
def equal(x1, x2):
|
|
795
1087
|
element_type = None
|
|
796
1088
|
if isinstance(x1, OpenVINOKerasTensor):
|
|
@@ -833,11 +1125,101 @@ def expm1(x):
|
|
|
833
1125
|
|
|
834
1126
|
|
|
835
1127
|
def flip(x, axis=None):
|
|
836
|
-
|
|
1128
|
+
x_node = get_ov_output(x)
|
|
1129
|
+
|
|
1130
|
+
# Using OpenVINO tensor shape
|
|
1131
|
+
ndim = len(x_node.get_partial_shape())
|
|
1132
|
+
if ndim is None:
|
|
1133
|
+
raise ValueError(
|
|
1134
|
+
"The `flip` operation does not support tensors with dynamic rank "
|
|
1135
|
+
"for the OpenVINO backend."
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
if axis is None:
|
|
1139
|
+
axis = list(range(ndim))
|
|
1140
|
+
elif isinstance(axis, int):
|
|
1141
|
+
axis = [axis]
|
|
1142
|
+
|
|
1143
|
+
axis = [a + ndim if a < 0 else a for a in axis]
|
|
1144
|
+
|
|
1145
|
+
begin = [0] * ndim
|
|
1146
|
+
end = [0] * ndim
|
|
1147
|
+
strides = [1] * ndim
|
|
1148
|
+
for a in axis:
|
|
1149
|
+
strides[a] = -1
|
|
1150
|
+
|
|
1151
|
+
all_ones_mask = [1] * ndim
|
|
1152
|
+
result = ov_opset.strided_slice(
|
|
1153
|
+
data=x_node,
|
|
1154
|
+
begin=begin,
|
|
1155
|
+
end=end,
|
|
1156
|
+
strides=strides,
|
|
1157
|
+
begin_mask=all_ones_mask,
|
|
1158
|
+
end_mask=all_ones_mask,
|
|
1159
|
+
)
|
|
1160
|
+
return OpenVINOKerasTensor(result.output(0))
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
def rot90(array, k=1, axes=(0, 1)):
|
|
1164
|
+
"""Rotate an array by 90 degrees in the plane specified by axes."""
|
|
1165
|
+
array = get_ov_output(array)
|
|
1166
|
+
|
|
1167
|
+
if not isinstance(axes, (tuple, list)) or len(axes) != 2:
|
|
1168
|
+
raise ValueError("axes must be a tuple of length 2")
|
|
1169
|
+
|
|
1170
|
+
shape = array.get_partial_shape()
|
|
1171
|
+
ndim = shape.rank.get_length()
|
|
1172
|
+
if ndim is None:
|
|
1173
|
+
raise ValueError(
|
|
1174
|
+
"`rot90` does not support tensors with dynamic rank "
|
|
1175
|
+
"for the OpenVINO backend."
|
|
1176
|
+
)
|
|
1177
|
+
|
|
1178
|
+
axis1 = canonicalize_axis(axes[0], ndim)
|
|
1179
|
+
axis2 = canonicalize_axis(axes[1], ndim)
|
|
1180
|
+
|
|
1181
|
+
if axis1 == axis2:
|
|
1182
|
+
raise ValueError("axes must be different")
|
|
1183
|
+
|
|
1184
|
+
k = k % 4
|
|
1185
|
+
if k == 0:
|
|
1186
|
+
return OpenVINOKerasTensor(array)
|
|
1187
|
+
|
|
1188
|
+
result = array
|
|
1189
|
+
|
|
1190
|
+
for _ in range(k):
|
|
1191
|
+
# 1️ Transpose axis1 <-> axis2
|
|
1192
|
+
perm = list(range(ndim))
|
|
1193
|
+
perm[axis1], perm[axis2] = perm[axis2], perm[axis1]
|
|
1194
|
+
perm_const = ov_opset.constant(perm, Type.i32).output(0)
|
|
1195
|
+
result = ov_opset.transpose(result, perm_const).output(0)
|
|
1196
|
+
|
|
1197
|
+
# 2️ Reverse along axis1 using StridedSlice
|
|
1198
|
+
begin = [0] * ndim
|
|
1199
|
+
end = [0] * ndim
|
|
1200
|
+
strides = [1] * ndim
|
|
1201
|
+
strides[axis1] = -1
|
|
1202
|
+
|
|
1203
|
+
begin_mask = [1] * ndim
|
|
1204
|
+
end_mask = [1] * ndim
|
|
1205
|
+
|
|
1206
|
+
result = ov_opset.strided_slice(
|
|
1207
|
+
data=result,
|
|
1208
|
+
begin=begin,
|
|
1209
|
+
end=end,
|
|
1210
|
+
strides=strides,
|
|
1211
|
+
begin_mask=begin_mask,
|
|
1212
|
+
end_mask=end_mask,
|
|
1213
|
+
).output(0)
|
|
1214
|
+
|
|
1215
|
+
return OpenVINOKerasTensor(result)
|
|
837
1216
|
|
|
838
1217
|
|
|
839
1218
|
def floor(x):
|
|
840
1219
|
x = get_ov_output(x)
|
|
1220
|
+
x_type = x.get_element_type()
|
|
1221
|
+
if x_type.is_integral():
|
|
1222
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()])
|
|
841
1223
|
return OpenVINOKerasTensor(ov_opset.floor(x).output(0))
|
|
842
1224
|
|
|
843
1225
|
|
|
@@ -909,7 +1291,34 @@ def hstack(xs):
|
|
|
909
1291
|
|
|
910
1292
|
|
|
911
1293
|
def hypot(x1, x2):
|
|
912
|
-
|
|
1294
|
+
element_type = None
|
|
1295
|
+
if isinstance(x1, OpenVINOKerasTensor):
|
|
1296
|
+
element_type = x1.output.get_element_type()
|
|
1297
|
+
if isinstance(x2, OpenVINOKerasTensor):
|
|
1298
|
+
element_type = x2.output.get_element_type()
|
|
1299
|
+
x1 = get_ov_output(x1, element_type)
|
|
1300
|
+
x2 = get_ov_output(x2, element_type)
|
|
1301
|
+
x1, x2 = _align_operand_types(x1, x2, "hypot()")
|
|
1302
|
+
x_type = x1.get_element_type()
|
|
1303
|
+
if x_type.is_integral() or x_type == Type.boolean:
|
|
1304
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
1305
|
+
x1 = ov_opset.convert(x1, ov_type)
|
|
1306
|
+
x2 = ov_opset.convert(x2, ov_type)
|
|
1307
|
+
x1_abs = ov_opset.absolute(x1)
|
|
1308
|
+
x2_abs = ov_opset.absolute(x2)
|
|
1309
|
+
max_val = ov_opset.maximum(x1_abs, x2_abs)
|
|
1310
|
+
min_val = ov_opset.minimum(x1_abs, x2_abs)
|
|
1311
|
+
one = ov_opset.constant(1, max_val.get_element_type())
|
|
1312
|
+
is_zero_mask = ov_opset.equal(
|
|
1313
|
+
max_val, ov_opset.constant(0, max_val.get_element_type())
|
|
1314
|
+
)
|
|
1315
|
+
safe_divisor = ov_opset.select(is_zero_mask, one, max_val)
|
|
1316
|
+
ratio = ov_opset.divide(min_val, safe_divisor)
|
|
1317
|
+
result = ov_opset.multiply(
|
|
1318
|
+
max_val,
|
|
1319
|
+
ov_opset.sqrt(ov_opset.add(one, ov_opset.multiply(ratio, ratio))),
|
|
1320
|
+
)
|
|
1321
|
+
return OpenVINOKerasTensor(result.output(0))
|
|
913
1322
|
|
|
914
1323
|
|
|
915
1324
|
def identity(n, dtype=None):
|
|
@@ -950,25 +1359,70 @@ def isclose(x1, x2, rtol=1e-5, atol=1e-8, equal_nan=False):
|
|
|
950
1359
|
|
|
951
1360
|
|
|
952
1361
|
def isfinite(x):
|
|
953
|
-
|
|
954
|
-
|
|
1362
|
+
# NOTE: openvino has an is_finite operation but it does not properly
|
|
1363
|
+
# catch np.inf and -np.inf as not finite values. Hence we bootstrap here. If
|
|
1364
|
+
# that ever changes, we could simplify this to just call that operation.
|
|
1365
|
+
inf_values = get_ov_output(isinf(x))
|
|
1366
|
+
nan_values = get_ov_output(isnan(x))
|
|
1367
|
+
all_non_finite_values = ov_opset.logical_or(inf_values, nan_values).output(
|
|
1368
|
+
0
|
|
1369
|
+
)
|
|
1370
|
+
is_finite = ov_opset.logical_not(all_non_finite_values).output(0)
|
|
1371
|
+
return OpenVINOKerasTensor(is_finite)
|
|
955
1372
|
|
|
956
1373
|
|
|
957
1374
|
def isin(x1, x2, assume_unique=False, invert=False):
|
|
958
|
-
|
|
1375
|
+
x1 = get_ov_output(x1)
|
|
1376
|
+
x2 = get_ov_output(x2)
|
|
1377
|
+
output_shape = ov_opset.shape_of(x1).output(0)
|
|
1378
|
+
x1, x2 = _align_operand_types(x1, x2, "isin()")
|
|
1379
|
+
|
|
1380
|
+
minus_one = ov_opset.constant([-1], dtype=Type.i64)
|
|
1381
|
+
x1 = ov_opset.reshape(x1, minus_one, special_zero=False).output(0)
|
|
1382
|
+
x2 = ov_opset.reshape(x2, minus_one, special_zero=False).output(0)
|
|
1383
|
+
if not assume_unique:
|
|
1384
|
+
x2 = ov_opset.unique(x2).output(0)
|
|
1385
|
+
x1 = ov_opset.unsqueeze(x1, 1).output(0)
|
|
1386
|
+
x2 = ov_opset.unsqueeze(x2, 0).output(0)
|
|
1387
|
+
cmp = ov_opset.equal(x1, x2).output(0)
|
|
1388
|
+
result_flat = ov_opset.reduce_logical_or(cmp, 1).output(0)
|
|
1389
|
+
|
|
1390
|
+
if invert:
|
|
1391
|
+
result_flat = ov_opset.logical_not(result_flat).output(0)
|
|
1392
|
+
result = ov_opset.reshape(result_flat, output_shape, False).output(0)
|
|
1393
|
+
return OpenVINOKerasTensor(result)
|
|
959
1394
|
|
|
960
1395
|
|
|
961
1396
|
def isinf(x):
|
|
962
|
-
|
|
963
|
-
|
|
1397
|
+
pos_inf = get_ov_output(isposinf(x))
|
|
1398
|
+
neg_inf = get_ov_output(isneginf(x))
|
|
1399
|
+
inf = ov_opset.logical_or(pos_inf, neg_inf).output(0)
|
|
1400
|
+
return OpenVINOKerasTensor(inf)
|
|
964
1401
|
|
|
965
1402
|
|
|
966
1403
|
def isnan(x):
|
|
967
1404
|
x = get_ov_output(x)
|
|
1405
|
+
x_type = x.get_element_type()
|
|
1406
|
+
if x_type.is_integral():
|
|
1407
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()])
|
|
968
1408
|
return OpenVINOKerasTensor(ov_opset.is_nan(x).output(0))
|
|
969
1409
|
|
|
970
1410
|
|
|
971
1411
|
def isneginf(x):
|
|
1412
|
+
return _is_inf(x, pos=False)
|
|
1413
|
+
|
|
1414
|
+
|
|
1415
|
+
def isposinf(x):
|
|
1416
|
+
return _is_inf(x)
|
|
1417
|
+
|
|
1418
|
+
|
|
1419
|
+
def _is_inf(x, pos=True):
|
|
1420
|
+
# NOTE: there is an ov_opset.is_inf but it does not catch
|
|
1421
|
+
# numpy infinite values like np.inf and -np.inf, hence why we have this
|
|
1422
|
+
# if this ever changes in OpenVINO, we can do this instead:
|
|
1423
|
+
# ov_opset.is_inf(x, {"detect_positive": pos, "detect_negative": not pos})
|
|
1424
|
+
# for each infinite sign
|
|
1425
|
+
inf_value = np.inf if pos else -np.inf
|
|
972
1426
|
x = get_ov_output(x)
|
|
973
1427
|
x_type = x.get_element_type()
|
|
974
1428
|
|
|
@@ -981,36 +1435,96 @@ def isneginf(x):
|
|
|
981
1435
|
|
|
982
1436
|
if x_type == Type.bf16:
|
|
983
1437
|
x_f32 = ov_opset.convert(x, Type.f32).output(0)
|
|
984
|
-
|
|
985
|
-
|
|
1438
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
1439
|
+
is_inf = ov_opset.equal(x_f32, inf).output(0)
|
|
986
1440
|
else:
|
|
987
1441
|
if x_type == Type.f16:
|
|
988
|
-
|
|
1442
|
+
inf = ov_opset.constant(inf_value, Type.f16).output(0)
|
|
989
1443
|
elif x_type == Type.f32:
|
|
990
|
-
|
|
1444
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
991
1445
|
elif x_type == Type.f64:
|
|
992
|
-
|
|
1446
|
+
inf = ov_opset.constant(inf_value, Type.f64).output(0)
|
|
993
1447
|
else:
|
|
994
|
-
|
|
995
|
-
|
|
1448
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
1449
|
+
is_inf = ov_opset.equal(x, inf).output(0)
|
|
1450
|
+
return OpenVINOKerasTensor(is_inf)
|
|
996
1451
|
|
|
997
|
-
return OpenVINOKerasTensor(is_neg_inf)
|
|
998
1452
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
raise NotImplementedError(
|
|
1002
|
-
"`isposinf` is not supported with openvino backend"
|
|
1003
|
-
)
|
|
1453
|
+
def isreal(x):
|
|
1454
|
+
raise NotImplementedError("`isreal` is not supported with openvino backend")
|
|
1004
1455
|
|
|
1005
1456
|
|
|
1006
1457
|
def kron(x1, x2):
|
|
1007
|
-
|
|
1458
|
+
x1 = get_ov_output(x1)
|
|
1459
|
+
x2 = get_ov_output(x2)
|
|
1460
|
+
x1, x2 = _align_operand_types(x1, x2, "kron()")
|
|
1461
|
+
x1_shape = x1.get_partial_shape()
|
|
1462
|
+
x2_shape = x2.get_partial_shape()
|
|
1463
|
+
if x1_shape.rank.is_dynamic or x2_shape.rank.is_dynamic:
|
|
1464
|
+
raise ValueError(
|
|
1465
|
+
"`kron` does not support tensors with dynamic rank for "
|
|
1466
|
+
"the OpenVINO backend."
|
|
1467
|
+
)
|
|
1468
|
+
ndim1 = x1_shape.rank.get_length()
|
|
1469
|
+
ndim2 = x2_shape.rank.get_length()
|
|
1470
|
+
if ndim1 < ndim2:
|
|
1471
|
+
axes = ov_opset.range(
|
|
1472
|
+
ov_opset.constant(0, Type.i32),
|
|
1473
|
+
ov_opset.constant(ndim2 - ndim1, Type.i32),
|
|
1474
|
+
ov_opset.constant(1, Type.i32),
|
|
1475
|
+
)
|
|
1476
|
+
x1 = ov_opset.unsqueeze(x1, axes)
|
|
1477
|
+
ndim1 = ndim2
|
|
1478
|
+
elif ndim2 < ndim1:
|
|
1479
|
+
axes = ov_opset.range(
|
|
1480
|
+
ov_opset.constant(0, Type.i32),
|
|
1481
|
+
ov_opset.constant(ndim1 - ndim2, Type.i32),
|
|
1482
|
+
ov_opset.constant(1, Type.i32),
|
|
1483
|
+
)
|
|
1484
|
+
x2 = ov_opset.unsqueeze(x2, axes)
|
|
1485
|
+
ndim2 = ndim1
|
|
1486
|
+
shape1 = ov_opset.shape_of(x1, Type.i32)
|
|
1487
|
+
shape2 = ov_opset.shape_of(x2, Type.i32)
|
|
1488
|
+
ones = ov_opset.broadcast(
|
|
1489
|
+
ov_opset.constant(1, Type.i32), ov_opset.constant([ndim1], Type.i32)
|
|
1490
|
+
)
|
|
1491
|
+
axis = ov_opset.constant(1, Type.i32)
|
|
1492
|
+
flatten = ov_opset.constant([-1], Type.i32)
|
|
1493
|
+
unsqueezed_ones = ov_opset.unsqueeze(ones, axis)
|
|
1494
|
+
x1_new_shape = ov_opset.reshape(
|
|
1495
|
+
ov_opset.concat(
|
|
1496
|
+
[ov_opset.unsqueeze(shape1, axis), unsqueezed_ones],
|
|
1497
|
+
axis=1,
|
|
1498
|
+
),
|
|
1499
|
+
flatten,
|
|
1500
|
+
False,
|
|
1501
|
+
)
|
|
1502
|
+
x2_new_shape = ov_opset.reshape(
|
|
1503
|
+
ov_opset.concat(
|
|
1504
|
+
[unsqueezed_ones, ov_opset.unsqueeze(shape2, axis)],
|
|
1505
|
+
axis=1,
|
|
1506
|
+
),
|
|
1507
|
+
flatten,
|
|
1508
|
+
False,
|
|
1509
|
+
)
|
|
1510
|
+
result = ov_opset.multiply(
|
|
1511
|
+
ov_opset.reshape(x1, x1_new_shape, False),
|
|
1512
|
+
ov_opset.reshape(x2, x2_new_shape, False),
|
|
1513
|
+
)
|
|
1514
|
+
result = ov_opset.reshape(
|
|
1515
|
+
result, ov_opset.multiply(shape1, shape2), False
|
|
1516
|
+
).output(0)
|
|
1517
|
+
return OpenVINOKerasTensor(result)
|
|
1008
1518
|
|
|
1009
1519
|
|
|
1010
1520
|
def lcm(x1, x2):
|
|
1011
1521
|
raise NotImplementedError("`lcm` is not supported with openvino backend")
|
|
1012
1522
|
|
|
1013
1523
|
|
|
1524
|
+
def ldexp(x1, x2):
|
|
1525
|
+
raise NotImplementedError("`ldexp` is not supported with openvino backend")
|
|
1526
|
+
|
|
1527
|
+
|
|
1014
1528
|
def less(x1, x2):
|
|
1015
1529
|
element_type = None
|
|
1016
1530
|
if isinstance(x1, OpenVINOKerasTensor):
|
|
@@ -1505,46 +2019,7 @@ def meshgrid(*x, indexing="xy"):
|
|
|
1505
2019
|
|
|
1506
2020
|
|
|
1507
2021
|
def min(x, axis=None, keepdims=False, initial=None):
|
|
1508
|
-
x
|
|
1509
|
-
original_type = x.get_element_type()
|
|
1510
|
-
x_type = original_type
|
|
1511
|
-
x_shape = x.get_partial_shape().to_shape()
|
|
1512
|
-
|
|
1513
|
-
is_bool = x_type == Type.boolean
|
|
1514
|
-
if is_bool:
|
|
1515
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1516
|
-
x_type = Type.i32
|
|
1517
|
-
|
|
1518
|
-
if isinstance(axis, tuple) and len(axis) == 0:
|
|
1519
|
-
return OpenVINOKerasTensor(x)
|
|
1520
|
-
|
|
1521
|
-
if axis is None:
|
|
1522
|
-
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
1523
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1524
|
-
axis = 0
|
|
1525
|
-
|
|
1526
|
-
if isinstance(axis, tuple):
|
|
1527
|
-
axis = list(axis)
|
|
1528
|
-
|
|
1529
|
-
axis_const = ov_opset.constant(axis, Type.i32).output(0)
|
|
1530
|
-
min_result = ov_opset.reduce_min(x, axis_const, keepdims).output(0)
|
|
1531
|
-
|
|
1532
|
-
if initial is not None:
|
|
1533
|
-
initial_tensor = ov_opset.constant(initial, x_type).output(0)
|
|
1534
|
-
min_result = ov_opset.minimum(min_result, initial_tensor).output(0)
|
|
1535
|
-
|
|
1536
|
-
if keepdims:
|
|
1537
|
-
result_shape = [1] * len(x_shape)
|
|
1538
|
-
min_result = ov_opset.reshape(
|
|
1539
|
-
min_result,
|
|
1540
|
-
ov_opset.constant(result_shape, Type.i32).output(0),
|
|
1541
|
-
False,
|
|
1542
|
-
).output(0)
|
|
1543
|
-
|
|
1544
|
-
if is_bool:
|
|
1545
|
-
min_result = ov_opset.convert(min_result, Type.boolean).output(0)
|
|
1546
|
-
|
|
1547
|
-
return OpenVINOKerasTensor(min_result)
|
|
2022
|
+
return _compute_extrema(x, "min", axis, keepdims, initial)
|
|
1548
2023
|
|
|
1549
2024
|
|
|
1550
2025
|
def minimum(x1, x2):
|
|
@@ -1695,7 +2170,9 @@ def pad(x, pad_width, mode="constant", constant_values=None):
|
|
|
1695
2170
|
"`pad` operation supports only scalar pad value "
|
|
1696
2171
|
"in constant mode by openvino backend"
|
|
1697
2172
|
)
|
|
1698
|
-
pad_value =
|
|
2173
|
+
pad_value = ov_opset.constant(
|
|
2174
|
+
constant_values, x.get_element_type()
|
|
2175
|
+
).output(0)
|
|
1699
2176
|
|
|
1700
2177
|
# split pad_width into two tensors pads_begin and pads_end
|
|
1701
2178
|
pads_begin = []
|
|
@@ -1719,29 +2196,20 @@ def prod(x, axis=None, keepdims=False, dtype=None):
|
|
|
1719
2196
|
x = ov_opset.convert(x, ov_dtype).output(0)
|
|
1720
2197
|
# Otherwise, apply dtype promotion rules before reduction.
|
|
1721
2198
|
else:
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1725
|
-
elif x_type in (Type.i8, Type.i16):
|
|
1726
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1727
|
-
elif x_type in (Type.u8, Type.u16):
|
|
1728
|
-
x = ov_opset.convert(x, Type.u32).output(0)
|
|
1729
|
-
|
|
2199
|
+
x = _upcast_type_if_needed(x)
|
|
2200
|
+
x, axis = _resolve_axis(x, axis)
|
|
1730
2201
|
if axis is None:
|
|
1731
|
-
|
|
1732
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1733
|
-
axis = 0
|
|
1734
|
-
|
|
1735
|
-
if isinstance(axis, tuple):
|
|
1736
|
-
axis = list(axis)
|
|
1737
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
1738
|
-
|
|
2202
|
+
return OpenVINOKerasTensor(x)
|
|
1739
2203
|
# Compute the product
|
|
1740
2204
|
result = ov_opset.reduce_prod(x, axis, keepdims).output(0)
|
|
1741
2205
|
|
|
1742
2206
|
return OpenVINOKerasTensor(result)
|
|
1743
2207
|
|
|
1744
2208
|
|
|
2209
|
+
def ptp(x, axis=None, keepdims=False):
|
|
2210
|
+
raise NotImplementedError("`ptp` is not supported with openvino backend")
|
|
2211
|
+
|
|
2212
|
+
|
|
1745
2213
|
def quantile(x, q, axis=None, method="linear", keepdims=False):
|
|
1746
2214
|
raise NotImplementedError(
|
|
1747
2215
|
"`quantile` is not supported with openvino backend"
|
|
@@ -1835,7 +2303,17 @@ def reshape(x, newshape):
|
|
|
1835
2303
|
|
|
1836
2304
|
|
|
1837
2305
|
def roll(x, shift, axis=None):
|
|
1838
|
-
|
|
2306
|
+
x = get_ov_output(x)
|
|
2307
|
+
if axis is not None:
|
|
2308
|
+
result = ov_opset.roll(x, shift, axis).output(0)
|
|
2309
|
+
else:
|
|
2310
|
+
output_shape = ov_opset.shape_of(x).output(0)
|
|
2311
|
+
flattened = ov_opset.reshape(
|
|
2312
|
+
x, ov_opset.constant([-1], Type.i32), False
|
|
2313
|
+
).output(0)
|
|
2314
|
+
result = ov_opset.roll(flattened, shift, 0).output(0)
|
|
2315
|
+
result = ov_opset.reshape(result, output_shape, False).output(0)
|
|
2316
|
+
return OpenVINOKerasTensor(result)
|
|
1839
2317
|
|
|
1840
2318
|
|
|
1841
2319
|
def sign(x):
|
|
@@ -1868,7 +2346,14 @@ def sinh(x):
|
|
|
1868
2346
|
|
|
1869
2347
|
|
|
1870
2348
|
def size(x):
|
|
1871
|
-
|
|
2349
|
+
x = get_ov_output(x)
|
|
2350
|
+
shape_tensor = ov_opset.shape_of(x, output_type=Type.i64)
|
|
2351
|
+
final_size = ov_opset.reduce_prod(
|
|
2352
|
+
shape_tensor,
|
|
2353
|
+
ov_opset.constant([0], Type.i64),
|
|
2354
|
+
keep_dims=False,
|
|
2355
|
+
)
|
|
2356
|
+
return OpenVINOKerasTensor(final_size.output(0))
|
|
1872
2357
|
|
|
1873
2358
|
|
|
1874
2359
|
def sort(x, axis=-1):
|
|
@@ -1957,6 +2442,37 @@ def split(x, indices_or_sections, axis=0):
|
|
|
1957
2442
|
)
|
|
1958
2443
|
|
|
1959
2444
|
|
|
2445
|
+
def array_split(x, indices_or_sections, axis=0):
|
|
2446
|
+
original_shape = x.shape
|
|
2447
|
+
x = get_ov_output(x)
|
|
2448
|
+
|
|
2449
|
+
num_splits_val = indices_or_sections
|
|
2450
|
+
total_size = original_shape[axis]
|
|
2451
|
+
if total_size is None:
|
|
2452
|
+
raise ValueError(
|
|
2453
|
+
f"Cannot use array_split with static Python logic on dynamic axis. "
|
|
2454
|
+
f"Axis {axis} has unknown dimension for shape {original_shape}."
|
|
2455
|
+
)
|
|
2456
|
+
|
|
2457
|
+
base_size = total_size // num_splits_val
|
|
2458
|
+
remainder = total_size % num_splits_val
|
|
2459
|
+
|
|
2460
|
+
split_lengths = [base_size + 1] * remainder + [base_size] * (
|
|
2461
|
+
num_splits_val - remainder
|
|
2462
|
+
)
|
|
2463
|
+
split_lengths_tensor = ov_opset.constant(
|
|
2464
|
+
split_lengths, dtype=Type.i64
|
|
2465
|
+
).output(0)
|
|
2466
|
+
|
|
2467
|
+
axis_tensor = ov_opset.constant(axis, dtype=Type.i32).output(0)
|
|
2468
|
+
splits = ov_opset.variadic_split(x, axis_tensor, split_lengths_tensor)
|
|
2469
|
+
|
|
2470
|
+
result = []
|
|
2471
|
+
for i in range(num_splits_val):
|
|
2472
|
+
result.append(OpenVINOKerasTensor(splits.output(i)))
|
|
2473
|
+
return result
|
|
2474
|
+
|
|
2475
|
+
|
|
1960
2476
|
def stack(x, axis=0):
|
|
1961
2477
|
if isinstance(x, tuple):
|
|
1962
2478
|
x = list(x)
|
|
@@ -1973,28 +2489,26 @@ def stack(x, axis=0):
|
|
|
1973
2489
|
|
|
1974
2490
|
|
|
1975
2491
|
def std(x, axis=None, keepdims=False):
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1980
|
-
axis = 0
|
|
1981
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
1982
|
-
# The variance is computed using $Var = E[|x|^2] - |E[x]|^2$, It is faster
|
|
1983
|
-
# but less numerically stable.
|
|
1984
|
-
mean = ov_opset.reduce_mean(x, axis, keepdims).output(0)
|
|
1985
|
-
const_two = ov_opset.constant(2, x.get_element_type()).output(0)
|
|
1986
|
-
squared_x = ov_opset.power(x, const_two).output(0)
|
|
1987
|
-
squared_mean = ov_opset.power(mean, const_two).output(0)
|
|
1988
|
-
squared_x_mean = ov_opset.reduce_mean(squared_x, axis, keepdims)
|
|
1989
|
-
variance = ov_opset.subtract(squared_x_mean, squared_mean).output(0)
|
|
1990
|
-
std_var = OpenVINOKerasTensor(ov_opset.sqrt(variance).output(0))
|
|
1991
|
-
return std_var
|
|
2492
|
+
var_x = var(x, axis, keepdims)
|
|
2493
|
+
std_dev = ov_opset.sqrt(var_x).output(0)
|
|
2494
|
+
return OpenVINOKerasTensor(std_dev)
|
|
1992
2495
|
|
|
1993
2496
|
|
|
1994
2497
|
def swapaxes(x, axis1, axis2):
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2498
|
+
x = get_ov_output(x)
|
|
2499
|
+
x_shape = x.get_partial_shape()
|
|
2500
|
+
if x_shape.rank.is_dynamic:
|
|
2501
|
+
raise ValueError(
|
|
2502
|
+
"`swapaxes` does not support tensors with dynamic rank for the "
|
|
2503
|
+
"OpenVINO backend."
|
|
2504
|
+
)
|
|
2505
|
+
rank = x_shape.rank.get_length()
|
|
2506
|
+
axis1 = canonicalize_axis(axis1, rank)
|
|
2507
|
+
axis2 = canonicalize_axis(axis2, rank)
|
|
2508
|
+
axes = list(range(rank))
|
|
2509
|
+
axes[axis1], axes[axis2] = axes[axis2], axes[axis1]
|
|
2510
|
+
result = ov_opset.transpose(x, ov_opset.constant(axes, Type.i32))
|
|
2511
|
+
return OpenVINOKerasTensor(result.output(0))
|
|
1998
2512
|
|
|
1999
2513
|
|
|
2000
2514
|
def take(x, indices, axis=None):
|
|
@@ -2113,7 +2627,8 @@ def tile(x, repeats):
|
|
|
2113
2627
|
|
|
2114
2628
|
|
|
2115
2629
|
def trace(x, offset=0, axis1=0, axis2=1):
|
|
2116
|
-
|
|
2630
|
+
x = diagonal(x, offset=offset, axis1=axis1, axis2=axis2)
|
|
2631
|
+
return sum(x, axis=-1)
|
|
2117
2632
|
|
|
2118
2633
|
|
|
2119
2634
|
def tri(N, M=None, k=0, dtype=None):
|
|
@@ -2208,7 +2723,20 @@ def triu(x, k=0):
|
|
|
2208
2723
|
|
|
2209
2724
|
|
|
2210
2725
|
def vdot(x1, x2):
|
|
2211
|
-
|
|
2726
|
+
element_type = None
|
|
2727
|
+
if isinstance(x1, OpenVINOKerasTensor):
|
|
2728
|
+
element_type = x1.output.get_element_type()
|
|
2729
|
+
if isinstance(x2, OpenVINOKerasTensor):
|
|
2730
|
+
element_type = x2.output.get_element_type()
|
|
2731
|
+
x1 = get_ov_output(x1, element_type)
|
|
2732
|
+
x2 = get_ov_output(x2, element_type)
|
|
2733
|
+
x1, x2 = _align_operand_types(x1, x2, "vdot()")
|
|
2734
|
+
if x1.get_partial_shape().rank == 0 or x2.get_partial_shape().rank == 0:
|
|
2735
|
+
return OpenVINOKerasTensor(ov_opset.multiply(x1, x2).output(0))
|
|
2736
|
+
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
2737
|
+
x1 = ov_opset.reshape(x1, flatten_shape, False).output(0)
|
|
2738
|
+
x2 = ov_opset.reshape(x2, flatten_shape, False).output(0)
|
|
2739
|
+
return OpenVINOKerasTensor(ov_opset.matmul(x1, x2, False, False).output(0))
|
|
2212
2740
|
|
|
2213
2741
|
|
|
2214
2742
|
def vstack(xs):
|
|
@@ -2294,14 +2822,27 @@ def negative(x):
|
|
|
2294
2822
|
return OpenVINOKerasTensor(ov_opset.negative(x).output(0))
|
|
2295
2823
|
|
|
2296
2824
|
|
|
2825
|
+
def nextafter(x1, x2):
|
|
2826
|
+
raise NotImplementedError(
|
|
2827
|
+
"`nextafter` is not supported with openvino backend"
|
|
2828
|
+
)
|
|
2829
|
+
|
|
2830
|
+
|
|
2297
2831
|
def square(x):
|
|
2298
2832
|
x = get_ov_output(x)
|
|
2833
|
+
x_type = x.get_element_type()
|
|
2834
|
+
if x_type == Type.boolean:
|
|
2835
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
2299
2836
|
const_two = ov_opset.constant(2, x.get_element_type()).output(0)
|
|
2300
2837
|
return OpenVINOKerasTensor(ov_opset.power(x, const_two).output(0))
|
|
2301
2838
|
|
|
2302
2839
|
|
|
2303
2840
|
def sqrt(x):
|
|
2304
2841
|
x = get_ov_output(x)
|
|
2842
|
+
x_type = x.get_element_type()
|
|
2843
|
+
if x_type.is_integral():
|
|
2844
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
2845
|
+
x = ov_opset.convert(x, ov_type).output(0)
|
|
2305
2846
|
return OpenVINOKerasTensor(ov_opset.sqrt(x).output(0))
|
|
2306
2847
|
|
|
2307
2848
|
|
|
@@ -2312,6 +2853,8 @@ def squeeze(x, axis=None):
|
|
|
2312
2853
|
for idx, dim in enumerate(x.get_partial_shape()):
|
|
2313
2854
|
if dim == 1:
|
|
2314
2855
|
axis.append(idx)
|
|
2856
|
+
if isinstance(axis, tuple):
|
|
2857
|
+
axis = list(axis)
|
|
2315
2858
|
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
2316
2859
|
return OpenVINOKerasTensor(ov_opset.squeeze(x, axis).output(0))
|
|
2317
2860
|
|
|
@@ -2336,20 +2879,135 @@ def transpose(x, axes=None):
|
|
|
2336
2879
|
return OpenVINOKerasTensor(ov_opset.transpose(x, axes).output(0))
|
|
2337
2880
|
|
|
2338
2881
|
|
|
2882
|
+
def _helper_trapezoid(y, axis):
|
|
2883
|
+
rank = y.get_partial_shape().rank.get_length()
|
|
2884
|
+
strides = ov_opset.constant([1] * rank, dtype=Type.i64).output(0)
|
|
2885
|
+
|
|
2886
|
+
# y[:-1]
|
|
2887
|
+
begin1 = ov_opset.constant([0] * rank, dtype=Type.i64).output(0)
|
|
2888
|
+
end1_list = [0] * rank
|
|
2889
|
+
end1_list[axis] = -1
|
|
2890
|
+
end1 = ov_opset.constant(end1_list, dtype=Type.i64).output(0)
|
|
2891
|
+
begin_mask1 = [1] * rank
|
|
2892
|
+
begin_mask1[axis] = 0
|
|
2893
|
+
end_mask1 = [1] * rank
|
|
2894
|
+
end_mask1[axis] = 0
|
|
2895
|
+
y1 = ov_opset.strided_slice(
|
|
2896
|
+
y, begin1, end1, strides, begin_mask1, end_mask1
|
|
2897
|
+
).output(0)
|
|
2898
|
+
|
|
2899
|
+
# y[1:]
|
|
2900
|
+
begin2_list = [0] * rank
|
|
2901
|
+
begin2_list[axis] = 1
|
|
2902
|
+
begin2 = ov_opset.constant(begin2_list, dtype=Type.i64).output(0)
|
|
2903
|
+
end2 = ov_opset.constant([0] * rank, dtype=Type.i64).output(0)
|
|
2904
|
+
begin_mask2 = [1] * rank
|
|
2905
|
+
begin_mask2[axis] = 0
|
|
2906
|
+
end_mask2 = [1] * rank
|
|
2907
|
+
y2 = ov_opset.strided_slice(
|
|
2908
|
+
y, begin2, end2, strides, begin_mask2, end_mask2
|
|
2909
|
+
).output(0)
|
|
2910
|
+
|
|
2911
|
+
return y1, y2
|
|
2912
|
+
|
|
2913
|
+
|
|
2914
|
+
def trapezoid(y, x=None, dx=1.0, axis=-1):
|
|
2915
|
+
y = get_ov_output(y)
|
|
2916
|
+
y_type = y.get_element_type()
|
|
2917
|
+
|
|
2918
|
+
if y_type.is_integral():
|
|
2919
|
+
y_type = OPENVINO_DTYPES[config.floatx()]
|
|
2920
|
+
y = ov_opset.convert(y, y_type).output(0)
|
|
2921
|
+
|
|
2922
|
+
y1, y2 = _helper_trapezoid(y, axis)
|
|
2923
|
+
y_final = ov_opset.add(y1, y2).output(0)
|
|
2924
|
+
const_two = ov_opset.constant(2, dtype=y_type).output(0)
|
|
2925
|
+
y_final = ov_opset.divide(y_final, const_two).output(0)
|
|
2926
|
+
|
|
2927
|
+
if x is not None:
|
|
2928
|
+
x = get_ov_output(x)
|
|
2929
|
+
x_type = x.get_element_type()
|
|
2930
|
+
if x_type.is_integral():
|
|
2931
|
+
x_type = OPENVINO_DTYPES[config.floatx()]
|
|
2932
|
+
x = ov_opset.convert(x, x_type).output(0)
|
|
2933
|
+
|
|
2934
|
+
x1, x2 = _helper_trapezoid(x, axis)
|
|
2935
|
+
x_final = ov_opset.subtract(x2, x1).output(0)
|
|
2936
|
+
|
|
2937
|
+
else:
|
|
2938
|
+
x_final = ov_opset.constant(dx, dtype=y_type).output(0)
|
|
2939
|
+
|
|
2940
|
+
result = ov_opset.multiply(y_final, x_final).output(0)
|
|
2941
|
+
const_axis = ov_opset.constant([axis], Type.i64).output(0)
|
|
2942
|
+
result = ov_opset.reduce_sum(result, const_axis, False).output(0)
|
|
2943
|
+
|
|
2944
|
+
return OpenVINOKerasTensor(result)
|
|
2945
|
+
|
|
2946
|
+
|
|
2947
|
+
def vander(x, N=None, increasing=False):
|
|
2948
|
+
x = get_ov_output(x)
|
|
2949
|
+
x_type = x.get_element_type()
|
|
2950
|
+
|
|
2951
|
+
shape_x = ov_opset.shape_of(x, Type.i64).output(0)
|
|
2952
|
+
|
|
2953
|
+
const_zero_1D = ov_opset.constant([0], dtype=Type.i64).output(0)
|
|
2954
|
+
const_zero = ov_opset.constant(0, dtype=Type.i64).output(0)
|
|
2955
|
+
const_one = ov_opset.constant(1, dtype=Type.i64).output(0)
|
|
2956
|
+
const_mone = ov_opset.constant(-1, dtype=Type.i64).output(0)
|
|
2957
|
+
|
|
2958
|
+
if N is None:
|
|
2959
|
+
const_N = ov_opset.squeeze(shape_x, const_zero_1D).output(0)
|
|
2960
|
+
const_N_1D = shape_x
|
|
2961
|
+
else:
|
|
2962
|
+
const_N = ov_opset.constant(N, Type.i64).output(0)
|
|
2963
|
+
const_N_1D = ov_opset.constant([N], Type.i64).output(0)
|
|
2964
|
+
|
|
2965
|
+
const_N_minus_one = ov_opset.subtract(const_N, const_one).output(0)
|
|
2966
|
+
if increasing:
|
|
2967
|
+
powers = ov_opset.range(const_zero, const_N, const_one, x_type).output(
|
|
2968
|
+
0
|
|
2969
|
+
)
|
|
2970
|
+
else:
|
|
2971
|
+
powers = ov_opset.range(
|
|
2972
|
+
const_N_minus_one, const_mone, const_mone, x_type
|
|
2973
|
+
).output(0)
|
|
2974
|
+
|
|
2975
|
+
target_shape = ov_opset.concat([shape_x, const_N_1D], 0).output(0)
|
|
2976
|
+
|
|
2977
|
+
const_one_1D = ov_opset.constant([1], dtype=Type.i64).output(0)
|
|
2978
|
+
|
|
2979
|
+
powers = ov_opset.unsqueeze(powers, const_zero_1D).output(0)
|
|
2980
|
+
x = ov_opset.unsqueeze(x, const_one_1D).output(0)
|
|
2981
|
+
|
|
2982
|
+
result = ov_opset.broadcast(x, target_shape).output(0)
|
|
2983
|
+
|
|
2984
|
+
result = ov_opset.power(result, powers).output(0)
|
|
2985
|
+
|
|
2986
|
+
return OpenVINOKerasTensor(result)
|
|
2987
|
+
|
|
2988
|
+
|
|
2339
2989
|
def var(x, axis=None, keepdims=False):
|
|
2340
2990
|
x = get_ov_output(x)
|
|
2991
|
+
x_type = x.get_element_type()
|
|
2992
|
+
x, axis = _resolve_axis(x, axis)
|
|
2993
|
+
|
|
2994
|
+
work_dtype = Type.f64 if x_type.is_integral() else x.get_element_type()
|
|
2995
|
+
if x_type.is_integral():
|
|
2996
|
+
x = ov_opset.convert(x, work_dtype).output(0)
|
|
2341
2997
|
if axis is None:
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2998
|
+
const_zero = ov_opset.constant(0, dtype=work_dtype).output(0)
|
|
2999
|
+
return OpenVINOKerasTensor(
|
|
3000
|
+
ov_opset.broadcast(const_zero, ov_opset.shape_of(x)).output(0)
|
|
3001
|
+
)
|
|
2346
3002
|
# The variance is computed using $Var = E[|x|^2] - |E[x]|^2$, It is faster
|
|
2347
3003
|
# but less numerically stable.
|
|
2348
3004
|
mean = ov_opset.reduce_mean(x, axis, keepdims).output(0)
|
|
2349
|
-
const_two = ov_opset.constant(2,
|
|
3005
|
+
const_two = ov_opset.constant(2, work_dtype).output(0)
|
|
3006
|
+
|
|
2350
3007
|
squared_x = ov_opset.power(x, const_two).output(0)
|
|
2351
3008
|
squared_mean = ov_opset.power(mean, const_two).output(0)
|
|
2352
|
-
|
|
3009
|
+
|
|
3010
|
+
squared_x_mean = ov_opset.reduce_mean(squared_x, axis, keepdims).output(0)
|
|
2353
3011
|
variance = OpenVINOKerasTensor(
|
|
2354
3012
|
ov_opset.subtract(squared_x_mean, squared_mean).output(0)
|
|
2355
3013
|
)
|
|
@@ -2358,22 +3016,46 @@ def var(x, axis=None, keepdims=False):
|
|
|
2358
3016
|
|
|
2359
3017
|
def sum(x, axis=None, keepdims=False):
|
|
2360
3018
|
x = get_ov_output(x)
|
|
3019
|
+
x, axis = _resolve_axis(x, axis)
|
|
2361
3020
|
if axis is None:
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
return OpenVINOKerasTensor(ov_opset.reduce_sum(x, axis, keepdims).output(0))
|
|
3021
|
+
return OpenVINOKerasTensor(x)
|
|
3022
|
+
x = _upcast_type_if_needed(x)
|
|
3023
|
+
summed_value = ov_opset.reduce_sum(x, axis, keepdims).output(0)
|
|
3024
|
+
return OpenVINOKerasTensor(summed_value)
|
|
2367
3025
|
|
|
2368
3026
|
|
|
2369
3027
|
def eye(N, M=None, k=0, dtype=None):
|
|
2370
|
-
|
|
3028
|
+
dtype = standardize_dtype(dtype) or config.floatx()
|
|
3029
|
+
ov_type = OPENVINO_DTYPES[dtype]
|
|
3030
|
+
if M is None:
|
|
3031
|
+
M = N
|
|
3032
|
+
return OpenVINOKerasTensor(
|
|
3033
|
+
ov_opset.eye(
|
|
3034
|
+
ov_opset.constant(N, Type.i32),
|
|
3035
|
+
ov_opset.constant(M, Type.i32),
|
|
3036
|
+
ov_opset.constant(k, Type.i32),
|
|
3037
|
+
output_type=ov_type,
|
|
3038
|
+
).output(0)
|
|
3039
|
+
)
|
|
2371
3040
|
|
|
2372
3041
|
|
|
2373
3042
|
def floor_divide(x1, x2):
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
)
|
|
3043
|
+
x1_output = get_ov_output(x1)
|
|
3044
|
+
x2_output = get_ov_output(x2)
|
|
3045
|
+
if x1_output.get_element_type() == Type.boolean:
|
|
3046
|
+
x1_output = ov_opset.convert(x1_output, Type.i32).output(0)
|
|
3047
|
+
if isinstance(x2, (int, float)):
|
|
3048
|
+
if x1_output.get_element_type().is_integral() and isinstance(x2, float):
|
|
3049
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
3050
|
+
else:
|
|
3051
|
+
ov_type = x1_output.get_element_type()
|
|
3052
|
+
x1 = ov_opset.convert(x1_output, ov_type).output(0)
|
|
3053
|
+
x2 = ov_opset.convert(x2_output, ov_type).output(0)
|
|
3054
|
+
else:
|
|
3055
|
+
x1, x2 = _align_operand_types(x1_output, x2_output, "floor_divide()")
|
|
3056
|
+
div = ov_opset.divide(x1, x2).output(0)
|
|
3057
|
+
floored_div = ov_opset.floor(div).output(0)
|
|
3058
|
+
return OpenVINOKerasTensor(floored_div)
|
|
2377
3059
|
|
|
2378
3060
|
|
|
2379
3061
|
def logical_xor(x1, x2):
|
|
@@ -2385,16 +3067,88 @@ def logical_xor(x1, x2):
|
|
|
2385
3067
|
|
|
2386
3068
|
|
|
2387
3069
|
def corrcoef(x):
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
3070
|
+
x_ov = get_ov_output(x)
|
|
3071
|
+
x_type = x_ov.get_element_type()
|
|
3072
|
+
ov_type = x_type
|
|
3073
|
+
|
|
3074
|
+
if x_type.is_integral():
|
|
3075
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
3076
|
+
x_ov = ov_opset.convert(x_ov, ov_type).output(0)
|
|
3077
|
+
|
|
3078
|
+
const_one = ov_opset.constant(1, dtype=Type.i64).output(0)
|
|
3079
|
+
const_two = ov_opset.constant(2, dtype=ov_type).output(0)
|
|
3080
|
+
|
|
3081
|
+
mean = ov_opset.reduce_mean(x_ov, const_one, True).output(0)
|
|
3082
|
+
x_ov = ov_opset.subtract(x_ov, mean).output(0)
|
|
3083
|
+
|
|
3084
|
+
cov = ov_opset.matmul(x_ov, x_ov, False, True).output(0)
|
|
3085
|
+
xsqr = ov_opset.power(x_ov, const_two).output(0)
|
|
3086
|
+
xvar = ov_opset.reduce_sum(xsqr, const_one, True).output(0)
|
|
3087
|
+
xstd = ov_opset.sqrt(xvar).output(0)
|
|
3088
|
+
|
|
3089
|
+
den = ov_opset.matmul(xstd, xstd, False, True).output(0)
|
|
3090
|
+
|
|
3091
|
+
result = ov_opset.divide(cov, den).output(0)
|
|
3092
|
+
|
|
3093
|
+
return OpenVINOKerasTensor(result)
|
|
2391
3094
|
|
|
2392
3095
|
|
|
2393
3096
|
def correlate(x1, x2, mode="valid"):
|
|
2394
|
-
|
|
2395
|
-
|
|
3097
|
+
x1 = get_ov_output(x1)
|
|
3098
|
+
x2 = get_ov_output(x2)
|
|
3099
|
+
x1_type = x1.get_element_type()
|
|
3100
|
+
x2_type = x2.get_element_type()
|
|
3101
|
+
x1_type = ov_to_keras_type(x1_type)
|
|
3102
|
+
x2_type = ov_to_keras_type(x2_type)
|
|
3103
|
+
result_type = dtypes.result_type(x1_type, x2_type, float)
|
|
3104
|
+
|
|
3105
|
+
result_type = OPENVINO_DTYPES[result_type]
|
|
3106
|
+
x1 = ov_opset.convert(x1, result_type).output(0)
|
|
3107
|
+
x2 = ov_opset.convert(x2, result_type).output(0)
|
|
3108
|
+
|
|
3109
|
+
shape_filter = ov_opset.shape_of(x2, Type.i64).output(0)
|
|
3110
|
+
const_two = ov_opset.constant(2, Type.f64).output(0)
|
|
3111
|
+
const_one = ov_opset.constant(1, Type.i64).output(0)
|
|
3112
|
+
const_zero = ov_opset.constant(0, result_type).output(0)
|
|
3113
|
+
shape_filter_minus_one = ov_opset.subtract(shape_filter, const_one).output(
|
|
3114
|
+
0
|
|
2396
3115
|
)
|
|
2397
3116
|
|
|
3117
|
+
# padding x1
|
|
3118
|
+
if mode == "valid":
|
|
3119
|
+
pass
|
|
3120
|
+
|
|
3121
|
+
elif mode == "same":
|
|
3122
|
+
shape_minus_one_float = ov_opset.convert(
|
|
3123
|
+
shape_filter_minus_one, Type.f64
|
|
3124
|
+
).output(0)
|
|
3125
|
+
|
|
3126
|
+
right = ov_opset.divide(shape_minus_one_float, const_two).output(0)
|
|
3127
|
+
left = ov_opset.ceil(right).output(0)
|
|
3128
|
+
right = ov_opset.floor(right).output(0)
|
|
3129
|
+
left = ov_opset.convert(left, Type.i64).output(0)
|
|
3130
|
+
right = ov_opset.convert(right, Type.i64).output(0)
|
|
3131
|
+
x1 = ov_opset.pad(x1, left, right, "constant", const_zero).output(0)
|
|
3132
|
+
|
|
3133
|
+
elif mode == "full":
|
|
3134
|
+
pad = shape_filter_minus_one
|
|
3135
|
+
x1 = ov_opset.pad(x1, pad, pad, "constant", const_zero).output(0)
|
|
3136
|
+
|
|
3137
|
+
else:
|
|
3138
|
+
raise ValueError(
|
|
3139
|
+
f"mode: {mode} not available chose from valid, same, full."
|
|
3140
|
+
)
|
|
3141
|
+
|
|
3142
|
+
axes = ov_opset.constant([0, 1], dtype=Type.i64).output(0)
|
|
3143
|
+
x2 = ov_opset.unsqueeze(x2, axes).output(0)
|
|
3144
|
+
x1 = ov_opset.unsqueeze(x1, axes).output(0)
|
|
3145
|
+
|
|
3146
|
+
result = ov_opset.convolution(x1, x2, [1], [0], [0], [1]).output(0)
|
|
3147
|
+
|
|
3148
|
+
result = ov_opset.squeeze(result, axes).output(0)
|
|
3149
|
+
|
|
3150
|
+
return OpenVINOKerasTensor(result)
|
|
3151
|
+
|
|
2398
3152
|
|
|
2399
3153
|
def select(condlist, choicelist, default=0):
|
|
2400
3154
|
raise NotImplementedError("`select` is not supported with openvino backend")
|