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
keras/src/backend/numpy/numpy.py
CHANGED
|
@@ -173,15 +173,18 @@ def append(x1, x2, axis=None):
|
|
|
173
173
|
return np.append(x1, x2, axis=axis)
|
|
174
174
|
|
|
175
175
|
|
|
176
|
-
def arange(start, stop=None, step=
|
|
176
|
+
def arange(start, stop=None, step=None, dtype=None):
|
|
177
177
|
if dtype is None:
|
|
178
|
-
dtypes_to_resolve = [
|
|
179
|
-
getattr(start, "dtype", type(start)),
|
|
180
|
-
getattr(step, "dtype", type(step)),
|
|
181
|
-
]
|
|
178
|
+
dtypes_to_resolve = [getattr(start, "dtype", type(start))]
|
|
182
179
|
if stop is not None:
|
|
183
180
|
dtypes_to_resolve.append(getattr(stop, "dtype", type(stop)))
|
|
181
|
+
if step is not None:
|
|
182
|
+
dtypes_to_resolve.append(getattr(step, "dtype", type(step)))
|
|
184
183
|
dtype = dtypes.result_type(*dtypes_to_resolve)
|
|
184
|
+
if stop is None:
|
|
185
|
+
start, stop = 0, start
|
|
186
|
+
if step is None:
|
|
187
|
+
step = 1
|
|
185
188
|
return np.arange(start, stop, step=step, dtype=dtype)
|
|
186
189
|
|
|
187
190
|
|
|
@@ -291,6 +294,11 @@ def array(x, dtype=None):
|
|
|
291
294
|
return convert_to_tensor(x, dtype=dtype)
|
|
292
295
|
|
|
293
296
|
|
|
297
|
+
def view(x, dtype=None):
|
|
298
|
+
x = convert_to_tensor(x)
|
|
299
|
+
return x.view(dtype=dtype)
|
|
300
|
+
|
|
301
|
+
|
|
294
302
|
def average(x, axis=None, weights=None):
|
|
295
303
|
axis = standardize_axis_for_numpy(axis)
|
|
296
304
|
x = convert_to_tensor(x)
|
|
@@ -604,6 +612,10 @@ def empty(shape, dtype=None):
|
|
|
604
612
|
return np.empty(shape, dtype=dtype)
|
|
605
613
|
|
|
606
614
|
|
|
615
|
+
def empty_like(x, dtype=None):
|
|
616
|
+
return np.empty_like(x, dtype=dtype)
|
|
617
|
+
|
|
618
|
+
|
|
607
619
|
def equal(x1, x2):
|
|
608
620
|
return np.equal(x1, x2)
|
|
609
621
|
|
|
@@ -742,6 +754,11 @@ def isposinf(x):
|
|
|
742
754
|
return np.isposinf(x)
|
|
743
755
|
|
|
744
756
|
|
|
757
|
+
def isreal(x):
|
|
758
|
+
x = convert_to_tensor(x)
|
|
759
|
+
return np.isreal(x)
|
|
760
|
+
|
|
761
|
+
|
|
745
762
|
def kron(x1, x2):
|
|
746
763
|
x1 = convert_to_tensor(x1)
|
|
747
764
|
x2 = convert_to_tensor(x2)
|
|
@@ -756,6 +773,19 @@ def lcm(x1, x2):
|
|
|
756
773
|
return np.lcm(x1, x2).astype(dtype)
|
|
757
774
|
|
|
758
775
|
|
|
776
|
+
def ldexp(x1, x2):
|
|
777
|
+
x1 = convert_to_tensor(x1)
|
|
778
|
+
x2 = convert_to_tensor(x2)
|
|
779
|
+
dtype = dtypes.result_type(x1.dtype, x2.dtype, float)
|
|
780
|
+
|
|
781
|
+
if standardize_dtype(x2.dtype) not in dtypes.INT_TYPES:
|
|
782
|
+
raise TypeError(
|
|
783
|
+
f"ldexp exponent must be an integer type. "
|
|
784
|
+
f"Received: x2 dtype={x2.dtype}"
|
|
785
|
+
)
|
|
786
|
+
return np.ldexp(x1, x2).astype(dtype)
|
|
787
|
+
|
|
788
|
+
|
|
759
789
|
def less(x1, x2):
|
|
760
790
|
return np.less(x1, x2)
|
|
761
791
|
|
|
@@ -835,6 +865,13 @@ def logaddexp(x1, x2):
|
|
|
835
865
|
return np.logaddexp(x1, x2)
|
|
836
866
|
|
|
837
867
|
|
|
868
|
+
def logaddexp2(x1, x2):
|
|
869
|
+
x1 = convert_to_tensor(x1)
|
|
870
|
+
x2 = convert_to_tensor(x2)
|
|
871
|
+
dtype = dtypes.result_type(x1.dtype, x2.dtype, float)
|
|
872
|
+
return np.logaddexp2(x1, x2).astype(dtype)
|
|
873
|
+
|
|
874
|
+
|
|
838
875
|
def logical_and(x1, x2):
|
|
839
876
|
return np.logical_and(x1, x2)
|
|
840
877
|
|
|
@@ -1087,6 +1124,11 @@ def split(x, indices_or_sections, axis=0):
|
|
|
1087
1124
|
return np.split(x, indices_or_sections, axis=axis)
|
|
1088
1125
|
|
|
1089
1126
|
|
|
1127
|
+
def array_split(x, indices_or_sections, axis=0):
|
|
1128
|
+
axis = standardize_axis_for_numpy(axis)
|
|
1129
|
+
return np.array_split(x, indices_or_sections, axis=axis)
|
|
1130
|
+
|
|
1131
|
+
|
|
1090
1132
|
def stack(x, axis=0):
|
|
1091
1133
|
axis = standardize_axis_for_numpy(axis)
|
|
1092
1134
|
dtype_set = set([getattr(a, "dtype", type(a)) for a in x])
|
|
@@ -1162,8 +1204,10 @@ def trace(x, offset=0, axis1=0, axis2=1):
|
|
|
1162
1204
|
axis2 = standardize_axis_for_numpy(axis2)
|
|
1163
1205
|
x = convert_to_tensor(x)
|
|
1164
1206
|
dtype = standardize_dtype(x.dtype)
|
|
1165
|
-
if dtype
|
|
1166
|
-
dtype =
|
|
1207
|
+
if dtype in ("bool", "int8", "int16"):
|
|
1208
|
+
dtype = "int32"
|
|
1209
|
+
elif dtype in ("uint8", "uint16"):
|
|
1210
|
+
dtype = "uint32"
|
|
1167
1211
|
return np.trace(x, offset=offset, axis1=axis1, axis2=axis2, dtype=dtype)
|
|
1168
1212
|
|
|
1169
1213
|
|
|
@@ -1291,6 +1335,14 @@ def negative(x):
|
|
|
1291
1335
|
return np.negative(x)
|
|
1292
1336
|
|
|
1293
1337
|
|
|
1338
|
+
def nextafter(x1, x2):
|
|
1339
|
+
x1 = convert_to_tensor(x1)
|
|
1340
|
+
x2 = convert_to_tensor(x2)
|
|
1341
|
+
dtype = dtypes.result_type(x1.dtype, x2.dtype, float)
|
|
1342
|
+
|
|
1343
|
+
return np.nextafter(x1, x2).astype(dtype)
|
|
1344
|
+
|
|
1345
|
+
|
|
1294
1346
|
def square(x):
|
|
1295
1347
|
x = convert_to_tensor(x)
|
|
1296
1348
|
if standardize_dtype(x.dtype) == "bool":
|
|
@@ -1319,6 +1371,23 @@ def transpose(x, axes=None):
|
|
|
1319
1371
|
return np.transpose(x, axes=axes)
|
|
1320
1372
|
|
|
1321
1373
|
|
|
1374
|
+
def trapezoid(y, x=None, dx=1.0, axis=-1):
|
|
1375
|
+
y = convert_to_tensor(y)
|
|
1376
|
+
result_dtype = dtypes.result_type(y.dtype, float)
|
|
1377
|
+
if x is not None:
|
|
1378
|
+
x = convert_to_tensor(x)
|
|
1379
|
+
dx = convert_to_tensor(dx)
|
|
1380
|
+
return np.trapezoid(y, x, dx=dx, axis=axis).astype(result_dtype)
|
|
1381
|
+
|
|
1382
|
+
|
|
1383
|
+
def vander(x, N=None, increasing=False):
|
|
1384
|
+
x = convert_to_tensor(x)
|
|
1385
|
+
result_dtype = dtypes.result_type(x.dtype)
|
|
1386
|
+
compute_dtype = dtypes.result_type(x.dtype, config.floatx())
|
|
1387
|
+
x = x.astype(compute_dtype)
|
|
1388
|
+
return np.vander(x, N=N, increasing=increasing).astype(result_dtype)
|
|
1389
|
+
|
|
1390
|
+
|
|
1322
1391
|
def var(x, axis=None, keepdims=False):
|
|
1323
1392
|
axis = standardize_axis_for_numpy(axis)
|
|
1324
1393
|
x = convert_to_tensor(x)
|
|
@@ -15,6 +15,7 @@ from keras.src.backend.openvino.core import compute_output_spec
|
|
|
15
15
|
from keras.src.backend.openvino.core import cond
|
|
16
16
|
from keras.src.backend.openvino.core import convert_to_numpy
|
|
17
17
|
from keras.src.backend.openvino.core import convert_to_tensor
|
|
18
|
+
from keras.src.backend.openvino.core import device_scope
|
|
18
19
|
from keras.src.backend.openvino.core import is_tensor
|
|
19
20
|
from keras.src.backend.openvino.core import random_seed_dtype
|
|
20
21
|
from keras.src.backend.openvino.core import shape
|
|
@@ -13,7 +13,6 @@ from openvino import compile_model
|
|
|
13
13
|
from keras.src import tree
|
|
14
14
|
from keras.src.backend.common import KerasVariable
|
|
15
15
|
from keras.src.backend.common import dtypes
|
|
16
|
-
from keras.src.backend.common import global_state
|
|
17
16
|
from keras.src.backend.common import standardize_dtype
|
|
18
17
|
from keras.src.backend.common.dtypes import result_type
|
|
19
18
|
from keras.src.backend.common.keras_tensor import KerasTensor
|
|
@@ -530,31 +529,11 @@ def ov_to_keras_type(ov_type):
|
|
|
530
529
|
|
|
531
530
|
@contextlib.contextmanager
|
|
532
531
|
def device_scope(device_name):
|
|
533
|
-
|
|
534
|
-
global_state.set_global_attribute("openvino_device", current_device)
|
|
532
|
+
yield
|
|
535
533
|
|
|
536
534
|
|
|
537
535
|
def get_device():
|
|
538
|
-
|
|
539
|
-
if device is None:
|
|
540
|
-
return "CPU"
|
|
541
|
-
return device
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
def _parse_device_input(device_name):
|
|
545
|
-
if isinstance(device_name, str):
|
|
546
|
-
# We support string value like "cpu:0", "gpu:1", and need to convert
|
|
547
|
-
# "gpu" to "cuda"
|
|
548
|
-
device_name = device_name.upper()
|
|
549
|
-
device_type, _ = device_name.split(":")
|
|
550
|
-
return device_type
|
|
551
|
-
else:
|
|
552
|
-
raise ValueError(
|
|
553
|
-
"Invalid value for argument `device_name`. "
|
|
554
|
-
"Expected a string like 'gpu:0' or 'cpu'. "
|
|
555
|
-
f"Received: device_name='{device_name}'"
|
|
556
|
-
)
|
|
557
|
-
return device_name
|
|
536
|
+
return "CPU"
|
|
558
537
|
|
|
559
538
|
|
|
560
539
|
class Variable(KerasVariable):
|
|
@@ -56,3 +56,7 @@ def svd(x, full_matrices=True, compute_uv=True):
|
|
|
56
56
|
|
|
57
57
|
def lstsq(a, b, rcond=None):
|
|
58
58
|
raise NotImplementedError("`lstsq` is not supported with openvino backend")
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def jvp(fun, primals, tangents, has_aux=False):
|
|
62
|
+
raise NotImplementedError("`jvp` is not supported with openvino backend")
|
keras/src/backend/openvino/nn.py
CHANGED
|
@@ -2,6 +2,7 @@ import openvino.opset14 as ov_opset
|
|
|
2
2
|
from openvino import Type
|
|
3
3
|
|
|
4
4
|
from keras.src import backend
|
|
5
|
+
from keras.src.backend.openvino.core import OPENVINO_DTYPES
|
|
5
6
|
from keras.src.backend.openvino.core import OpenVINOKerasTensor
|
|
6
7
|
from keras.src.backend.openvino.core import get_ov_output
|
|
7
8
|
|
|
@@ -16,6 +17,23 @@ def relu6(x):
|
|
|
16
17
|
return OpenVINOKerasTensor(ov_opset.clamp(x, 0.0, 6.0).output(0))
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def celu(x, alpha=1.0):
|
|
21
|
+
x = get_ov_output(x)
|
|
22
|
+
const_zero = get_ov_output(0.0, x.get_element_type())
|
|
23
|
+
const_alpha = get_ov_output(alpha, x.get_element_type())
|
|
24
|
+
const_one = get_ov_output(1.0, x.get_element_type())
|
|
25
|
+
exp_x_div_alpha = ov_opset.exp(ov_opset.divide(x, const_alpha)).output(0)
|
|
26
|
+
negative_branch = ov_opset.multiply(
|
|
27
|
+
const_alpha, ov_opset.subtract(exp_x_div_alpha, const_one)
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
celu_x = ov_opset.add(
|
|
31
|
+
ov_opset.maximum(x, const_zero).output(0),
|
|
32
|
+
ov_opset.minimum(negative_branch, const_zero).output(0),
|
|
33
|
+
)
|
|
34
|
+
return OpenVINOKerasTensor(celu_x.output(0))
|
|
35
|
+
|
|
36
|
+
|
|
19
37
|
def sigmoid(x):
|
|
20
38
|
x = get_ov_output(x)
|
|
21
39
|
return OpenVINOKerasTensor(ov_opset.sigmoid(x).output(0))
|
|
@@ -26,6 +44,39 @@ def tanh(x):
|
|
|
26
44
|
return OpenVINOKerasTensor(ov_opset.tanh(x).output(0))
|
|
27
45
|
|
|
28
46
|
|
|
47
|
+
def tanh_shrink(x):
|
|
48
|
+
x = get_ov_output(x)
|
|
49
|
+
return OpenVINOKerasTensor(ov_opset.subtract(x, ov_opset.tanh(x)).output(0))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def hard_tanh(x):
|
|
53
|
+
x = get_ov_output(x)
|
|
54
|
+
return OpenVINOKerasTensor(ov_opset.clamp(x, -1.0, 1.0).output(0))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def soft_shrink(x, threshold=0.5):
|
|
58
|
+
x = get_ov_output(x)
|
|
59
|
+
et = x.get_element_type()
|
|
60
|
+
thr = get_ov_output(threshold, et)
|
|
61
|
+
zero = get_ov_output(0.0, et)
|
|
62
|
+
abs_x = ov_opset.abs(x)
|
|
63
|
+
sub = ov_opset.subtract(abs_x, thr)
|
|
64
|
+
shrunk = ov_opset.maximum(sub, zero)
|
|
65
|
+
sign = ov_opset.sign(x)
|
|
66
|
+
out = ov_opset.multiply(sign, shrunk)
|
|
67
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def hard_shrink(x, threshold=0.5):
|
|
71
|
+
x = get_ov_output(x)
|
|
72
|
+
et = x.get_element_type()
|
|
73
|
+
thr = get_ov_output(threshold, et)
|
|
74
|
+
zero = get_ov_output(0.0, et)
|
|
75
|
+
cond = ov_opset.greater(ov_opset.abs(x), thr)
|
|
76
|
+
out = ov_opset.select(cond, x, zero)
|
|
77
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
78
|
+
|
|
79
|
+
|
|
29
80
|
def softplus(x):
|
|
30
81
|
x = get_ov_output(x)
|
|
31
82
|
return OpenVINOKerasTensor(ov_opset.softplus(x).output(0))
|
|
@@ -38,14 +89,15 @@ def softsign(x):
|
|
|
38
89
|
|
|
39
90
|
def silu(x):
|
|
40
91
|
x = get_ov_output(x)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
92
|
+
beta = get_ov_output(1.0, x.get_element_type())
|
|
93
|
+
return OpenVINOKerasTensor(ov_opset.swish(x, beta=beta).output(0))
|
|
44
94
|
|
|
45
95
|
|
|
46
96
|
def log_sigmoid(x):
|
|
47
|
-
|
|
48
|
-
|
|
97
|
+
x = get_ov_output(x)
|
|
98
|
+
neg_x = ov_opset.negative(x)
|
|
99
|
+
return OpenVINOKerasTensor(
|
|
100
|
+
ov_opset.negative(ov_opset.softplus(neg_x)).output(0)
|
|
49
101
|
)
|
|
50
102
|
|
|
51
103
|
|
|
@@ -58,6 +110,17 @@ def leaky_relu(x, negative_slope=0.2):
|
|
|
58
110
|
return OpenVINOKerasTensor(leaky_relu)
|
|
59
111
|
|
|
60
112
|
|
|
113
|
+
def sparse_sigmoid(x):
|
|
114
|
+
x = get_ov_output(x)
|
|
115
|
+
et = x.get_element_type()
|
|
116
|
+
one = get_ov_output(1.0, et)
|
|
117
|
+
neg_one = get_ov_output(-1.0, et)
|
|
118
|
+
half = get_ov_output(0.5, et)
|
|
119
|
+
y = ov_opset.minimum(ov_opset.maximum(x, neg_one), one)
|
|
120
|
+
out = ov_opset.multiply(half, ov_opset.add(y, one))
|
|
121
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
122
|
+
|
|
123
|
+
|
|
61
124
|
def hard_sigmoid(x):
|
|
62
125
|
x = get_ov_output(x)
|
|
63
126
|
alpha = get_ov_output(1.0 / 6.0, x.get_element_type())
|
|
@@ -121,6 +184,48 @@ def log_softmax(x, axis=-1):
|
|
|
121
184
|
return OpenVINOKerasTensor(ov_opset.log_softmax(x, axis).output(0))
|
|
122
185
|
|
|
123
186
|
|
|
187
|
+
def squareplus(x, b=4):
|
|
188
|
+
x = get_ov_output(x)
|
|
189
|
+
et = x.get_element_type()
|
|
190
|
+
b = get_ov_output(b, et)
|
|
191
|
+
two = get_ov_output(2.0, et)
|
|
192
|
+
x_squared = ov_opset.multiply(x, x)
|
|
193
|
+
inside = ov_opset.add(x_squared, b)
|
|
194
|
+
root = ov_opset.sqrt(inside)
|
|
195
|
+
summed = ov_opset.add(x, root)
|
|
196
|
+
out = ov_opset.divide(summed, two)
|
|
197
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def sparse_plus(x):
|
|
201
|
+
x = get_ov_output(x)
|
|
202
|
+
et = x.get_element_type()
|
|
203
|
+
one = get_ov_output(1.0, et)
|
|
204
|
+
neg_one = get_ov_output(-1.0, et)
|
|
205
|
+
zero = get_ov_output(0.0, et)
|
|
206
|
+
quarter = get_ov_output(0.25, et)
|
|
207
|
+
x_plus_1 = ov_opset.add(x, one)
|
|
208
|
+
quad = ov_opset.multiply(quarter, ov_opset.multiply(x_plus_1, x_plus_1))
|
|
209
|
+
leq_than_neg_one = ov_opset.less_equal(x, neg_one)
|
|
210
|
+
less_than_one = ov_opset.less(x, one)
|
|
211
|
+
out = ov_opset.select(
|
|
212
|
+
leq_than_neg_one,
|
|
213
|
+
zero,
|
|
214
|
+
ov_opset.select(less_than_one, quad, x),
|
|
215
|
+
)
|
|
216
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def threshold(x, threshold, default_value):
|
|
220
|
+
x = get_ov_output(x)
|
|
221
|
+
et = x.get_element_type()
|
|
222
|
+
thr = get_ov_output(threshold, et)
|
|
223
|
+
dv = get_ov_output(default_value, et)
|
|
224
|
+
cond = ov_opset.greater(x, thr)
|
|
225
|
+
out = ov_opset.select(cond, x, dv)
|
|
226
|
+
return OpenVINOKerasTensor(out.output(0))
|
|
227
|
+
|
|
228
|
+
|
|
124
229
|
def max_pool(
|
|
125
230
|
inputs,
|
|
126
231
|
pool_size,
|
|
@@ -128,8 +233,18 @@ def max_pool(
|
|
|
128
233
|
padding="valid",
|
|
129
234
|
data_format=None,
|
|
130
235
|
):
|
|
131
|
-
|
|
132
|
-
|
|
236
|
+
num_spatial_dims = (
|
|
237
|
+
get_ov_output(inputs).get_partial_shape().rank.get_length() - 2
|
|
238
|
+
)
|
|
239
|
+
kwargs = {"dilations": [1] * num_spatial_dims} # required for ov max_pool
|
|
240
|
+
return _pool(
|
|
241
|
+
inputs,
|
|
242
|
+
pool_size,
|
|
243
|
+
ov_opset.max_pool,
|
|
244
|
+
strides,
|
|
245
|
+
padding,
|
|
246
|
+
data_format,
|
|
247
|
+
**kwargs,
|
|
133
248
|
)
|
|
134
249
|
|
|
135
250
|
|
|
@@ -140,11 +255,62 @@ def average_pool(
|
|
|
140
255
|
padding="valid",
|
|
141
256
|
data_format=None,
|
|
142
257
|
):
|
|
143
|
-
|
|
144
|
-
|
|
258
|
+
return _pool(
|
|
259
|
+
inputs,
|
|
260
|
+
pool_size,
|
|
261
|
+
ov_opset.avg_pool,
|
|
262
|
+
strides,
|
|
263
|
+
padding,
|
|
264
|
+
data_format,
|
|
265
|
+
exclude_pad=True,
|
|
145
266
|
)
|
|
146
267
|
|
|
147
268
|
|
|
269
|
+
def adaptive_average_pool(inputs, output_size, data_format=None):
|
|
270
|
+
"""Adaptive average pooling - OpenVINO backend not yet supported."""
|
|
271
|
+
raise NotImplementedError("Adaptive pooling not implemented for OpenVINO.")
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def adaptive_max_pool(inputs, output_size, data_format=None):
|
|
275
|
+
"""Adaptive max pooling - OpenVINO backend not yet supported."""
|
|
276
|
+
raise NotImplementedError("Adaptive pooling not implemented for OpenVINO.")
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def _pool(
|
|
280
|
+
inputs,
|
|
281
|
+
pool_size,
|
|
282
|
+
pooling_func,
|
|
283
|
+
strides=None,
|
|
284
|
+
padding="valid",
|
|
285
|
+
data_format=None,
|
|
286
|
+
**kwargs,
|
|
287
|
+
):
|
|
288
|
+
data_format = backend.standardize_data_format(data_format)
|
|
289
|
+
inputs = get_ov_output(inputs)
|
|
290
|
+
|
|
291
|
+
num_spatial_dims = inputs.get_partial_shape().rank.get_length() - 2
|
|
292
|
+
if isinstance(pool_size, int):
|
|
293
|
+
pool_size = [pool_size] * num_spatial_dims
|
|
294
|
+
|
|
295
|
+
if strides is None:
|
|
296
|
+
strides = pool_size
|
|
297
|
+
|
|
298
|
+
strides = _adjust_strides_dilation(strides, num_spatial_dims)
|
|
299
|
+
pad_mode, pads_begin, pads_end = _adjust_padding(padding)
|
|
300
|
+
inputs = _adjust_input(inputs, num_spatial_dims, data_format)
|
|
301
|
+
pool_kwargs = {
|
|
302
|
+
"kernel_shape": pool_size,
|
|
303
|
+
"strides": strides,
|
|
304
|
+
"auto_pad": pad_mode,
|
|
305
|
+
"pads_begin": pads_begin,
|
|
306
|
+
"pads_end": pads_end,
|
|
307
|
+
**kwargs,
|
|
308
|
+
}
|
|
309
|
+
pooled = pooling_func(inputs, **pool_kwargs).output(0)
|
|
310
|
+
adjusted_pooled = _adjust_outputs(pooled, num_spatial_dims, data_format)
|
|
311
|
+
return OpenVINOKerasTensor(adjusted_pooled)
|
|
312
|
+
|
|
313
|
+
|
|
148
314
|
def _adjust_strides_dilation(
|
|
149
315
|
x,
|
|
150
316
|
num_spatial_dims,
|
|
@@ -374,15 +540,33 @@ def conv_transpose(
|
|
|
374
540
|
|
|
375
541
|
|
|
376
542
|
def one_hot(x, num_classes, axis=-1, dtype=None, sparse=False):
|
|
377
|
-
|
|
378
|
-
"`
|
|
379
|
-
)
|
|
543
|
+
if sparse:
|
|
544
|
+
raise ValueError("`sparse=True` is not supported with openvino backend")
|
|
545
|
+
x = get_ov_output(x)
|
|
546
|
+
if dtype is None:
|
|
547
|
+
dtype = backend.floatx()
|
|
548
|
+
ov_dtype = OPENVINO_DTYPES[dtype]
|
|
549
|
+
on_value = get_ov_output(1, ov_dtype)
|
|
550
|
+
off_value = get_ov_output(0, ov_dtype)
|
|
551
|
+
one_hot_encoded = ov_opset.one_hot(
|
|
552
|
+
x,
|
|
553
|
+
depth=num_classes,
|
|
554
|
+
axis=axis,
|
|
555
|
+
on_value=on_value,
|
|
556
|
+
off_value=off_value,
|
|
557
|
+
).output(0)
|
|
558
|
+
return OpenVINOKerasTensor(one_hot_encoded)
|
|
380
559
|
|
|
381
560
|
|
|
382
561
|
def multi_hot(x, num_classes, axis=-1, dtype=None, sparse=False):
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
562
|
+
reduction_axis = 1 if len(x.shape) > 1 else 0
|
|
563
|
+
if backend.standardize_dtype(dtype) == "bool":
|
|
564
|
+
outputs = one_hot(x, num_classes, axis=axis, dtype=dtype, sparse=sparse)
|
|
565
|
+
result = ov_opset.reduce_logical_or(outputs, reduction_axis)
|
|
566
|
+
else:
|
|
567
|
+
outputs = one_hot(x, num_classes, axis=axis, dtype=dtype)
|
|
568
|
+
result = ov_opset.reduce_max(outputs, reduction_axis)
|
|
569
|
+
return OpenVINOKerasTensor(result.output(0))
|
|
386
570
|
|
|
387
571
|
|
|
388
572
|
def categorical_crossentropy(target, output, from_logits=False, axis=-1):
|
|
@@ -465,9 +649,15 @@ def batch_normalization(
|
|
|
465
649
|
|
|
466
650
|
|
|
467
651
|
def ctc_loss(target, output, target_length, output_length, mask_index=0):
|
|
468
|
-
|
|
469
|
-
|
|
652
|
+
target = get_ov_output(target)
|
|
653
|
+
output = get_ov_output(output)
|
|
654
|
+
target_length = get_ov_output(target_length)
|
|
655
|
+
output_length = get_ov_output(output_length)
|
|
656
|
+
ctc_loss_ = ov_opset.ctc_loss(
|
|
657
|
+
output, output_length, target, target_length, blank_index=mask_index
|
|
470
658
|
)
|
|
659
|
+
ctc_loss_ = ov_opset.convert(ctc_loss_, OPENVINO_DTYPES[backend.floatx()])
|
|
660
|
+
return OpenVINOKerasTensor(ctc_loss_.output(0))
|
|
471
661
|
|
|
472
662
|
|
|
473
663
|
def ctc_decode(
|
|
@@ -485,7 +675,27 @@ def ctc_decode(
|
|
|
485
675
|
|
|
486
676
|
|
|
487
677
|
def psnr(x1, x2, max_val):
|
|
488
|
-
|
|
678
|
+
from keras.src.backend.openvino.numpy import log10
|
|
679
|
+
|
|
680
|
+
x1 = get_ov_output(x1)
|
|
681
|
+
x2 = get_ov_output(x2)
|
|
682
|
+
max_val = get_ov_output(max_val, x1.get_element_type())
|
|
683
|
+
diff = ov_opset.subtract(x1, x2)
|
|
684
|
+
squared_diff = ov_opset.multiply(diff, diff)
|
|
685
|
+
reduction_axes = list(range(0, x1.get_partial_shape().rank.get_length()))
|
|
686
|
+
mse = ov_opset.reduce_mean(squared_diff, reduction_axes).output(0)
|
|
687
|
+
log_max_val = get_ov_output(log10(OpenVINOKerasTensor(max_val)))
|
|
688
|
+
log_mse = get_ov_output(log10(OpenVINOKerasTensor(mse)))
|
|
689
|
+
|
|
690
|
+
psnr = ov_opset.subtract(
|
|
691
|
+
ov_opset.multiply(
|
|
692
|
+
ov_opset.constant(20, log_max_val.get_element_type()), log_max_val
|
|
693
|
+
),
|
|
694
|
+
ov_opset.multiply(
|
|
695
|
+
ov_opset.constant(10, log_mse.get_element_type()), log_mse
|
|
696
|
+
),
|
|
697
|
+
).output(0)
|
|
698
|
+
return OpenVINOKerasTensor(psnr)
|
|
489
699
|
|
|
490
700
|
|
|
491
701
|
def dot_product_attention(
|
|
@@ -499,6 +709,47 @@ def dot_product_attention(
|
|
|
499
709
|
flash_attention=None,
|
|
500
710
|
attn_logits_soft_cap=None,
|
|
501
711
|
):
|
|
502
|
-
|
|
503
|
-
|
|
712
|
+
if bias is not None:
|
|
713
|
+
raise NotImplementedError(
|
|
714
|
+
"`dot_product_attention` with `bias` is not supported "
|
|
715
|
+
"with openvino backend"
|
|
716
|
+
)
|
|
717
|
+
if flash_attention:
|
|
718
|
+
raise NotImplementedError(
|
|
719
|
+
"`dot_product_attention` with `flash_attention` is not supported "
|
|
720
|
+
"with openvino backend"
|
|
721
|
+
)
|
|
722
|
+
if attn_logits_soft_cap is not None:
|
|
723
|
+
raise NotImplementedError(
|
|
724
|
+
"`dot_product_attention` with `attn_logits_soft_cap` is not "
|
|
725
|
+
"supported with openvino backend"
|
|
726
|
+
)
|
|
727
|
+
query = get_ov_output(query)
|
|
728
|
+
key = get_ov_output(key)
|
|
729
|
+
value = get_ov_output(value)
|
|
730
|
+
if query.get_element_type() != key.get_element_type():
|
|
731
|
+
ov_type = OPENVINO_DTYPES[backend.floatx()]
|
|
732
|
+
query = ov_opset.convert(query, ov_type).output(0)
|
|
733
|
+
key = ov_opset.convert(key, ov_type).output(0)
|
|
734
|
+
if value.get_element_type() != query.get_element_type():
|
|
735
|
+
value = ov_opset.convert(value, query.get_element_type()).output(0)
|
|
736
|
+
axes_const = ov_opset.constant([0, 2, 1, 3], Type.i32).output(0)
|
|
737
|
+
|
|
738
|
+
query = ov_opset.transpose(query, axes_const)
|
|
739
|
+
key = ov_opset.transpose(key, axes_const)
|
|
740
|
+
value = ov_opset.transpose(value, axes_const)
|
|
741
|
+
mask = get_ov_output(mask) if mask is not None else None
|
|
742
|
+
scale = (
|
|
743
|
+
get_ov_output(scale, query.get_element_type())
|
|
744
|
+
if scale is not None
|
|
745
|
+
else None
|
|
746
|
+
)
|
|
747
|
+
dpa = ov_opset.scaled_dot_product_attention(
|
|
748
|
+
query, key, value, attention_mask=mask, scale=scale, causal=is_causal
|
|
504
749
|
)
|
|
750
|
+
dpa = ov_opset.transpose(dpa, axes_const)
|
|
751
|
+
return OpenVINOKerasTensor(dpa.output(0))
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
def unfold(input, kernel_size, dilation=1, padding=0, stride=1):
|
|
755
|
+
raise NotImplementedError("`unfold` is not supported with openvino backend")
|