keras-nightly 3.12.0.dev2025092403__py3-none-any.whl → 3.14.0.dev2026010104__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/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 +12 -0
- keras/callbacks/__init__.py +3 -0
- keras/distillation/__init__.py +16 -0
- keras/distribution/__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 +12 -0
- keras/src/applications/imagenet_utils.py +4 -1
- keras/src/backend/common/backend_utils.py +30 -6
- keras/src/backend/common/dtypes.py +1 -1
- keras/src/backend/common/name_scope.py +2 -1
- keras/src/backend/common/variables.py +33 -16
- 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 +485 -20
- keras/src/backend/jax/numpy.py +92 -23
- keras/src/backend/jax/optimizer.py +3 -2
- keras/src/backend/jax/trainer.py +14 -2
- keras/src/backend/numpy/linalg.py +4 -0
- keras/src/backend/numpy/nn.py +313 -2
- keras/src/backend/numpy/numpy.py +76 -7
- 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 +1030 -185
- keras/src/backend/openvino/random.py +7 -14
- 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 +264 -54
- 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 +84 -8
- keras/src/callbacks/__init__.py +1 -0
- keras/src/callbacks/callback_list.py +45 -11
- keras/src/callbacks/model_checkpoint.py +5 -0
- keras/src/callbacks/orbax_checkpoint.py +299 -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/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/attention.py +1 -1
- keras/src/layers/attention/multi_head_attention.py +4 -1
- keras/src/layers/core/dense.py +191 -172
- keras/src/layers/core/einsum_dense.py +235 -186
- keras/src/layers/core/embedding.py +83 -93
- keras/src/layers/core/input_layer.py +1 -0
- keras/src/layers/core/reversible_embedding.py +390 -0
- keras/src/layers/input_spec.py +17 -17
- keras/src/layers/layer.py +40 -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/index_lookup.py +19 -1
- keras/src/layers/preprocessing/normalization.py +16 -1
- keras/src/layers/regularization/dropout.py +43 -1
- keras/src/layers/rnn/gru.py +1 -1
- keras/src/layers/rnn/lstm.py +2 -2
- keras/src/layers/rnn/rnn.py +19 -0
- keras/src/layers/rnn/simple_rnn.py +1 -1
- keras/src/losses/loss.py +1 -1
- 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 +156 -27
- keras/src/ops/image.py +184 -3
- keras/src/ops/linalg.py +93 -0
- keras/src/ops/nn.py +268 -2
- keras/src/ops/numpy.py +541 -43
- keras/src/optimizers/adafactor.py +29 -10
- keras/src/optimizers/base_optimizer.py +22 -3
- keras/src/optimizers/loss_scale_optimizer.py +51 -18
- keras/src/optimizers/muon.py +65 -31
- keras/src/optimizers/schedules/learning_rate_schedule.py +4 -3
- keras/src/quantizers/__init__.py +12 -1
- keras/src/quantizers/gptq.py +8 -6
- keras/src/quantizers/gptq_config.py +36 -1
- keras/src/quantizers/gptq_core.py +150 -78
- keras/src/quantizers/quantization_config.py +232 -0
- keras/src/quantizers/quantizers.py +114 -38
- keras/src/quantizers/utils.py +23 -0
- keras/src/random/seed_generator.py +4 -2
- keras/src/saving/file_editor.py +81 -6
- 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/trainers/compile_utils.py +14 -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 +187 -36
- keras/src/utils/module_utils.py +18 -0
- keras/src/utils/progbar.py +10 -12
- keras/src/utils/rng_utils.py +9 -1
- keras/src/version.py +1 -1
- {keras_nightly-3.12.0.dev2025092403.dist-info → keras_nightly-3.14.0.dev2026010104.dist-info}/METADATA +16 -6
- {keras_nightly-3.12.0.dev2025092403.dist-info → keras_nightly-3.14.0.dev2026010104.dist-info}/RECORD +133 -116
- {keras_nightly-3.12.0.dev2025092403.dist-info → keras_nightly-3.14.0.dev2026010104.dist-info}/WHEEL +0 -0
- {keras_nightly-3.12.0.dev2025092403.dist-info → keras_nightly-3.14.0.dev2026010104.dist-info}/top_level.txt +0 -0
|
@@ -76,25 +76,81 @@ def multiply(x1, x2):
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def mean(x, axis=None, keepdims=False):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
x_ov = get_ov_output(x)
|
|
80
|
+
x_type = x_ov.get_element_type()
|
|
81
|
+
|
|
82
|
+
was_axis_none = axis is None
|
|
83
|
+
x_resolved, axis_resolved = _resolve_axis(x_ov, axis)
|
|
84
|
+
|
|
85
|
+
if axis_resolved is None:
|
|
86
|
+
return OpenVINOKerasTensor(x_ov)
|
|
87
|
+
|
|
88
|
+
if x_type.is_integral():
|
|
89
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
90
|
+
x_resolved = ov_opset.convert(x_resolved, ov_type).output(0)
|
|
91
|
+
|
|
92
|
+
result = ov_opset.reduce_mean(x_resolved, axis_resolved, keepdims).output(0)
|
|
93
|
+
|
|
94
|
+
if keepdims and was_axis_none:
|
|
95
|
+
rank = x.get_partial_shape().rank.get_length()
|
|
96
|
+
result_shape = [1] * rank
|
|
97
|
+
result = ov_opset.reshape(
|
|
98
|
+
result,
|
|
99
|
+
ov_opset.constant(result_shape, Type.i32).output(0),
|
|
100
|
+
False,
|
|
101
|
+
).output(0)
|
|
102
|
+
|
|
103
|
+
return OpenVINOKerasTensor(result)
|
|
87
104
|
|
|
88
105
|
|
|
89
106
|
def max(x, axis=None, keepdims=False, initial=None):
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
107
|
+
return _compute_extrema(x, "max", axis, keepdims, initial)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _compute_extrema(x, operation, axis=None, keepdims=False, initial=None):
|
|
111
|
+
if operation == "min":
|
|
112
|
+
reduction_op = ov_opset.reduce_min
|
|
113
|
+
elementwise_op = ov_opset.minimum
|
|
114
|
+
elif operation == "max":
|
|
115
|
+
reduction_op = ov_opset.reduce_max
|
|
116
|
+
elementwise_op = ov_opset.maximum
|
|
117
|
+
else:
|
|
118
|
+
raise ValueError(
|
|
119
|
+
f"Operation must be 'min' or 'max', received {operation}"
|
|
120
|
+
)
|
|
121
|
+
|
|
93
122
|
x = get_ov_output(x)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
123
|
+
x_type = x.get_element_type()
|
|
124
|
+
x_for_rank = x
|
|
125
|
+
|
|
126
|
+
is_bool = x_type == Type.boolean
|
|
127
|
+
if is_bool:
|
|
128
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
129
|
+
x_type = Type.i32
|
|
130
|
+
|
|
131
|
+
if isinstance(axis, tuple) and len(axis) == 0:
|
|
132
|
+
return OpenVINOKerasTensor(x)
|
|
133
|
+
|
|
134
|
+
was_axis_none = axis is None
|
|
135
|
+
x, axis = _resolve_axis(x, axis)
|
|
136
|
+
|
|
137
|
+
result = reduction_op(x, axis, keepdims).output(0)
|
|
138
|
+
|
|
139
|
+
if initial is not None:
|
|
140
|
+
initial_tensor = ov_opset.constant(initial, x_type).output(0)
|
|
141
|
+
result = elementwise_op(result, initial_tensor).output(0)
|
|
142
|
+
|
|
143
|
+
if keepdims and was_axis_none:
|
|
144
|
+
orig_shape = ov_opset.shape_of(x_for_rank, Type.i32).output(0)
|
|
145
|
+
orig_rank_shape = ov_opset.shape_of(orig_shape, Type.i32).output(0)
|
|
146
|
+
one = ov_opset.constant(1, Type.i32).output(0)
|
|
147
|
+
result_shape = ov_opset.broadcast(one, orig_rank_shape).output(0)
|
|
148
|
+
result = ov_opset.reshape(result, result_shape, False).output(0)
|
|
149
|
+
|
|
150
|
+
if is_bool:
|
|
151
|
+
result = ov_opset.convert(result, Type.boolean).output(0)
|
|
152
|
+
|
|
153
|
+
return OpenVINOKerasTensor(result)
|
|
98
154
|
|
|
99
155
|
|
|
100
156
|
def ones(shape, dtype=None):
|
|
@@ -125,6 +181,9 @@ def zeros(shape, dtype=None):
|
|
|
125
181
|
|
|
126
182
|
def absolute(x):
|
|
127
183
|
x = get_ov_output(x)
|
|
184
|
+
x_type = x.get_element_type()
|
|
185
|
+
if x_type == Type.boolean:
|
|
186
|
+
return OpenVINOKerasTensor(x)
|
|
128
187
|
return OpenVINOKerasTensor(ov_opset.absolute(x).output(0))
|
|
129
188
|
|
|
130
189
|
|
|
@@ -135,11 +194,10 @@ def abs(x):
|
|
|
135
194
|
|
|
136
195
|
def all(x, axis=None, keepdims=False):
|
|
137
196
|
x = get_ov_output(x)
|
|
197
|
+
x, axis = _resolve_axis(x, axis)
|
|
138
198
|
if axis is None:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
axis = 0
|
|
142
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
199
|
+
return OpenVINOKerasTensor(x)
|
|
200
|
+
x = ov_opset.convert(x, Type.boolean).output(0)
|
|
143
201
|
return OpenVINOKerasTensor(
|
|
144
202
|
ov_opset.reduce_logical_and(x, axis, keepdims).output(0)
|
|
145
203
|
)
|
|
@@ -151,28 +209,21 @@ def angle(x):
|
|
|
151
209
|
|
|
152
210
|
def any(x, axis=None, keepdims=False):
|
|
153
211
|
x = get_ov_output(x)
|
|
212
|
+
x, axis = _resolve_axis(x, axis)
|
|
154
213
|
if axis is None:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
axis = 0
|
|
158
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
214
|
+
return OpenVINOKerasTensor(x)
|
|
215
|
+
x = ov_opset.convert(x, Type.boolean).output(0)
|
|
159
216
|
return OpenVINOKerasTensor(
|
|
160
217
|
ov_opset.reduce_logical_or(x, axis, keepdims).output(0)
|
|
161
218
|
)
|
|
162
219
|
|
|
163
220
|
|
|
164
221
|
def amax(x, axis=None, keepdims=False):
|
|
165
|
-
if axis == () or axis == []:
|
|
166
|
-
return x
|
|
167
222
|
x = get_ov_output(x)
|
|
168
223
|
x_type = x.get_element_type()
|
|
224
|
+
x, axis = _resolve_axis(x, axis)
|
|
169
225
|
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)
|
|
226
|
+
return OpenVINOKerasTensor(x)
|
|
176
227
|
if x_type == Type.boolean:
|
|
177
228
|
return OpenVINOKerasTensor(
|
|
178
229
|
ov_opset.reduce_logical_or(x, axis, keepdims).output(0)
|
|
@@ -181,10 +232,21 @@ def amax(x, axis=None, keepdims=False):
|
|
|
181
232
|
|
|
182
233
|
|
|
183
234
|
def amin(x, axis=None, keepdims=False):
|
|
184
|
-
if axis == () or axis == []:
|
|
185
|
-
return x
|
|
186
235
|
x = get_ov_output(x)
|
|
187
236
|
x_type = x.get_element_type()
|
|
237
|
+
x, axis = _resolve_axis(x, axis)
|
|
238
|
+
if axis is None:
|
|
239
|
+
return OpenVINOKerasTensor(x)
|
|
240
|
+
if x_type == Type.boolean:
|
|
241
|
+
return OpenVINOKerasTensor(
|
|
242
|
+
ov_opset.reduce_logical_and(x, axis, keepdims).output(0)
|
|
243
|
+
)
|
|
244
|
+
return OpenVINOKerasTensor(ov_opset.reduce_min(x, axis, keepdims).output(0))
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _resolve_axis(x, axis):
|
|
248
|
+
if axis == () or axis == []:
|
|
249
|
+
return x, None
|
|
188
250
|
if axis is None:
|
|
189
251
|
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
190
252
|
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
@@ -192,11 +254,18 @@ def amin(x, axis=None, keepdims=False):
|
|
|
192
254
|
if isinstance(axis, tuple):
|
|
193
255
|
axis = list(axis)
|
|
194
256
|
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
257
|
+
return x, axis
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def _upcast_type_if_needed(x):
|
|
261
|
+
x_type = x.get_element_type()
|
|
195
262
|
if x_type == Type.boolean:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
)
|
|
199
|
-
|
|
263
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
264
|
+
elif x_type in (Type.i8, Type.i16):
|
|
265
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
266
|
+
elif x_type in (Type.u8, Type.u16):
|
|
267
|
+
x = ov_opset.convert(x, Type.u32).output(0)
|
|
268
|
+
return x
|
|
200
269
|
|
|
201
270
|
|
|
202
271
|
def append(x1, x2, axis=None):
|
|
@@ -210,7 +279,7 @@ def append(x1, x2, axis=None):
|
|
|
210
279
|
return OpenVINOKerasTensor(ov_opset.concat([x1, x2], axis).output(0))
|
|
211
280
|
|
|
212
281
|
|
|
213
|
-
def arange(start, stop=None, step=
|
|
282
|
+
def arange(start, stop=None, step=None, dtype=None):
|
|
214
283
|
if stop is None:
|
|
215
284
|
start, stop = get_ov_output(0), get_ov_output(start)
|
|
216
285
|
else:
|
|
@@ -439,6 +508,10 @@ def array(x, dtype=None):
|
|
|
439
508
|
return np.array(x)
|
|
440
509
|
|
|
441
510
|
|
|
511
|
+
def view(x, dtype=None):
|
|
512
|
+
raise NotImplementedError("`view` is not supported with openvino backend")
|
|
513
|
+
|
|
514
|
+
|
|
442
515
|
def average(x, axis=None, weights=None):
|
|
443
516
|
x = get_ov_output(x)
|
|
444
517
|
if weights is not None:
|
|
@@ -472,22 +545,79 @@ def average(x, axis=None, weights=None):
|
|
|
472
545
|
|
|
473
546
|
|
|
474
547
|
def bartlett(x):
|
|
475
|
-
|
|
476
|
-
|
|
548
|
+
x = get_ov_output(x)
|
|
549
|
+
zero_const = ov_opset.constant(0, Type.i64)
|
|
550
|
+
one_const = ov_opset.constant(1, Type.i64)
|
|
551
|
+
two_const = ov_opset.constant(2, Type.i64)
|
|
552
|
+
two_const_f64 = ov_opset.constant(2.0, Type.f64)
|
|
553
|
+
if x.get_element_type() != Type.i64:
|
|
554
|
+
x = ov_opset.convert(x, Type.i64)
|
|
555
|
+
half = ov_opset.convert(
|
|
556
|
+
ov_opset.divide(ov_opset.subtract(x, one_const), two_const), Type.f64
|
|
557
|
+
)
|
|
558
|
+
n = ov_opset.range(zero_const, x, one_const, Type.f64)
|
|
559
|
+
condition = ov_opset.less_equal(n, half)
|
|
560
|
+
first_half = ov_opset.divide(
|
|
561
|
+
ov_opset.multiply(two_const_f64, n),
|
|
562
|
+
ov_opset.convert(ov_opset.subtract(x, one_const), Type.f64),
|
|
477
563
|
)
|
|
564
|
+
second_half = ov_opset.subtract(two_const_f64, first_half)
|
|
565
|
+
window = ov_opset.select(condition, first_half, second_half)
|
|
566
|
+
window = ov_opset.convert(window, OPENVINO_DTYPES[config.floatx()]).output(
|
|
567
|
+
0
|
|
568
|
+
)
|
|
569
|
+
return OpenVINOKerasTensor(window)
|
|
478
570
|
|
|
479
571
|
|
|
480
572
|
def hamming(x):
|
|
481
|
-
|
|
482
|
-
|
|
573
|
+
m = get_ov_output(x)
|
|
574
|
+
|
|
575
|
+
m_i64 = (
|
|
576
|
+
m if m.get_element_type() == Type.i64 else ov_opset.convert(m, Type.i64)
|
|
483
577
|
)
|
|
484
578
|
|
|
579
|
+
start = ov_opset.constant(0, Type.i64)
|
|
580
|
+
step = ov_opset.constant(1, Type.i64)
|
|
581
|
+
n = ov_opset.range(start, m_i64, step, Type.f64)
|
|
485
582
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
583
|
+
one_i64 = ov_opset.constant(1, Type.i64)
|
|
584
|
+
denom_i64 = ov_opset.subtract(m_i64, one_i64)
|
|
585
|
+
denom = ov_opset.convert(denom_i64, Type.f64)
|
|
586
|
+
|
|
587
|
+
two_pi = ov_opset.constant(2.0 * np.pi, Type.f64)
|
|
588
|
+
two_pi_over_m_minus_1 = ov_opset.divide(two_pi, denom)
|
|
589
|
+
|
|
590
|
+
x = ov_opset.multiply(two_pi_over_m_minus_1, n)
|
|
591
|
+
c = ov_opset.cos(x)
|
|
592
|
+
|
|
593
|
+
# 0.54 - 0.46 * cos(...)
|
|
594
|
+
a = ov_opset.constant(0.54, Type.f64)
|
|
595
|
+
b = ov_opset.constant(0.46, Type.f64)
|
|
596
|
+
hamming_window = ov_opset.subtract(a, ov_opset.multiply(b, c))
|
|
597
|
+
hamming_window = ov_opset.convert(
|
|
598
|
+
hamming_window, OPENVINO_DTYPES[config.floatx()]
|
|
489
599
|
)
|
|
490
600
|
|
|
601
|
+
return OpenVINOKerasTensor(hamming_window.output(0))
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
def heaviside(x1, x2):
|
|
605
|
+
x1 = get_ov_output(x1)
|
|
606
|
+
x_type = x1.get_element_type()
|
|
607
|
+
x2 = get_ov_output(x2, x_type)
|
|
608
|
+
|
|
609
|
+
zero_scalar = ov_opset.constant(0, x_type).output(0)
|
|
610
|
+
one_scalar = ov_opset.constant(1, x_type).output(0)
|
|
611
|
+
|
|
612
|
+
neg = ov_opset.less(x1, zero_scalar).output(0)
|
|
613
|
+
pos = ov_opset.greater(x1, zero_scalar).output(0)
|
|
614
|
+
eq = ov_opset.equal(x1, zero_scalar).output(0)
|
|
615
|
+
|
|
616
|
+
x = ov_opset.select(neg, zero_scalar, x1).output(0)
|
|
617
|
+
x = ov_opset.select(pos, one_scalar, x).output(0)
|
|
618
|
+
x = ov_opset.select(eq, x2, x).output(0)
|
|
619
|
+
return OpenVINOKerasTensor(x)
|
|
620
|
+
|
|
491
621
|
|
|
492
622
|
def kaiser(x, beta):
|
|
493
623
|
raise NotImplementedError("`kaiser` is not supported with openvino backend")
|
|
@@ -539,9 +669,30 @@ def bincount(x, weights=None, minlength=0, sparse=False):
|
|
|
539
669
|
|
|
540
670
|
|
|
541
671
|
def blackman(x):
|
|
542
|
-
|
|
543
|
-
|
|
672
|
+
x = get_ov_output(x)
|
|
673
|
+
zero_const = ov_opset.constant(0, Type.i64)
|
|
674
|
+
one_const = ov_opset.constant(1, Type.i64)
|
|
675
|
+
two_pi = ov_opset.constant(2.0 * np.pi, Type.f64)
|
|
676
|
+
term_1 = ov_opset.constant(0.42, Type.f64)
|
|
677
|
+
term_2 = ov_opset.constant(0.5, Type.f64)
|
|
678
|
+
term_3 = ov_opset.constant(0.08, Type.f64)
|
|
679
|
+
if x.get_element_type() != Type.i64:
|
|
680
|
+
x = ov_opset.convert(x, Type.i64)
|
|
681
|
+
n = ov_opset.range(zero_const, x, one_const, Type.f64)
|
|
682
|
+
n_minus_1 = ov_opset.subtract(
|
|
683
|
+
ov_opset.convert(x, Type.f64), ov_opset.constant(1.0, Type.f64)
|
|
684
|
+
).output(0)
|
|
685
|
+
angle_2pi = ov_opset.divide(ov_opset.multiply(two_pi, n), n_minus_1)
|
|
686
|
+
angle_4pi = ov_opset.multiply(angle_2pi, ov_opset.constant(2.0, Type.f64))
|
|
687
|
+
cos_2pi = ov_opset.cos(angle_2pi)
|
|
688
|
+
cos_4pi = ov_opset.cos(angle_4pi)
|
|
689
|
+
term_2_final = ov_opset.multiply(term_2, cos_2pi)
|
|
690
|
+
term_3_final = ov_opset.multiply(term_3, cos_4pi)
|
|
691
|
+
window = ov_opset.add(ov_opset.subtract(term_1, term_2_final), term_3_final)
|
|
692
|
+
window = ov_opset.convert(window, OPENVINO_DTYPES[config.floatx()]).output(
|
|
693
|
+
0
|
|
544
694
|
)
|
|
695
|
+
return OpenVINOKerasTensor(window)
|
|
545
696
|
|
|
546
697
|
|
|
547
698
|
def broadcast_to(x, shape):
|
|
@@ -559,11 +710,18 @@ def cbrt(x):
|
|
|
559
710
|
|
|
560
711
|
def ceil(x):
|
|
561
712
|
x = get_ov_output(x)
|
|
562
|
-
|
|
713
|
+
x_type = x.get_element_type()
|
|
714
|
+
if x_type.is_integral():
|
|
715
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()]).output(0)
|
|
716
|
+
ceiling = ov_opset.ceil(x).output(0)
|
|
717
|
+
return OpenVINOKerasTensor(ceiling)
|
|
563
718
|
|
|
564
719
|
|
|
565
720
|
def clip(x, x_min, x_max):
|
|
566
721
|
x = get_ov_output(x)
|
|
722
|
+
x_type = x.get_element_type()
|
|
723
|
+
if x_type == Type.boolean:
|
|
724
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
567
725
|
x_min = get_ov_output(x_min, x.get_element_type())
|
|
568
726
|
x_max = get_ov_output(x_max, x.get_element_type())
|
|
569
727
|
clip_by_min = ov_opset.maximum(x, x_min).output(0)
|
|
@@ -619,15 +777,9 @@ def count_nonzero(x, axis=None):
|
|
|
619
777
|
zero_constant = ov_opset.convert_like(zero_constant, x)
|
|
620
778
|
x = ov_opset.not_equal(x, zero_constant).output(0)
|
|
621
779
|
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 == []:
|
|
780
|
+
x, axis = _resolve_axis(x, axis)
|
|
781
|
+
if not axis:
|
|
629
782
|
return OpenVINOKerasTensor(x)
|
|
630
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
631
783
|
return OpenVINOKerasTensor(ov_opset.reduce_sum(x, axis, False).output(0))
|
|
632
784
|
|
|
633
785
|
|
|
@@ -646,11 +798,9 @@ def cumsum(x, axis=None, dtype=None):
|
|
|
646
798
|
if dtype is not None:
|
|
647
799
|
ov_type = OPENVINO_DTYPES[standardize_dtype(dtype)]
|
|
648
800
|
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)
|
|
801
|
+
x, axis = _resolve_axis(x, axis)
|
|
802
|
+
if x.get_element_type() == Type.boolean:
|
|
803
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
654
804
|
return OpenVINOKerasTensor(ov_opset.cumsum(x, axis).output(0))
|
|
655
805
|
|
|
656
806
|
|
|
@@ -676,7 +826,70 @@ def deg2rad(x):
|
|
|
676
826
|
|
|
677
827
|
|
|
678
828
|
def diag(x, k=0):
|
|
679
|
-
|
|
829
|
+
x = get_ov_output(x)
|
|
830
|
+
x_shape = x.get_partial_shape()
|
|
831
|
+
rank = x_shape.rank.get_length()
|
|
832
|
+
|
|
833
|
+
if rank == 1:
|
|
834
|
+
N_dim = x_shape[0]
|
|
835
|
+
if not N_dim.is_static:
|
|
836
|
+
raise ValueError(
|
|
837
|
+
"diag requires input with static shape for 1D input."
|
|
838
|
+
)
|
|
839
|
+
N = N_dim.get_length()
|
|
840
|
+
output_size = N + np.abs(k)
|
|
841
|
+
out_shape = ov_opset.constant(
|
|
842
|
+
[output_size, output_size], dtype=Type.i32
|
|
843
|
+
).output(0)
|
|
844
|
+
zeros_const = ov_opset.constant(0, x.get_element_type()).output(0)
|
|
845
|
+
diag_matrix = ov_opset.broadcast(zeros_const, out_shape)
|
|
846
|
+
|
|
847
|
+
indices = []
|
|
848
|
+
if k >= 0:
|
|
849
|
+
for i in range(N):
|
|
850
|
+
indices.append([i, i + k])
|
|
851
|
+
else:
|
|
852
|
+
for i in range(N):
|
|
853
|
+
indices.append([i - k, i])
|
|
854
|
+
|
|
855
|
+
indices = np.array(indices, dtype=np.int32)
|
|
856
|
+
indices_const = ov_opset.constant(indices, dtype=Type.i32).output(0)
|
|
857
|
+
updated = ov_opset.scatter_nd_update(diag_matrix, indices_const, x)
|
|
858
|
+
return OpenVINOKerasTensor(updated.output(0))
|
|
859
|
+
|
|
860
|
+
elif rank == 2:
|
|
861
|
+
M_dim = x_shape[0]
|
|
862
|
+
N_dim = x_shape[1]
|
|
863
|
+
if not M_dim.is_static or not N_dim.is_static:
|
|
864
|
+
raise ValueError(
|
|
865
|
+
"diag requires input with static shape for 2D input."
|
|
866
|
+
)
|
|
867
|
+
M = M_dim.get_length()
|
|
868
|
+
N = N_dim.get_length()
|
|
869
|
+
|
|
870
|
+
if k >= 0:
|
|
871
|
+
L = np.minimum(M, N - k) if (N - k) > 0 else 0
|
|
872
|
+
indices = [[i, i + k] for i in range(L)]
|
|
873
|
+
else:
|
|
874
|
+
L = np.minimum(M + k, N) if (M + k) > 0 else 0
|
|
875
|
+
indices = [[i - k, i] for i in range(L)]
|
|
876
|
+
|
|
877
|
+
if L <= 0:
|
|
878
|
+
keras_dtype = ov_to_keras_type(x.get_element_type())
|
|
879
|
+
np_dtype = np.dtype(keras_dtype)
|
|
880
|
+
empty_np = np.empty((0,), dtype=np_dtype)
|
|
881
|
+
empty_const = ov_opset.constant(
|
|
882
|
+
empty_np, x.get_element_type()
|
|
883
|
+
).output(0)
|
|
884
|
+
return OpenVINOKerasTensor(empty_const)
|
|
885
|
+
|
|
886
|
+
indices = np.array(indices, dtype=np.int32)
|
|
887
|
+
indices_const = ov_opset.constant(indices, dtype=Type.i32).output(0)
|
|
888
|
+
diag_vec = ov_opset.gather_nd(x, indices_const)
|
|
889
|
+
return OpenVINOKerasTensor(diag_vec.output(0))
|
|
890
|
+
|
|
891
|
+
else:
|
|
892
|
+
raise ValueError("diag supports only 1D or 2D tensors")
|
|
680
893
|
|
|
681
894
|
|
|
682
895
|
def diagonal(x, offset=0, axis1=0, axis2=1):
|
|
@@ -759,9 +972,30 @@ def diff(a, n=1, axis=-1):
|
|
|
759
972
|
|
|
760
973
|
|
|
761
974
|
def digitize(x, bins):
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
)
|
|
975
|
+
x_node = get_ov_output(x)
|
|
976
|
+
|
|
977
|
+
if isinstance(bins, OpenVINOKerasTensor):
|
|
978
|
+
bins_node = get_ov_output(bins)
|
|
979
|
+
else:
|
|
980
|
+
bins_np = np.asarray(bins)
|
|
981
|
+
if bins_np.ndim != 1:
|
|
982
|
+
raise ValueError("`bins` must be 1-D array-like")
|
|
983
|
+
bins_node = ov_opset.constant(bins_np).output(0)
|
|
984
|
+
|
|
985
|
+
x_node, bins_node = _align_operand_types(x_node, bins_node, "digitize()")
|
|
986
|
+
|
|
987
|
+
if x_node.get_element_type() == Type.boolean:
|
|
988
|
+
x_node = ov_opset.convert(x_node, Type.f32).output(0)
|
|
989
|
+
bins_node = ov_opset.convert(bins_node, Type.f32).output(0)
|
|
990
|
+
|
|
991
|
+
result = ov_opset.bucketize(
|
|
992
|
+
x_node,
|
|
993
|
+
bins_node,
|
|
994
|
+
output_type=Type.i32,
|
|
995
|
+
with_right_bound=False,
|
|
996
|
+
).output(0)
|
|
997
|
+
|
|
998
|
+
return OpenVINOKerasTensor(result)
|
|
765
999
|
|
|
766
1000
|
|
|
767
1001
|
def dot(x1, x2):
|
|
@@ -791,6 +1025,10 @@ def empty(shape, dtype=None):
|
|
|
791
1025
|
return OpenVINOKerasTensor(empty_tensor)
|
|
792
1026
|
|
|
793
1027
|
|
|
1028
|
+
def empty_like(x, dtype=None):
|
|
1029
|
+
return zeros_like(x, dtype=dtype)
|
|
1030
|
+
|
|
1031
|
+
|
|
794
1032
|
def equal(x1, x2):
|
|
795
1033
|
element_type = None
|
|
796
1034
|
if isinstance(x1, OpenVINOKerasTensor):
|
|
@@ -833,11 +1071,40 @@ def expm1(x):
|
|
|
833
1071
|
|
|
834
1072
|
|
|
835
1073
|
def flip(x, axis=None):
|
|
836
|
-
|
|
1074
|
+
x_node = get_ov_output(x)
|
|
1075
|
+
ndim = x.ndim
|
|
1076
|
+
if ndim is None:
|
|
1077
|
+
raise ValueError(
|
|
1078
|
+
"The `flip` operation does not support tensors with dynamic rank"
|
|
1079
|
+
"for the OpenVINO backend."
|
|
1080
|
+
)
|
|
1081
|
+
if axis is None:
|
|
1082
|
+
axis = list(range(ndim))
|
|
1083
|
+
elif isinstance(axis, int):
|
|
1084
|
+
axis = [axis]
|
|
1085
|
+
axis = [a + ndim if a < 0 else a for a in axis]
|
|
1086
|
+
begin = [0] * ndim
|
|
1087
|
+
end = [0] * ndim
|
|
1088
|
+
strides = [1] * ndim
|
|
1089
|
+
for a in axis:
|
|
1090
|
+
strides[a] = -1
|
|
1091
|
+
all_ones_mask = [1] * ndim
|
|
1092
|
+
result = ov_opset.strided_slice(
|
|
1093
|
+
data=x_node,
|
|
1094
|
+
begin=begin,
|
|
1095
|
+
end=end,
|
|
1096
|
+
strides=strides,
|
|
1097
|
+
begin_mask=all_ones_mask,
|
|
1098
|
+
end_mask=all_ones_mask,
|
|
1099
|
+
)
|
|
1100
|
+
return OpenVINOKerasTensor(result.output(0))
|
|
837
1101
|
|
|
838
1102
|
|
|
839
1103
|
def floor(x):
|
|
840
1104
|
x = get_ov_output(x)
|
|
1105
|
+
x_type = x.get_element_type()
|
|
1106
|
+
if x_type.is_integral():
|
|
1107
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()])
|
|
841
1108
|
return OpenVINOKerasTensor(ov_opset.floor(x).output(0))
|
|
842
1109
|
|
|
843
1110
|
|
|
@@ -950,25 +1217,70 @@ def isclose(x1, x2, rtol=1e-5, atol=1e-8, equal_nan=False):
|
|
|
950
1217
|
|
|
951
1218
|
|
|
952
1219
|
def isfinite(x):
|
|
953
|
-
|
|
954
|
-
|
|
1220
|
+
# NOTE: openvino has an is_finite operation but it does not properly
|
|
1221
|
+
# catch np.inf and -np.inf as not finite values. Hence we bootstrap here. If
|
|
1222
|
+
# that ever changes, we could simplify this to just call that operation.
|
|
1223
|
+
inf_values = get_ov_output(isinf(x))
|
|
1224
|
+
nan_values = get_ov_output(isnan(x))
|
|
1225
|
+
all_non_finite_values = ov_opset.logical_or(inf_values, nan_values).output(
|
|
1226
|
+
0
|
|
1227
|
+
)
|
|
1228
|
+
is_finite = ov_opset.logical_not(all_non_finite_values).output(0)
|
|
1229
|
+
return OpenVINOKerasTensor(is_finite)
|
|
955
1230
|
|
|
956
1231
|
|
|
957
1232
|
def isin(x1, x2, assume_unique=False, invert=False):
|
|
958
|
-
|
|
1233
|
+
x1 = get_ov_output(x1)
|
|
1234
|
+
x2 = get_ov_output(x2)
|
|
1235
|
+
output_shape = ov_opset.shape_of(x1).output(0)
|
|
1236
|
+
x1, x2 = _align_operand_types(x1, x2, "isin()")
|
|
1237
|
+
|
|
1238
|
+
minus_one = ov_opset.constant([-1], dtype=Type.i64)
|
|
1239
|
+
x1 = ov_opset.reshape(x1, minus_one, special_zero=False).output(0)
|
|
1240
|
+
x2 = ov_opset.reshape(x2, minus_one, special_zero=False).output(0)
|
|
1241
|
+
if not assume_unique:
|
|
1242
|
+
x2 = ov_opset.unique(x2).output(0)
|
|
1243
|
+
x1 = ov_opset.unsqueeze(x1, 1).output(0)
|
|
1244
|
+
x2 = ov_opset.unsqueeze(x2, 0).output(0)
|
|
1245
|
+
cmp = ov_opset.equal(x1, x2).output(0)
|
|
1246
|
+
result_flat = ov_opset.reduce_logical_or(cmp, 1).output(0)
|
|
1247
|
+
|
|
1248
|
+
if invert:
|
|
1249
|
+
result_flat = ov_opset.logical_not(result_flat).output(0)
|
|
1250
|
+
result = ov_opset.reshape(result_flat, output_shape, False).output(0)
|
|
1251
|
+
return OpenVINOKerasTensor(result)
|
|
959
1252
|
|
|
960
1253
|
|
|
961
1254
|
def isinf(x):
|
|
962
|
-
|
|
963
|
-
|
|
1255
|
+
pos_inf = get_ov_output(isposinf(x))
|
|
1256
|
+
neg_inf = get_ov_output(isneginf(x))
|
|
1257
|
+
inf = ov_opset.logical_or(pos_inf, neg_inf).output(0)
|
|
1258
|
+
return OpenVINOKerasTensor(inf)
|
|
964
1259
|
|
|
965
1260
|
|
|
966
1261
|
def isnan(x):
|
|
967
1262
|
x = get_ov_output(x)
|
|
1263
|
+
x_type = x.get_element_type()
|
|
1264
|
+
if x_type.is_integral():
|
|
1265
|
+
x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()])
|
|
968
1266
|
return OpenVINOKerasTensor(ov_opset.is_nan(x).output(0))
|
|
969
1267
|
|
|
970
1268
|
|
|
971
1269
|
def isneginf(x):
|
|
1270
|
+
return _is_inf(x, pos=False)
|
|
1271
|
+
|
|
1272
|
+
|
|
1273
|
+
def isposinf(x):
|
|
1274
|
+
return _is_inf(x)
|
|
1275
|
+
|
|
1276
|
+
|
|
1277
|
+
def _is_inf(x, pos=True):
|
|
1278
|
+
# NOTE: there is an ov_opset.is_inf but it does not catch
|
|
1279
|
+
# numpy infinite values like np.inf and -np.inf, hence why we have this
|
|
1280
|
+
# if this ever changes in OpenVINO, we can do this instead:
|
|
1281
|
+
# ov_opset.is_inf(x, {"detect_positive": pos, "detect_negative": not pos})
|
|
1282
|
+
# for each infinite sign
|
|
1283
|
+
inf_value = np.inf if pos else -np.inf
|
|
972
1284
|
x = get_ov_output(x)
|
|
973
1285
|
x_type = x.get_element_type()
|
|
974
1286
|
|
|
@@ -981,26 +1293,23 @@ def isneginf(x):
|
|
|
981
1293
|
|
|
982
1294
|
if x_type == Type.bf16:
|
|
983
1295
|
x_f32 = ov_opset.convert(x, Type.f32).output(0)
|
|
984
|
-
|
|
985
|
-
|
|
1296
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
1297
|
+
is_inf = ov_opset.equal(x_f32, inf).output(0)
|
|
986
1298
|
else:
|
|
987
1299
|
if x_type == Type.f16:
|
|
988
|
-
|
|
1300
|
+
inf = ov_opset.constant(inf_value, Type.f16).output(0)
|
|
989
1301
|
elif x_type == Type.f32:
|
|
990
|
-
|
|
1302
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
991
1303
|
elif x_type == Type.f64:
|
|
992
|
-
|
|
1304
|
+
inf = ov_opset.constant(inf_value, Type.f64).output(0)
|
|
993
1305
|
else:
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
return OpenVINOKerasTensor(is_neg_inf)
|
|
1306
|
+
inf = ov_opset.constant(inf_value, Type.f32).output(0)
|
|
1307
|
+
is_inf = ov_opset.equal(x, inf).output(0)
|
|
1308
|
+
return OpenVINOKerasTensor(is_inf)
|
|
998
1309
|
|
|
999
1310
|
|
|
1000
|
-
def
|
|
1001
|
-
raise NotImplementedError(
|
|
1002
|
-
"`isposinf` is not supported with openvino backend"
|
|
1003
|
-
)
|
|
1311
|
+
def isreal(x):
|
|
1312
|
+
raise NotImplementedError("`isreal` is not supported with openvino backend")
|
|
1004
1313
|
|
|
1005
1314
|
|
|
1006
1315
|
def kron(x1, x2):
|
|
@@ -1011,6 +1320,10 @@ def lcm(x1, x2):
|
|
|
1011
1320
|
raise NotImplementedError("`lcm` is not supported with openvino backend")
|
|
1012
1321
|
|
|
1013
1322
|
|
|
1323
|
+
def ldexp(x1, x2):
|
|
1324
|
+
raise NotImplementedError("`ldexp` is not supported with openvino backend")
|
|
1325
|
+
|
|
1326
|
+
|
|
1014
1327
|
def less(x1, x2):
|
|
1015
1328
|
element_type = None
|
|
1016
1329
|
if isinstance(x1, OpenVINOKerasTensor):
|
|
@@ -1038,9 +1351,131 @@ def less_equal(x1, x2):
|
|
|
1038
1351
|
def linspace(
|
|
1039
1352
|
start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0
|
|
1040
1353
|
):
|
|
1041
|
-
|
|
1042
|
-
|
|
1354
|
+
"""Return evenly spaced numbers over a specified interval.
|
|
1355
|
+
|
|
1356
|
+
Supports axis=0 (prepend) and axis=-1 (append). Intermediate axis values are
|
|
1357
|
+
treated as axis=-1.
|
|
1358
|
+
|
|
1359
|
+
If `retstep` is True, also returns the step size between values.
|
|
1360
|
+
|
|
1361
|
+
"""
|
|
1362
|
+
|
|
1363
|
+
start = get_ov_output(start)
|
|
1364
|
+
stop = get_ov_output(stop)
|
|
1365
|
+
|
|
1366
|
+
if hasattr(num, "output") or isinstance(num, OpenVINOKerasTensor):
|
|
1367
|
+
num_tensor = get_ov_output(num)
|
|
1368
|
+
try:
|
|
1369
|
+
if num_tensor.get_node().get_type_name() == "Constant":
|
|
1370
|
+
num_value = num_tensor.get_node().get_vector()[0]
|
|
1371
|
+
num = int(num_value)
|
|
1372
|
+
else:
|
|
1373
|
+
raise NotImplementedError(
|
|
1374
|
+
"Dynamic num values not fully supported"
|
|
1375
|
+
)
|
|
1376
|
+
except Exception as e:
|
|
1377
|
+
raise NotImplementedError(
|
|
1378
|
+
"Could not extract num value from tensor"
|
|
1379
|
+
) from e
|
|
1380
|
+
else:
|
|
1381
|
+
num = int(num)
|
|
1382
|
+
|
|
1383
|
+
if dtype is None:
|
|
1384
|
+
output_type = OPENVINO_DTYPES[config.floatx()]
|
|
1385
|
+
else:
|
|
1386
|
+
output_type = OPENVINO_DTYPES[dtype]
|
|
1387
|
+
|
|
1388
|
+
start = ov_opset.convert(start, output_type).output(0)
|
|
1389
|
+
stop = ov_opset.convert(stop, output_type).output(0)
|
|
1390
|
+
|
|
1391
|
+
if num < 0:
|
|
1392
|
+
raise ValueError("Number of samples, `num`, must be non-negative.")
|
|
1393
|
+
|
|
1394
|
+
if num == 0:
|
|
1395
|
+
empty_shape = ov_opset.constant([0], Type.i32).output(0)
|
|
1396
|
+
result = ov_opset.broadcast(
|
|
1397
|
+
ov_opset.constant(0.0, output_type).output(0), empty_shape
|
|
1398
|
+
).output(0)
|
|
1399
|
+
if retstep:
|
|
1400
|
+
nan_step = ov_opset.constant(np.nan, output_type).output(0)
|
|
1401
|
+
return OpenVINOKerasTensor(result), OpenVINOKerasTensor(nan_step)
|
|
1402
|
+
return OpenVINOKerasTensor(result)
|
|
1403
|
+
|
|
1404
|
+
if num == 1:
|
|
1405
|
+
result_val = start
|
|
1406
|
+
axis_const = ov_opset.constant([axis], Type.i32).output(0)
|
|
1407
|
+
result = ov_opset.unsqueeze(result_val, axis_const).output(0)
|
|
1408
|
+
if retstep:
|
|
1409
|
+
if endpoint:
|
|
1410
|
+
step = ov_opset.constant(np.nan, output_type).output(0)
|
|
1411
|
+
else:
|
|
1412
|
+
step = ov_opset.subtract(stop, start).output(0)
|
|
1413
|
+
return OpenVINOKerasTensor(result), OpenVINOKerasTensor(step)
|
|
1414
|
+
zero_i32 = ov_opset.constant(0, Type.i32).output(0)
|
|
1415
|
+
one_i32 = ov_opset.constant(1, Type.i32).output(0)
|
|
1416
|
+
one_i32_array = ov_opset.constant([1], Type.i32).output(0)
|
|
1417
|
+
|
|
1418
|
+
num_const = ov_opset.constant(num, output_type).output(0)
|
|
1419
|
+
|
|
1420
|
+
if endpoint:
|
|
1421
|
+
divisor = ov_opset.subtract(
|
|
1422
|
+
num_const, ov_opset.constant(1, output_type).output(0)
|
|
1423
|
+
).output(0)
|
|
1424
|
+
else:
|
|
1425
|
+
divisor = num_const
|
|
1426
|
+
|
|
1427
|
+
step = ov_opset.divide(
|
|
1428
|
+
ov_opset.subtract(stop, start).output(0), divisor
|
|
1429
|
+
).output(0)
|
|
1430
|
+
|
|
1431
|
+
indices = ov_opset.range(
|
|
1432
|
+
zero_i32,
|
|
1433
|
+
ov_opset.constant(num, Type.i32).output(0),
|
|
1434
|
+
one_i32,
|
|
1435
|
+
output_type,
|
|
1436
|
+
).output(0)
|
|
1437
|
+
|
|
1438
|
+
start_shape = ov_opset.convert(
|
|
1439
|
+
ov_opset.shape_of(start).output(0), Type.i32
|
|
1440
|
+
).output(0)
|
|
1441
|
+
indices_shape = ov_opset.convert(
|
|
1442
|
+
ov_opset.shape_of(indices).output(0), Type.i32
|
|
1443
|
+
).output(0)
|
|
1444
|
+
|
|
1445
|
+
start_rank = ov_opset.shape_of(start_shape).output(0)
|
|
1446
|
+
ones_for_start = ov_opset.broadcast(one_i32, start_rank).output(0)
|
|
1447
|
+
|
|
1448
|
+
if axis == 0:
|
|
1449
|
+
indices_target_shape = ov_opset.concat(
|
|
1450
|
+
[indices_shape, ones_for_start], 0
|
|
1451
|
+
).output(0)
|
|
1452
|
+
start_target_shape = ov_opset.concat(
|
|
1453
|
+
[one_i32_array, start_shape], 0
|
|
1454
|
+
).output(0)
|
|
1455
|
+
else:
|
|
1456
|
+
indices_target_shape = ov_opset.concat(
|
|
1457
|
+
[ones_for_start, indices_shape], 0
|
|
1458
|
+
).output(0)
|
|
1459
|
+
start_target_shape = ov_opset.concat(
|
|
1460
|
+
[start_shape, one_i32_array], 0
|
|
1461
|
+
).output(0)
|
|
1462
|
+
|
|
1463
|
+
indices_reshaped = ov_opset.reshape(
|
|
1464
|
+
indices, indices_target_shape, False
|
|
1465
|
+
).output(0)
|
|
1466
|
+
start_reshaped = ov_opset.reshape(start, start_target_shape, False).output(
|
|
1467
|
+
0
|
|
1468
|
+
)
|
|
1469
|
+
step_reshaped = ov_opset.reshape(step, start_target_shape, False).output(0)
|
|
1470
|
+
|
|
1471
|
+
scaled_indices = ov_opset.multiply(indices_reshaped, step_reshaped).output(
|
|
1472
|
+
0
|
|
1043
1473
|
)
|
|
1474
|
+
result = ov_opset.add(start_reshaped, scaled_indices).output(0)
|
|
1475
|
+
|
|
1476
|
+
if retstep:
|
|
1477
|
+
return OpenVINOKerasTensor(result), OpenVINOKerasTensor(step)
|
|
1478
|
+
return OpenVINOKerasTensor(result)
|
|
1044
1479
|
|
|
1045
1480
|
|
|
1046
1481
|
def log(x):
|
|
@@ -1142,6 +1577,12 @@ def logaddexp(x1, x2):
|
|
|
1142
1577
|
return OpenVINOKerasTensor(result)
|
|
1143
1578
|
|
|
1144
1579
|
|
|
1580
|
+
def logaddexp2(x1, x2):
|
|
1581
|
+
raise NotImplementedError(
|
|
1582
|
+
"`logaddexp2` is not supported with openvino backend"
|
|
1583
|
+
)
|
|
1584
|
+
|
|
1585
|
+
|
|
1145
1586
|
def logical_and(x1, x2):
|
|
1146
1587
|
x1 = get_ov_output(x1)
|
|
1147
1588
|
x2 = get_ov_output(x2)
|
|
@@ -1165,10 +1606,30 @@ def logical_or(x1, x2):
|
|
|
1165
1606
|
|
|
1166
1607
|
|
|
1167
1608
|
def logspace(start, stop, num=50, endpoint=True, base=10, dtype=None, axis=0):
|
|
1168
|
-
|
|
1169
|
-
|
|
1609
|
+
linear_samples = linspace(
|
|
1610
|
+
start=start,
|
|
1611
|
+
stop=stop,
|
|
1612
|
+
num=num,
|
|
1613
|
+
endpoint=endpoint,
|
|
1614
|
+
retstep=False,
|
|
1615
|
+
dtype=dtype,
|
|
1616
|
+
axis=axis,
|
|
1170
1617
|
)
|
|
1171
1618
|
|
|
1619
|
+
if dtype is None:
|
|
1620
|
+
output_type = OPENVINO_DTYPES[config.floatx()]
|
|
1621
|
+
else:
|
|
1622
|
+
output_type = OPENVINO_DTYPES[dtype]
|
|
1623
|
+
|
|
1624
|
+
linear_output = get_ov_output(linear_samples)
|
|
1625
|
+
base_tensor = get_ov_output(base)
|
|
1626
|
+
|
|
1627
|
+
base_tensor = ov_opset.convert(base_tensor, output_type).output(0)
|
|
1628
|
+
|
|
1629
|
+
result = ov_opset.power(base_tensor, linear_output).output(0)
|
|
1630
|
+
|
|
1631
|
+
return OpenVINOKerasTensor(result)
|
|
1632
|
+
|
|
1172
1633
|
|
|
1173
1634
|
def maximum(x1, x2):
|
|
1174
1635
|
x1 = get_ov_output(x1)
|
|
@@ -1178,7 +1639,138 @@ def maximum(x1, x2):
|
|
|
1178
1639
|
|
|
1179
1640
|
|
|
1180
1641
|
def median(x, axis=None, keepdims=False):
|
|
1181
|
-
|
|
1642
|
+
x = get_ov_output(x)
|
|
1643
|
+
x_shape = x.get_partial_shape()
|
|
1644
|
+
rank = x_shape.rank.get_length()
|
|
1645
|
+
|
|
1646
|
+
if rank == 0:
|
|
1647
|
+
return OpenVINOKerasTensor(x)
|
|
1648
|
+
|
|
1649
|
+
# Handle axis=None by flattening the input
|
|
1650
|
+
flattened_all = False
|
|
1651
|
+
if axis is None:
|
|
1652
|
+
x = ov_opset.reshape(x, [-1], False).output(0)
|
|
1653
|
+
axis = 0
|
|
1654
|
+
original_rank = rank
|
|
1655
|
+
rank = 1
|
|
1656
|
+
flattened_all = True
|
|
1657
|
+
else:
|
|
1658
|
+
# Handle tuple axis - for median, we only support single axis
|
|
1659
|
+
if isinstance(axis, (tuple, list)):
|
|
1660
|
+
if len(axis) != 1:
|
|
1661
|
+
raise ValueError("median only supports single axis reduction")
|
|
1662
|
+
axis = axis[0]
|
|
1663
|
+
|
|
1664
|
+
# Handle negative axis
|
|
1665
|
+
if axis < 0:
|
|
1666
|
+
axis = rank + axis
|
|
1667
|
+
original_rank = rank
|
|
1668
|
+
|
|
1669
|
+
# Get the size of the dimension to sort
|
|
1670
|
+
shape_tensor = ov_opset.shape_of(x, output_type=Type.i32).output(0)
|
|
1671
|
+
k = ov_opset.gather(
|
|
1672
|
+
shape_tensor,
|
|
1673
|
+
ov_opset.constant([axis], Type.i32).output(0),
|
|
1674
|
+
ov_opset.constant(0, Type.i32).output(0),
|
|
1675
|
+
).output(0)
|
|
1676
|
+
|
|
1677
|
+
# Convert k to a scalar value
|
|
1678
|
+
k_scalar = ov_opset.squeeze(k, [0]).output(0)
|
|
1679
|
+
|
|
1680
|
+
# Use topk with k=size_of_axis to get all elements sorted
|
|
1681
|
+
topk_outputs = ov_opset.topk(
|
|
1682
|
+
x, k=k_scalar, axis=axis, mode="min", sort="value", stable=True
|
|
1683
|
+
)
|
|
1684
|
+
|
|
1685
|
+
# Get the sorted values
|
|
1686
|
+
sorted_values = topk_outputs.output(0)
|
|
1687
|
+
|
|
1688
|
+
# Convert to float for median calculation
|
|
1689
|
+
x1_type = ov_to_keras_type(sorted_values.get_element_type())
|
|
1690
|
+
result_type = dtypes.result_type(x1_type, float)
|
|
1691
|
+
result_type = OPENVINO_DTYPES[result_type]
|
|
1692
|
+
sorted_values = ov_opset.convert(sorted_values, result_type).output(0)
|
|
1693
|
+
|
|
1694
|
+
# Calculate median indices
|
|
1695
|
+
# For odd length: median_idx = (k-1) // 2
|
|
1696
|
+
# For even length: we need indices (k//2 - 1) and k//2, then average
|
|
1697
|
+
|
|
1698
|
+
k_minus_1 = ov_opset.subtract(
|
|
1699
|
+
k_scalar, ov_opset.constant(1, Type.i32).output(0)
|
|
1700
|
+
).output(0)
|
|
1701
|
+
k_div_2 = ov_opset.divide(
|
|
1702
|
+
k_scalar, ov_opset.constant(2, Type.i32).output(0)
|
|
1703
|
+
).output(0)
|
|
1704
|
+
k_minus_1_div_2 = ov_opset.divide(
|
|
1705
|
+
k_minus_1, ov_opset.constant(2, Type.i32).output(0)
|
|
1706
|
+
).output(0)
|
|
1707
|
+
|
|
1708
|
+
# Check if k is odd
|
|
1709
|
+
k_mod_2 = ov_opset.mod(
|
|
1710
|
+
k_scalar, ov_opset.constant(2, Type.i32).output(0)
|
|
1711
|
+
).output(0)
|
|
1712
|
+
is_odd = ov_opset.equal(
|
|
1713
|
+
k_mod_2, ov_opset.constant(1, Type.i32).output(0)
|
|
1714
|
+
).output(0)
|
|
1715
|
+
|
|
1716
|
+
# For odd case: take the middle element
|
|
1717
|
+
odd_idx = k_minus_1_div_2
|
|
1718
|
+
|
|
1719
|
+
# For even case: take average of two middle elements
|
|
1720
|
+
even_idx1 = ov_opset.subtract(
|
|
1721
|
+
k_div_2, ov_opset.constant(1, Type.i32).output(0)
|
|
1722
|
+
).output(0)
|
|
1723
|
+
even_idx2 = k_div_2
|
|
1724
|
+
|
|
1725
|
+
# Gather elements for both cases
|
|
1726
|
+
# Create gather indices tensor for the axis
|
|
1727
|
+
gather_indices_odd = ov_opset.unsqueeze(odd_idx, [0]).output(0)
|
|
1728
|
+
gather_indices_even1 = ov_opset.unsqueeze(even_idx1, [0]).output(0)
|
|
1729
|
+
gather_indices_even2 = ov_opset.unsqueeze(even_idx2, [0]).output(0)
|
|
1730
|
+
|
|
1731
|
+
# Gather the median elements
|
|
1732
|
+
odd_result = ov_opset.gather(
|
|
1733
|
+
sorted_values,
|
|
1734
|
+
gather_indices_odd,
|
|
1735
|
+
ov_opset.constant(axis, Type.i32).output(0),
|
|
1736
|
+
).output(0)
|
|
1737
|
+
even_result1 = ov_opset.gather(
|
|
1738
|
+
sorted_values,
|
|
1739
|
+
gather_indices_even1,
|
|
1740
|
+
ov_opset.constant(axis, Type.i32).output(0),
|
|
1741
|
+
).output(0)
|
|
1742
|
+
even_result2 = ov_opset.gather(
|
|
1743
|
+
sorted_values,
|
|
1744
|
+
gather_indices_even2,
|
|
1745
|
+
ov_opset.constant(axis, Type.i32).output(0),
|
|
1746
|
+
).output(0)
|
|
1747
|
+
|
|
1748
|
+
# Average the two middle elements for even case
|
|
1749
|
+
even_sum = ov_opset.add(even_result1, even_result2).output(0)
|
|
1750
|
+
even_result = ov_opset.divide(
|
|
1751
|
+
even_sum, ov_opset.constant(2.0, result_type).output(0)
|
|
1752
|
+
).output(0)
|
|
1753
|
+
|
|
1754
|
+
# Select between odd and even results
|
|
1755
|
+
median_result = ov_opset.select(is_odd, odd_result, even_result).output(0)
|
|
1756
|
+
|
|
1757
|
+
# Remove the gathered dimension (squeeze)
|
|
1758
|
+
median_result = ov_opset.squeeze(median_result, [axis]).output(0)
|
|
1759
|
+
|
|
1760
|
+
# Handle keepdims
|
|
1761
|
+
if keepdims:
|
|
1762
|
+
if flattened_all:
|
|
1763
|
+
# When axis=None, keepdims should restore all dimensions as 1
|
|
1764
|
+
ones_shape = ov_opset.constant(
|
|
1765
|
+
[1] * original_rank, Type.i32
|
|
1766
|
+
).output(0)
|
|
1767
|
+
median_result = ov_opset.reshape(
|
|
1768
|
+
median_result, ones_shape, False
|
|
1769
|
+
).output(0)
|
|
1770
|
+
else:
|
|
1771
|
+
median_result = ov_opset.unsqueeze(median_result, [axis]).output(0)
|
|
1772
|
+
|
|
1773
|
+
return OpenVINOKerasTensor(median_result)
|
|
1182
1774
|
|
|
1183
1775
|
|
|
1184
1776
|
def meshgrid(*x, indexing="xy"):
|
|
@@ -1226,46 +1818,7 @@ def meshgrid(*x, indexing="xy"):
|
|
|
1226
1818
|
|
|
1227
1819
|
|
|
1228
1820
|
def min(x, axis=None, keepdims=False, initial=None):
|
|
1229
|
-
x
|
|
1230
|
-
original_type = x.get_element_type()
|
|
1231
|
-
x_type = original_type
|
|
1232
|
-
x_shape = x.get_partial_shape().to_shape()
|
|
1233
|
-
|
|
1234
|
-
is_bool = x_type == Type.boolean
|
|
1235
|
-
if is_bool:
|
|
1236
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1237
|
-
x_type = Type.i32
|
|
1238
|
-
|
|
1239
|
-
if isinstance(axis, tuple) and len(axis) == 0:
|
|
1240
|
-
return OpenVINOKerasTensor(x)
|
|
1241
|
-
|
|
1242
|
-
if axis is None:
|
|
1243
|
-
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
1244
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1245
|
-
axis = 0
|
|
1246
|
-
|
|
1247
|
-
if isinstance(axis, tuple):
|
|
1248
|
-
axis = list(axis)
|
|
1249
|
-
|
|
1250
|
-
axis_const = ov_opset.constant(axis, Type.i32).output(0)
|
|
1251
|
-
min_result = ov_opset.reduce_min(x, axis_const, keepdims).output(0)
|
|
1252
|
-
|
|
1253
|
-
if initial is not None:
|
|
1254
|
-
initial_tensor = ov_opset.constant(initial, x_type).output(0)
|
|
1255
|
-
min_result = ov_opset.minimum(min_result, initial_tensor).output(0)
|
|
1256
|
-
|
|
1257
|
-
if keepdims:
|
|
1258
|
-
result_shape = [1] * len(x_shape)
|
|
1259
|
-
min_result = ov_opset.reshape(
|
|
1260
|
-
min_result,
|
|
1261
|
-
ov_opset.constant(result_shape, Type.i32).output(0),
|
|
1262
|
-
False,
|
|
1263
|
-
).output(0)
|
|
1264
|
-
|
|
1265
|
-
if is_bool:
|
|
1266
|
-
min_result = ov_opset.convert(min_result, Type.boolean).output(0)
|
|
1267
|
-
|
|
1268
|
-
return OpenVINOKerasTensor(min_result)
|
|
1821
|
+
return _compute_extrema(x, "min", axis, keepdims, initial)
|
|
1269
1822
|
|
|
1270
1823
|
|
|
1271
1824
|
def minimum(x1, x2):
|
|
@@ -1416,7 +1969,9 @@ def pad(x, pad_width, mode="constant", constant_values=None):
|
|
|
1416
1969
|
"`pad` operation supports only scalar pad value "
|
|
1417
1970
|
"in constant mode by openvino backend"
|
|
1418
1971
|
)
|
|
1419
|
-
pad_value =
|
|
1972
|
+
pad_value = ov_opset.constant(
|
|
1973
|
+
constant_values, x.get_element_type()
|
|
1974
|
+
).output(0)
|
|
1420
1975
|
|
|
1421
1976
|
# split pad_width into two tensors pads_begin and pads_end
|
|
1422
1977
|
pads_begin = []
|
|
@@ -1440,23 +1995,10 @@ def prod(x, axis=None, keepdims=False, dtype=None):
|
|
|
1440
1995
|
x = ov_opset.convert(x, ov_dtype).output(0)
|
|
1441
1996
|
# Otherwise, apply dtype promotion rules before reduction.
|
|
1442
1997
|
else:
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1446
|
-
elif x_type in (Type.i8, Type.i16):
|
|
1447
|
-
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1448
|
-
elif x_type in (Type.u8, Type.u16):
|
|
1449
|
-
x = ov_opset.convert(x, Type.u32).output(0)
|
|
1450
|
-
|
|
1998
|
+
x = _upcast_type_if_needed(x)
|
|
1999
|
+
x, axis = _resolve_axis(x, axis)
|
|
1451
2000
|
if axis is None:
|
|
1452
|
-
|
|
1453
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1454
|
-
axis = 0
|
|
1455
|
-
|
|
1456
|
-
if isinstance(axis, tuple):
|
|
1457
|
-
axis = list(axis)
|
|
1458
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
1459
|
-
|
|
2001
|
+
return OpenVINOKerasTensor(x)
|
|
1460
2002
|
# Compute the product
|
|
1461
2003
|
result = ov_opset.reduce_prod(x, axis, keepdims).output(0)
|
|
1462
2004
|
|
|
@@ -1556,7 +2098,17 @@ def reshape(x, newshape):
|
|
|
1556
2098
|
|
|
1557
2099
|
|
|
1558
2100
|
def roll(x, shift, axis=None):
|
|
1559
|
-
|
|
2101
|
+
x = get_ov_output(x)
|
|
2102
|
+
if axis is not None:
|
|
2103
|
+
result = ov_opset.roll(x, shift, axis).output(0)
|
|
2104
|
+
else:
|
|
2105
|
+
output_shape = ov_opset.shape_of(x).output(0)
|
|
2106
|
+
flattened = ov_opset.reshape(
|
|
2107
|
+
x, ov_opset.constant([-1], Type.i32), False
|
|
2108
|
+
).output(0)
|
|
2109
|
+
result = ov_opset.roll(flattened, shift, 0).output(0)
|
|
2110
|
+
result = ov_opset.reshape(result, output_shape, False).output(0)
|
|
2111
|
+
return OpenVINOKerasTensor(result)
|
|
1560
2112
|
|
|
1561
2113
|
|
|
1562
2114
|
def sign(x):
|
|
@@ -1593,7 +2145,43 @@ def size(x):
|
|
|
1593
2145
|
|
|
1594
2146
|
|
|
1595
2147
|
def sort(x, axis=-1):
|
|
1596
|
-
|
|
2148
|
+
x = get_ov_output(x)
|
|
2149
|
+
x_shape = x.get_partial_shape()
|
|
2150
|
+
rank = x_shape.rank.get_length()
|
|
2151
|
+
|
|
2152
|
+
if rank == 0:
|
|
2153
|
+
return OpenVINOKerasTensor(x)
|
|
2154
|
+
|
|
2155
|
+
# Handle axis=None by flattening the input
|
|
2156
|
+
if axis is None:
|
|
2157
|
+
x = ov_opset.reshape(
|
|
2158
|
+
x, ov_opset.constant([-1], Type.i32), False
|
|
2159
|
+
).output(0)
|
|
2160
|
+
axis = 0
|
|
2161
|
+
# Handle negative axis
|
|
2162
|
+
elif axis < 0:
|
|
2163
|
+
axis = rank + axis
|
|
2164
|
+
|
|
2165
|
+
# Get the size of the dimension to sort
|
|
2166
|
+
shape_tensor = ov_opset.shape_of(x, output_type=Type.i32).output(0)
|
|
2167
|
+
k = ov_opset.gather(
|
|
2168
|
+
shape_tensor,
|
|
2169
|
+
ov_opset.constant([axis], Type.i32).output(0),
|
|
2170
|
+
ov_opset.constant(0, Type.i32).output(0),
|
|
2171
|
+
).output(0)
|
|
2172
|
+
|
|
2173
|
+
# Convert k to a scalar value
|
|
2174
|
+
k_scalar = ov_opset.squeeze(k, ov_opset.constant([0], Type.i32)).output(0)
|
|
2175
|
+
|
|
2176
|
+
# Use topk with k=size_of_axis to get all elements sorted
|
|
2177
|
+
topk_outputs = ov_opset.topk(
|
|
2178
|
+
x, k=k_scalar, axis=axis, mode="min", sort="value", stable=True
|
|
2179
|
+
)
|
|
2180
|
+
|
|
2181
|
+
# Get the sorted values
|
|
2182
|
+
sorted_values = topk_outputs.output(0)
|
|
2183
|
+
|
|
2184
|
+
return OpenVINOKerasTensor(sorted_values)
|
|
1597
2185
|
|
|
1598
2186
|
|
|
1599
2187
|
def split(x, indices_or_sections, axis=0):
|
|
@@ -1642,6 +2230,37 @@ def split(x, indices_or_sections, axis=0):
|
|
|
1642
2230
|
)
|
|
1643
2231
|
|
|
1644
2232
|
|
|
2233
|
+
def array_split(x, indices_or_sections, axis=0):
|
|
2234
|
+
original_shape = x.shape
|
|
2235
|
+
x = get_ov_output(x)
|
|
2236
|
+
|
|
2237
|
+
num_splits_val = indices_or_sections
|
|
2238
|
+
total_size = original_shape[axis]
|
|
2239
|
+
if total_size is None:
|
|
2240
|
+
raise ValueError(
|
|
2241
|
+
f"Cannot use array_split with static Python logic on dynamic axis. "
|
|
2242
|
+
f"Axis {axis} has unknown dimension for shape {original_shape}."
|
|
2243
|
+
)
|
|
2244
|
+
|
|
2245
|
+
base_size = total_size // num_splits_val
|
|
2246
|
+
remainder = total_size % num_splits_val
|
|
2247
|
+
|
|
2248
|
+
split_lengths = [base_size + 1] * remainder + [base_size] * (
|
|
2249
|
+
num_splits_val - remainder
|
|
2250
|
+
)
|
|
2251
|
+
split_lengths_tensor = ov_opset.constant(
|
|
2252
|
+
split_lengths, dtype=Type.i64
|
|
2253
|
+
).output(0)
|
|
2254
|
+
|
|
2255
|
+
axis_tensor = ov_opset.constant(axis, dtype=Type.i32).output(0)
|
|
2256
|
+
splits = ov_opset.variadic_split(x, axis_tensor, split_lengths_tensor)
|
|
2257
|
+
|
|
2258
|
+
result = []
|
|
2259
|
+
for i in range(num_splits_val):
|
|
2260
|
+
result.append(OpenVINOKerasTensor(splits.output(i)))
|
|
2261
|
+
return result
|
|
2262
|
+
|
|
2263
|
+
|
|
1645
2264
|
def stack(x, axis=0):
|
|
1646
2265
|
if isinstance(x, tuple):
|
|
1647
2266
|
x = list(x)
|
|
@@ -1658,22 +2277,9 @@ def stack(x, axis=0):
|
|
|
1658
2277
|
|
|
1659
2278
|
|
|
1660
2279
|
def std(x, axis=None, keepdims=False):
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
x = ov_opset.reshape(x, flatten_shape, False).output(0)
|
|
1665
|
-
axis = 0
|
|
1666
|
-
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
1667
|
-
# The variance is computed using $Var = E[|x|^2] - |E[x]|^2$, It is faster
|
|
1668
|
-
# but less numerically stable.
|
|
1669
|
-
mean = ov_opset.reduce_mean(x, axis, keepdims).output(0)
|
|
1670
|
-
const_two = ov_opset.constant(2, x.get_element_type()).output(0)
|
|
1671
|
-
squared_x = ov_opset.power(x, const_two).output(0)
|
|
1672
|
-
squared_mean = ov_opset.power(mean, const_two).output(0)
|
|
1673
|
-
squared_x_mean = ov_opset.reduce_mean(squared_x, axis, keepdims)
|
|
1674
|
-
variance = ov_opset.subtract(squared_x_mean, squared_mean).output(0)
|
|
1675
|
-
std_var = OpenVINOKerasTensor(ov_opset.sqrt(variance).output(0))
|
|
1676
|
-
return std_var
|
|
2280
|
+
var_x = var(x, axis, keepdims)
|
|
2281
|
+
std_dev = ov_opset.sqrt(var_x).output(0)
|
|
2282
|
+
return OpenVINOKerasTensor(std_dev)
|
|
1677
2283
|
|
|
1678
2284
|
|
|
1679
2285
|
def swapaxes(x, axis1, axis2):
|
|
@@ -1893,7 +2499,20 @@ def triu(x, k=0):
|
|
|
1893
2499
|
|
|
1894
2500
|
|
|
1895
2501
|
def vdot(x1, x2):
|
|
1896
|
-
|
|
2502
|
+
element_type = None
|
|
2503
|
+
if isinstance(x1, OpenVINOKerasTensor):
|
|
2504
|
+
element_type = x1.output.get_element_type()
|
|
2505
|
+
if isinstance(x2, OpenVINOKerasTensor):
|
|
2506
|
+
element_type = x2.output.get_element_type()
|
|
2507
|
+
x1 = get_ov_output(x1, element_type)
|
|
2508
|
+
x2 = get_ov_output(x2, element_type)
|
|
2509
|
+
x1, x2 = _align_operand_types(x1, x2, "vdot()")
|
|
2510
|
+
if x1.get_partial_shape().rank == 0 or x2.get_partial_shape().rank == 0:
|
|
2511
|
+
return OpenVINOKerasTensor(ov_opset.multiply(x1, x2).output(0))
|
|
2512
|
+
flatten_shape = ov_opset.constant([-1], Type.i32).output(0)
|
|
2513
|
+
x1 = ov_opset.reshape(x1, flatten_shape, False).output(0)
|
|
2514
|
+
x2 = ov_opset.reshape(x2, flatten_shape, False).output(0)
|
|
2515
|
+
return OpenVINOKerasTensor(ov_opset.matmul(x1, x2, False, False).output(0))
|
|
1897
2516
|
|
|
1898
2517
|
|
|
1899
2518
|
def vstack(xs):
|
|
@@ -1979,14 +2598,27 @@ def negative(x):
|
|
|
1979
2598
|
return OpenVINOKerasTensor(ov_opset.negative(x).output(0))
|
|
1980
2599
|
|
|
1981
2600
|
|
|
2601
|
+
def nextafter(x1, x2):
|
|
2602
|
+
raise NotImplementedError(
|
|
2603
|
+
"`nextafter` is not supported with openvino backend"
|
|
2604
|
+
)
|
|
2605
|
+
|
|
2606
|
+
|
|
1982
2607
|
def square(x):
|
|
1983
2608
|
x = get_ov_output(x)
|
|
2609
|
+
x_type = x.get_element_type()
|
|
2610
|
+
if x_type == Type.boolean:
|
|
2611
|
+
x = ov_opset.convert(x, Type.i32).output(0)
|
|
1984
2612
|
const_two = ov_opset.constant(2, x.get_element_type()).output(0)
|
|
1985
2613
|
return OpenVINOKerasTensor(ov_opset.power(x, const_two).output(0))
|
|
1986
2614
|
|
|
1987
2615
|
|
|
1988
2616
|
def sqrt(x):
|
|
1989
2617
|
x = get_ov_output(x)
|
|
2618
|
+
x_type = x.get_element_type()
|
|
2619
|
+
if x_type.is_integral():
|
|
2620
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
2621
|
+
x = ov_opset.convert(x, ov_type).output(0)
|
|
1990
2622
|
return OpenVINOKerasTensor(ov_opset.sqrt(x).output(0))
|
|
1991
2623
|
|
|
1992
2624
|
|
|
@@ -1997,6 +2629,8 @@ def squeeze(x, axis=None):
|
|
|
1997
2629
|
for idx, dim in enumerate(x.get_partial_shape()):
|
|
1998
2630
|
if dim == 1:
|
|
1999
2631
|
axis.append(idx)
|
|
2632
|
+
if isinstance(axis, tuple):
|
|
2633
|
+
axis = list(axis)
|
|
2000
2634
|
axis = ov_opset.constant(axis, Type.i32).output(0)
|
|
2001
2635
|
return OpenVINOKerasTensor(ov_opset.squeeze(x, axis).output(0))
|
|
2002
2636
|
|
|
@@ -2021,20 +2655,135 @@ def transpose(x, axes=None):
|
|
|
2021
2655
|
return OpenVINOKerasTensor(ov_opset.transpose(x, axes).output(0))
|
|
2022
2656
|
|
|
2023
2657
|
|
|
2658
|
+
def _helper_trapezoid(y, axis):
|
|
2659
|
+
rank = y.get_partial_shape().rank.get_length()
|
|
2660
|
+
strides = ov_opset.constant([1] * rank, dtype=Type.i64).output(0)
|
|
2661
|
+
|
|
2662
|
+
# y[:-1]
|
|
2663
|
+
begin1 = ov_opset.constant([0] * rank, dtype=Type.i64).output(0)
|
|
2664
|
+
end1_list = [0] * rank
|
|
2665
|
+
end1_list[axis] = -1
|
|
2666
|
+
end1 = ov_opset.constant(end1_list, dtype=Type.i64).output(0)
|
|
2667
|
+
begin_mask1 = [1] * rank
|
|
2668
|
+
begin_mask1[axis] = 0
|
|
2669
|
+
end_mask1 = [1] * rank
|
|
2670
|
+
end_mask1[axis] = 0
|
|
2671
|
+
y1 = ov_opset.strided_slice(
|
|
2672
|
+
y, begin1, end1, strides, begin_mask1, end_mask1
|
|
2673
|
+
).output(0)
|
|
2674
|
+
|
|
2675
|
+
# y[1:]
|
|
2676
|
+
begin2_list = [0] * rank
|
|
2677
|
+
begin2_list[axis] = 1
|
|
2678
|
+
begin2 = ov_opset.constant(begin2_list, dtype=Type.i64).output(0)
|
|
2679
|
+
end2 = ov_opset.constant([0] * rank, dtype=Type.i64).output(0)
|
|
2680
|
+
begin_mask2 = [1] * rank
|
|
2681
|
+
begin_mask2[axis] = 0
|
|
2682
|
+
end_mask2 = [1] * rank
|
|
2683
|
+
y2 = ov_opset.strided_slice(
|
|
2684
|
+
y, begin2, end2, strides, begin_mask2, end_mask2
|
|
2685
|
+
).output(0)
|
|
2686
|
+
|
|
2687
|
+
return y1, y2
|
|
2688
|
+
|
|
2689
|
+
|
|
2690
|
+
def trapezoid(y, x=None, dx=1.0, axis=-1):
|
|
2691
|
+
y = get_ov_output(y)
|
|
2692
|
+
y_type = y.get_element_type()
|
|
2693
|
+
|
|
2694
|
+
if y_type.is_integral():
|
|
2695
|
+
y_type = OPENVINO_DTYPES[config.floatx()]
|
|
2696
|
+
y = ov_opset.convert(y, y_type).output(0)
|
|
2697
|
+
|
|
2698
|
+
y1, y2 = _helper_trapezoid(y, axis)
|
|
2699
|
+
y_final = ov_opset.add(y1, y2).output(0)
|
|
2700
|
+
const_two = ov_opset.constant(2, dtype=y_type).output(0)
|
|
2701
|
+
y_final = ov_opset.divide(y_final, const_two).output(0)
|
|
2702
|
+
|
|
2703
|
+
if x is not None:
|
|
2704
|
+
x = get_ov_output(x)
|
|
2705
|
+
x_type = x.get_element_type()
|
|
2706
|
+
if x_type.is_integral():
|
|
2707
|
+
x_type = OPENVINO_DTYPES[config.floatx()]
|
|
2708
|
+
x = ov_opset.convert(x, x_type).output(0)
|
|
2709
|
+
|
|
2710
|
+
x1, x2 = _helper_trapezoid(x, axis)
|
|
2711
|
+
x_final = ov_opset.subtract(x2, x1).output(0)
|
|
2712
|
+
|
|
2713
|
+
else:
|
|
2714
|
+
x_final = ov_opset.constant(dx, dtype=y_type).output(0)
|
|
2715
|
+
|
|
2716
|
+
result = ov_opset.multiply(y_final, x_final).output(0)
|
|
2717
|
+
const_axis = ov_opset.constant([axis], Type.i64).output(0)
|
|
2718
|
+
result = ov_opset.reduce_sum(result, const_axis, False).output(0)
|
|
2719
|
+
|
|
2720
|
+
return OpenVINOKerasTensor(result)
|
|
2721
|
+
|
|
2722
|
+
|
|
2723
|
+
def vander(x, N=None, increasing=False):
|
|
2724
|
+
x = get_ov_output(x)
|
|
2725
|
+
x_type = x.get_element_type()
|
|
2726
|
+
|
|
2727
|
+
shape_x = ov_opset.shape_of(x, Type.i64).output(0)
|
|
2728
|
+
|
|
2729
|
+
const_zero_1D = ov_opset.constant([0], dtype=Type.i64).output(0)
|
|
2730
|
+
const_zero = ov_opset.constant(0, dtype=Type.i64).output(0)
|
|
2731
|
+
const_one = ov_opset.constant(1, dtype=Type.i64).output(0)
|
|
2732
|
+
const_mone = ov_opset.constant(-1, dtype=Type.i64).output(0)
|
|
2733
|
+
|
|
2734
|
+
if N is None:
|
|
2735
|
+
const_N = ov_opset.squeeze(shape_x, const_zero_1D).output(0)
|
|
2736
|
+
const_N_1D = shape_x
|
|
2737
|
+
else:
|
|
2738
|
+
const_N = ov_opset.constant(N, Type.i64).output(0)
|
|
2739
|
+
const_N_1D = ov_opset.constant([N], Type.i64).output(0)
|
|
2740
|
+
|
|
2741
|
+
const_N_minus_one = ov_opset.subtract(const_N, const_one).output(0)
|
|
2742
|
+
if increasing:
|
|
2743
|
+
powers = ov_opset.range(const_zero, const_N, const_one, x_type).output(
|
|
2744
|
+
0
|
|
2745
|
+
)
|
|
2746
|
+
else:
|
|
2747
|
+
powers = ov_opset.range(
|
|
2748
|
+
const_N_minus_one, const_mone, const_mone, x_type
|
|
2749
|
+
).output(0)
|
|
2750
|
+
|
|
2751
|
+
target_shape = ov_opset.concat([shape_x, const_N_1D], 0).output(0)
|
|
2752
|
+
|
|
2753
|
+
const_one_1D = ov_opset.constant([1], dtype=Type.i64).output(0)
|
|
2754
|
+
|
|
2755
|
+
powers = ov_opset.unsqueeze(powers, const_zero_1D).output(0)
|
|
2756
|
+
x = ov_opset.unsqueeze(x, const_one_1D).output(0)
|
|
2757
|
+
|
|
2758
|
+
result = ov_opset.broadcast(x, target_shape).output(0)
|
|
2759
|
+
|
|
2760
|
+
result = ov_opset.power(result, powers).output(0)
|
|
2761
|
+
|
|
2762
|
+
return OpenVINOKerasTensor(result)
|
|
2763
|
+
|
|
2764
|
+
|
|
2024
2765
|
def var(x, axis=None, keepdims=False):
|
|
2025
2766
|
x = get_ov_output(x)
|
|
2767
|
+
x_type = x.get_element_type()
|
|
2768
|
+
x, axis = _resolve_axis(x, axis)
|
|
2769
|
+
|
|
2770
|
+
work_dtype = Type.f64 if x_type.is_integral() else x.get_element_type()
|
|
2771
|
+
if x_type.is_integral():
|
|
2772
|
+
x = ov_opset.convert(x, work_dtype).output(0)
|
|
2026
2773
|
if axis is None:
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2774
|
+
const_zero = ov_opset.constant(0, dtype=work_dtype).output(0)
|
|
2775
|
+
return OpenVINOKerasTensor(
|
|
2776
|
+
ov_opset.broadcast(const_zero, ov_opset.shape_of(x)).output(0)
|
|
2777
|
+
)
|
|
2031
2778
|
# The variance is computed using $Var = E[|x|^2] - |E[x]|^2$, It is faster
|
|
2032
2779
|
# but less numerically stable.
|
|
2033
2780
|
mean = ov_opset.reduce_mean(x, axis, keepdims).output(0)
|
|
2034
|
-
const_two = ov_opset.constant(2,
|
|
2781
|
+
const_two = ov_opset.constant(2, work_dtype).output(0)
|
|
2782
|
+
|
|
2035
2783
|
squared_x = ov_opset.power(x, const_two).output(0)
|
|
2036
2784
|
squared_mean = ov_opset.power(mean, const_two).output(0)
|
|
2037
|
-
|
|
2785
|
+
|
|
2786
|
+
squared_x_mean = ov_opset.reduce_mean(squared_x, axis, keepdims).output(0)
|
|
2038
2787
|
variance = OpenVINOKerasTensor(
|
|
2039
2788
|
ov_opset.subtract(squared_x_mean, squared_mean).output(0)
|
|
2040
2789
|
)
|
|
@@ -2043,22 +2792,46 @@ def var(x, axis=None, keepdims=False):
|
|
|
2043
2792
|
|
|
2044
2793
|
def sum(x, axis=None, keepdims=False):
|
|
2045
2794
|
x = get_ov_output(x)
|
|
2795
|
+
x, axis = _resolve_axis(x, axis)
|
|
2046
2796
|
if axis is None:
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
return OpenVINOKerasTensor(ov_opset.reduce_sum(x, axis, keepdims).output(0))
|
|
2797
|
+
return OpenVINOKerasTensor(x)
|
|
2798
|
+
x = _upcast_type_if_needed(x)
|
|
2799
|
+
summed_value = ov_opset.reduce_sum(x, axis, keepdims).output(0)
|
|
2800
|
+
return OpenVINOKerasTensor(summed_value)
|
|
2052
2801
|
|
|
2053
2802
|
|
|
2054
2803
|
def eye(N, M=None, k=0, dtype=None):
|
|
2055
|
-
|
|
2804
|
+
dtype = standardize_dtype(dtype) or config.floatx()
|
|
2805
|
+
ov_type = OPENVINO_DTYPES[dtype]
|
|
2806
|
+
if M is None:
|
|
2807
|
+
M = N
|
|
2808
|
+
return OpenVINOKerasTensor(
|
|
2809
|
+
ov_opset.eye(
|
|
2810
|
+
ov_opset.constant(N, Type.i32),
|
|
2811
|
+
ov_opset.constant(M, Type.i32),
|
|
2812
|
+
ov_opset.constant(k, Type.i32),
|
|
2813
|
+
output_type=ov_type,
|
|
2814
|
+
).output(0)
|
|
2815
|
+
)
|
|
2056
2816
|
|
|
2057
2817
|
|
|
2058
2818
|
def floor_divide(x1, x2):
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
)
|
|
2819
|
+
x1_output = get_ov_output(x1)
|
|
2820
|
+
x2_output = get_ov_output(x2)
|
|
2821
|
+
if x1_output.get_element_type() == Type.boolean:
|
|
2822
|
+
x1_output = ov_opset.convert(x1_output, Type.i32).output(0)
|
|
2823
|
+
if isinstance(x2, (int, float)):
|
|
2824
|
+
if x1_output.get_element_type().is_integral() and isinstance(x2, float):
|
|
2825
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
2826
|
+
else:
|
|
2827
|
+
ov_type = x1_output.get_element_type()
|
|
2828
|
+
x1 = ov_opset.convert(x1_output, ov_type).output(0)
|
|
2829
|
+
x2 = ov_opset.convert(x2_output, ov_type).output(0)
|
|
2830
|
+
else:
|
|
2831
|
+
x1, x2 = _align_operand_types(x1_output, x2_output, "floor_divide()")
|
|
2832
|
+
div = ov_opset.divide(x1, x2).output(0)
|
|
2833
|
+
floored_div = ov_opset.floor(div).output(0)
|
|
2834
|
+
return OpenVINOKerasTensor(floored_div)
|
|
2062
2835
|
|
|
2063
2836
|
|
|
2064
2837
|
def logical_xor(x1, x2):
|
|
@@ -2070,16 +2843,88 @@ def logical_xor(x1, x2):
|
|
|
2070
2843
|
|
|
2071
2844
|
|
|
2072
2845
|
def corrcoef(x):
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2846
|
+
x_ov = get_ov_output(x)
|
|
2847
|
+
x_type = x_ov.get_element_type()
|
|
2848
|
+
ov_type = x_type
|
|
2849
|
+
|
|
2850
|
+
if x_type.is_integral():
|
|
2851
|
+
ov_type = OPENVINO_DTYPES[config.floatx()]
|
|
2852
|
+
x_ov = ov_opset.convert(x_ov, ov_type).output(0)
|
|
2853
|
+
|
|
2854
|
+
const_one = ov_opset.constant(1, dtype=Type.i64).output(0)
|
|
2855
|
+
const_two = ov_opset.constant(2, dtype=ov_type).output(0)
|
|
2856
|
+
|
|
2857
|
+
mean = ov_opset.reduce_mean(x_ov, const_one, True).output(0)
|
|
2858
|
+
x_ov = ov_opset.subtract(x_ov, mean).output(0)
|
|
2859
|
+
|
|
2860
|
+
cov = ov_opset.matmul(x_ov, x_ov, False, True).output(0)
|
|
2861
|
+
xsqr = ov_opset.power(x_ov, const_two).output(0)
|
|
2862
|
+
xvar = ov_opset.reduce_sum(xsqr, const_one, True).output(0)
|
|
2863
|
+
xstd = ov_opset.sqrt(xvar).output(0)
|
|
2864
|
+
|
|
2865
|
+
den = ov_opset.matmul(xstd, xstd, False, True).output(0)
|
|
2866
|
+
|
|
2867
|
+
result = ov_opset.divide(cov, den).output(0)
|
|
2868
|
+
|
|
2869
|
+
return OpenVINOKerasTensor(result)
|
|
2076
2870
|
|
|
2077
2871
|
|
|
2078
2872
|
def correlate(x1, x2, mode="valid"):
|
|
2079
|
-
|
|
2080
|
-
|
|
2873
|
+
x1 = get_ov_output(x1)
|
|
2874
|
+
x2 = get_ov_output(x2)
|
|
2875
|
+
x1_type = x1.get_element_type()
|
|
2876
|
+
x2_type = x2.get_element_type()
|
|
2877
|
+
x1_type = ov_to_keras_type(x1_type)
|
|
2878
|
+
x2_type = ov_to_keras_type(x2_type)
|
|
2879
|
+
result_type = dtypes.result_type(x1_type, x2_type, float)
|
|
2880
|
+
|
|
2881
|
+
result_type = OPENVINO_DTYPES[result_type]
|
|
2882
|
+
x1 = ov_opset.convert(x1, result_type).output(0)
|
|
2883
|
+
x2 = ov_opset.convert(x2, result_type).output(0)
|
|
2884
|
+
|
|
2885
|
+
shape_filter = ov_opset.shape_of(x2, Type.i64).output(0)
|
|
2886
|
+
const_two = ov_opset.constant(2, Type.f64).output(0)
|
|
2887
|
+
const_one = ov_opset.constant(1, Type.i64).output(0)
|
|
2888
|
+
const_zero = ov_opset.constant(0, result_type).output(0)
|
|
2889
|
+
shape_filter_minus_one = ov_opset.subtract(shape_filter, const_one).output(
|
|
2890
|
+
0
|
|
2081
2891
|
)
|
|
2082
2892
|
|
|
2893
|
+
# padding x1
|
|
2894
|
+
if mode == "valid":
|
|
2895
|
+
pass
|
|
2896
|
+
|
|
2897
|
+
elif mode == "same":
|
|
2898
|
+
shape_minus_one_float = ov_opset.convert(
|
|
2899
|
+
shape_filter_minus_one, Type.f64
|
|
2900
|
+
).output(0)
|
|
2901
|
+
|
|
2902
|
+
right = ov_opset.divide(shape_minus_one_float, const_two).output(0)
|
|
2903
|
+
left = ov_opset.ceil(right).output(0)
|
|
2904
|
+
right = ov_opset.floor(right).output(0)
|
|
2905
|
+
left = ov_opset.convert(left, Type.i64).output(0)
|
|
2906
|
+
right = ov_opset.convert(right, Type.i64).output(0)
|
|
2907
|
+
x1 = ov_opset.pad(x1, left, right, "constant", const_zero).output(0)
|
|
2908
|
+
|
|
2909
|
+
elif mode == "full":
|
|
2910
|
+
pad = shape_filter_minus_one
|
|
2911
|
+
x1 = ov_opset.pad(x1, pad, pad, "constant", const_zero).output(0)
|
|
2912
|
+
|
|
2913
|
+
else:
|
|
2914
|
+
raise ValueError(
|
|
2915
|
+
f"mode: {mode} not available chose from valid, same, full."
|
|
2916
|
+
)
|
|
2917
|
+
|
|
2918
|
+
axes = ov_opset.constant([0, 1], dtype=Type.i64).output(0)
|
|
2919
|
+
x2 = ov_opset.unsqueeze(x2, axes).output(0)
|
|
2920
|
+
x1 = ov_opset.unsqueeze(x1, axes).output(0)
|
|
2921
|
+
|
|
2922
|
+
result = ov_opset.convolution(x1, x2, [1], [0], [0], [1]).output(0)
|
|
2923
|
+
|
|
2924
|
+
result = ov_opset.squeeze(result, axes).output(0)
|
|
2925
|
+
|
|
2926
|
+
return OpenVINOKerasTensor(result)
|
|
2927
|
+
|
|
2083
2928
|
|
|
2084
2929
|
def select(condlist, choicelist, default=0):
|
|
2085
2930
|
raise NotImplementedError("`select` is not supported with openvino backend")
|