keras-nightly 3.12.0.dev2025100503__py3-none-any.whl → 3.14.0.dev2026011604__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. keras/__init__.py +1 -0
  2. keras/_tf_keras/keras/__init__.py +1 -0
  3. keras/_tf_keras/keras/callbacks/__init__.py +3 -0
  4. keras/_tf_keras/keras/distillation/__init__.py +16 -0
  5. keras/_tf_keras/keras/distribution/__init__.py +3 -0
  6. keras/_tf_keras/keras/dtype_policies/__init__.py +3 -0
  7. keras/_tf_keras/keras/layers/__init__.py +21 -0
  8. keras/_tf_keras/keras/ops/__init__.py +13 -0
  9. keras/_tf_keras/keras/ops/image/__init__.py +1 -0
  10. keras/_tf_keras/keras/ops/linalg/__init__.py +1 -0
  11. keras/_tf_keras/keras/ops/nn/__init__.py +3 -0
  12. keras/_tf_keras/keras/ops/numpy/__init__.py +9 -0
  13. keras/_tf_keras/keras/quantizers/__init__.py +13 -0
  14. keras/callbacks/__init__.py +3 -0
  15. keras/distillation/__init__.py +16 -0
  16. keras/distribution/__init__.py +3 -0
  17. keras/dtype_policies/__init__.py +3 -0
  18. keras/layers/__init__.py +21 -0
  19. keras/ops/__init__.py +13 -0
  20. keras/ops/image/__init__.py +1 -0
  21. keras/ops/linalg/__init__.py +1 -0
  22. keras/ops/nn/__init__.py +3 -0
  23. keras/ops/numpy/__init__.py +9 -0
  24. keras/quantizers/__init__.py +13 -0
  25. keras/src/applications/imagenet_utils.py +4 -1
  26. keras/src/backend/common/backend_utils.py +30 -6
  27. keras/src/backend/common/name_scope.py +2 -1
  28. keras/src/backend/common/variables.py +30 -15
  29. keras/src/backend/jax/core.py +92 -3
  30. keras/src/backend/jax/distribution_lib.py +16 -2
  31. keras/src/backend/jax/linalg.py +4 -0
  32. keras/src/backend/jax/nn.py +509 -29
  33. keras/src/backend/jax/numpy.py +59 -8
  34. keras/src/backend/jax/trainer.py +14 -2
  35. keras/src/backend/numpy/linalg.py +4 -0
  36. keras/src/backend/numpy/nn.py +311 -1
  37. keras/src/backend/numpy/numpy.py +65 -2
  38. keras/src/backend/openvino/__init__.py +1 -0
  39. keras/src/backend/openvino/core.py +2 -23
  40. keras/src/backend/openvino/linalg.py +4 -0
  41. keras/src/backend/openvino/nn.py +271 -20
  42. keras/src/backend/openvino/numpy.py +943 -189
  43. keras/src/backend/tensorflow/layer.py +43 -9
  44. keras/src/backend/tensorflow/linalg.py +24 -0
  45. keras/src/backend/tensorflow/nn.py +545 -1
  46. keras/src/backend/tensorflow/numpy.py +250 -50
  47. keras/src/backend/torch/core.py +3 -1
  48. keras/src/backend/torch/linalg.py +4 -0
  49. keras/src/backend/torch/nn.py +125 -0
  50. keras/src/backend/torch/numpy.py +80 -2
  51. keras/src/callbacks/__init__.py +1 -0
  52. keras/src/callbacks/model_checkpoint.py +5 -0
  53. keras/src/callbacks/orbax_checkpoint.py +332 -0
  54. keras/src/callbacks/terminate_on_nan.py +54 -5
  55. keras/src/datasets/cifar10.py +5 -0
  56. keras/src/distillation/__init__.py +1 -0
  57. keras/src/distillation/distillation_loss.py +390 -0
  58. keras/src/distillation/distiller.py +598 -0
  59. keras/src/distribution/distribution_lib.py +14 -0
  60. keras/src/dtype_policies/__init__.py +2 -0
  61. keras/src/dtype_policies/dtype_policy.py +90 -1
  62. keras/src/export/__init__.py +2 -0
  63. keras/src/export/export_utils.py +39 -2
  64. keras/src/export/litert.py +248 -0
  65. keras/src/export/openvino.py +1 -1
  66. keras/src/export/tf2onnx_lib.py +3 -0
  67. keras/src/layers/__init__.py +13 -0
  68. keras/src/layers/activations/softmax.py +9 -4
  69. keras/src/layers/attention/multi_head_attention.py +4 -1
  70. keras/src/layers/core/dense.py +241 -111
  71. keras/src/layers/core/einsum_dense.py +316 -131
  72. keras/src/layers/core/embedding.py +84 -94
  73. keras/src/layers/core/input_layer.py +1 -0
  74. keras/src/layers/core/reversible_embedding.py +399 -0
  75. keras/src/layers/input_spec.py +17 -17
  76. keras/src/layers/layer.py +45 -15
  77. keras/src/layers/merging/dot.py +4 -1
  78. keras/src/layers/pooling/adaptive_average_pooling1d.py +65 -0
  79. keras/src/layers/pooling/adaptive_average_pooling2d.py +62 -0
  80. keras/src/layers/pooling/adaptive_average_pooling3d.py +63 -0
  81. keras/src/layers/pooling/adaptive_max_pooling1d.py +65 -0
  82. keras/src/layers/pooling/adaptive_max_pooling2d.py +62 -0
  83. keras/src/layers/pooling/adaptive_max_pooling3d.py +63 -0
  84. keras/src/layers/pooling/base_adaptive_pooling.py +63 -0
  85. keras/src/layers/preprocessing/discretization.py +6 -5
  86. keras/src/layers/preprocessing/feature_space.py +8 -4
  87. keras/src/layers/preprocessing/image_preprocessing/aug_mix.py +2 -2
  88. keras/src/layers/preprocessing/image_preprocessing/random_contrast.py +3 -3
  89. keras/src/layers/preprocessing/image_preprocessing/resizing.py +10 -0
  90. keras/src/layers/preprocessing/index_lookup.py +19 -1
  91. keras/src/layers/preprocessing/normalization.py +14 -1
  92. keras/src/layers/regularization/dropout.py +43 -1
  93. keras/src/layers/rnn/rnn.py +19 -0
  94. keras/src/losses/loss.py +1 -1
  95. keras/src/losses/losses.py +24 -0
  96. keras/src/metrics/confusion_metrics.py +7 -6
  97. keras/src/models/cloning.py +4 -0
  98. keras/src/models/functional.py +11 -3
  99. keras/src/models/model.py +172 -34
  100. keras/src/ops/image.py +257 -20
  101. keras/src/ops/linalg.py +93 -0
  102. keras/src/ops/nn.py +258 -0
  103. keras/src/ops/numpy.py +569 -36
  104. keras/src/optimizers/muon.py +65 -31
  105. keras/src/optimizers/schedules/learning_rate_schedule.py +4 -3
  106. keras/src/quantizers/__init__.py +14 -1
  107. keras/src/quantizers/awq.py +361 -0
  108. keras/src/quantizers/awq_config.py +140 -0
  109. keras/src/quantizers/awq_core.py +217 -0
  110. keras/src/quantizers/gptq.py +2 -8
  111. keras/src/quantizers/gptq_config.py +36 -1
  112. keras/src/quantizers/gptq_core.py +65 -79
  113. keras/src/quantizers/quantization_config.py +246 -0
  114. keras/src/quantizers/quantizers.py +127 -61
  115. keras/src/quantizers/utils.py +23 -0
  116. keras/src/random/seed_generator.py +6 -4
  117. keras/src/saving/file_editor.py +81 -6
  118. keras/src/saving/orbax_util.py +26 -0
  119. keras/src/saving/saving_api.py +37 -14
  120. keras/src/saving/saving_lib.py +1 -1
  121. keras/src/testing/__init__.py +1 -0
  122. keras/src/testing/test_case.py +45 -5
  123. keras/src/utils/backend_utils.py +31 -4
  124. keras/src/utils/dataset_utils.py +234 -35
  125. keras/src/utils/file_utils.py +49 -11
  126. keras/src/utils/image_utils.py +14 -2
  127. keras/src/utils/jax_layer.py +244 -55
  128. keras/src/utils/module_utils.py +29 -0
  129. keras/src/utils/progbar.py +10 -2
  130. keras/src/utils/rng_utils.py +9 -1
  131. keras/src/utils/tracking.py +5 -5
  132. keras/src/version.py +1 -1
  133. {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/METADATA +16 -6
  134. {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/RECORD +136 -115
  135. {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/WHEEL +0 -0
  136. {keras_nightly-3.12.0.dev2025100503.dist-info → keras_nightly-3.14.0.dev2026011604.dist-info}/top_level.txt +0 -0
keras/src/ops/numpy.py CHANGED
@@ -301,33 +301,6 @@ def all(x, axis=None, keepdims=False):
301
301
  return backend.numpy.all(x, axis=axis, keepdims=keepdims)
302
302
 
303
303
 
304
- class Any(Operation):
305
- def __init__(self, axis=None, keepdims=False, *, name=None):
306
- super().__init__(name=name)
307
- if isinstance(axis, int):
308
- self.axis = [axis]
309
- else:
310
- self.axis = axis
311
- self.keepdims = keepdims
312
-
313
- def call(self, x):
314
- return backend.numpy.any(
315
- x,
316
- axis=self.axis,
317
- keepdims=self.keepdims,
318
- )
319
-
320
- def compute_output_spec(self, x):
321
- return KerasTensor(
322
- reduce_shape(
323
- x.shape,
324
- axis=self.axis,
325
- keepdims=self.keepdims,
326
- ),
327
- dtype="bool",
328
- )
329
-
330
-
331
304
  class Angle(Operation):
332
305
  def call(self, x):
333
306
  return backend.numpy.angle(x)
@@ -363,6 +336,33 @@ def angle(x):
363
336
  return backend.numpy.angle(x)
364
337
 
365
338
 
339
+ class Any(Operation):
340
+ def __init__(self, axis=None, keepdims=False, *, name=None):
341
+ super().__init__(name=name)
342
+ if isinstance(axis, int):
343
+ self.axis = [axis]
344
+ else:
345
+ self.axis = axis
346
+ self.keepdims = keepdims
347
+
348
+ def call(self, x):
349
+ return backend.numpy.any(
350
+ x,
351
+ axis=self.axis,
352
+ keepdims=self.keepdims,
353
+ )
354
+
355
+ def compute_output_spec(self, x):
356
+ return KerasTensor(
357
+ reduce_shape(
358
+ x.shape,
359
+ axis=self.axis,
360
+ keepdims=self.keepdims,
361
+ ),
362
+ dtype="bool",
363
+ )
364
+
365
+
366
366
  @keras_export(["keras.ops.any", "keras.ops.numpy.any"])
367
367
  def any(x, axis=None, keepdims=False):
368
368
  """Test whether any array element along a given axis evaluates to `True`.
@@ -924,6 +924,11 @@ def arctanh(x):
924
924
 
925
925
  Returns:
926
926
  Output tensor of same shape as `x`.
927
+
928
+ Example:
929
+ >>> x = keras.ops.convert_to_tensor([0, -0.5])
930
+ >>> keras.ops.arctanh(x)
931
+ array([ 0. , -0.54930615], dtype=float32)
927
932
  """
928
933
  if any_symbolic_tensors((x,)):
929
934
  return Arctanh().symbolic_call(x)
@@ -1124,6 +1129,68 @@ def array(x, dtype=None):
1124
1129
  return backend.numpy.array(x, dtype=dtype)
1125
1130
 
1126
1131
 
1132
+ class View(Operation):
1133
+ def __init__(self, dtype=None, *, name=None):
1134
+ super().__init__(name=name)
1135
+ self.dtype = None if dtype is None else backend.standardize_dtype(dtype)
1136
+
1137
+ def call(self, x):
1138
+ return backend.numpy.view(x, dtype=self.dtype)
1139
+
1140
+ def compute_output_spec(self, x):
1141
+ old_dtype = backend.standardize_dtype(x.dtype)
1142
+ new_dtype = backend.standardize_dtype(
1143
+ self.dtype if self.dtype else x.dtype
1144
+ )
1145
+
1146
+ old_itemsize = np.dtype(old_dtype).itemsize
1147
+ new_itemsize = np.dtype(new_dtype).itemsize
1148
+
1149
+ if old_itemsize == new_itemsize:
1150
+ return KerasTensor(x.shape, dtype=new_dtype)
1151
+
1152
+ if not x.shape:
1153
+ raise ValueError(
1154
+ "Cannot view a scalar as a different dtype if item sizes "
1155
+ "are different."
1156
+ )
1157
+
1158
+ output_shape = list(x.shape)
1159
+ if output_shape[-1] is not None:
1160
+ if (output_shape[-1] * old_itemsize) % new_itemsize != 0:
1161
+ raise ValueError(
1162
+ f"Cannot view array of shape {x.shape} and dtype {x.dtype} "
1163
+ f"as dtype {new_dtype} because the total number of bytes "
1164
+ "is not divisible by the new itemsize."
1165
+ )
1166
+ output_shape[-1] = output_shape[-1] * old_itemsize // new_itemsize
1167
+ return KerasTensor(tuple(output_shape), dtype=new_dtype)
1168
+
1169
+
1170
+ @keras_export(["keras.ops.view", "keras.ops.numpy.view"])
1171
+ def view(x, dtype=None):
1172
+ """Create a new bitwise view of the same data with the specified dtype.
1173
+
1174
+ Args:
1175
+ x: Input tensor.
1176
+ dtype: Data-type descriptor of the returned view,
1177
+ e.g., float32 or int16.
1178
+
1179
+ Returns:
1180
+ View of a tensor with data type dtype.
1181
+
1182
+ Examples:
1183
+ >>> x = keras.ops.array([1, 2, 3])
1184
+ >>> x
1185
+ array([1, 2, 3], dtype=int32)
1186
+ >>> keras.ops.view(x, dtype="float32")
1187
+ array([1.0e-45, 3.0e-45, 4.0e-45], dtype=float32)
1188
+ """
1189
+ if any_symbolic_tensors((x,)):
1190
+ return View(dtype=dtype).symbolic_call(x)
1191
+ return backend.numpy.view(x, dtype=dtype)
1192
+
1193
+
1127
1194
  class Average(Operation):
1128
1195
  def __init__(self, axis=None, *, name=None):
1129
1196
  super().__init__(name=name)
@@ -3052,6 +3119,48 @@ def empty(shape, dtype=None):
3052
3119
  return backend.numpy.empty(shape, dtype=dtype)
3053
3120
 
3054
3121
 
3122
+ class EmptyLike(Operation):
3123
+ def __init__(self, dtype=None, *, name=None):
3124
+ super().__init__(name=name)
3125
+ self.dtype = None if dtype is None else backend.standardize_dtype(dtype)
3126
+
3127
+ def call(self, x):
3128
+ return backend.numpy.empty_like(x, dtype=self.dtype)
3129
+
3130
+ def compute_output_spec(self, x):
3131
+ dtype = (
3132
+ backend.standardize_dtype(x.dtype)
3133
+ if self.dtype is None
3134
+ else self.dtype
3135
+ )
3136
+ return KerasTensor(x.shape, dtype=dtype)
3137
+
3138
+
3139
+ @keras_export(["keras.ops.empty_like", "keras.ops.numpy.empty_like"])
3140
+ def empty_like(x, dtype=None):
3141
+ """Return a new uninitialized tensor with the same shape and dtype as `x`.
3142
+
3143
+ Args:
3144
+ x: Input tensor to mimic shape and dtype.
3145
+ dtype: Optional data type. If None, uses `x.dtype`.
3146
+
3147
+ Returns:
3148
+ A tensor with the same shape and dtype as `x`, with arbitrary contents.
3149
+
3150
+ Example:
3151
+ >>> from keras import ops
3152
+ >>> x = ops.ones((2, 3), dtype="float32")
3153
+ >>> y = ops.empty_like(x)
3154
+ >>> y.shape
3155
+ (2, 3)
3156
+ >>> y.dtype
3157
+ dtype('float32')
3158
+ """
3159
+ if any_symbolic_tensors((x,)):
3160
+ return EmptyLike(dtype=dtype).symbolic_call(x)
3161
+ return backend.numpy.empty_like(x, dtype=dtype)
3162
+
3163
+
3055
3164
  class Equal(Operation):
3056
3165
  def call(self, x1, x2):
3057
3166
  return backend.numpy.equal(x1, x2)
@@ -3846,6 +3955,35 @@ def isposinf(x):
3846
3955
  return backend.numpy.isposinf(x)
3847
3956
 
3848
3957
 
3958
+ class Isreal(Operation):
3959
+ def call(self, x):
3960
+ return backend.numpy.isreal(x)
3961
+
3962
+ def compute_output_spec(self, x):
3963
+ return KerasTensor(x.shape, dtype="bool")
3964
+
3965
+
3966
+ @keras_export(["keras.ops.isreal", "keras.ops.numpy.isreal"])
3967
+ def isreal(x):
3968
+ """Test element-wise for real numbers.
3969
+
3970
+ Args:
3971
+ x: Input tensor.
3972
+
3973
+ Returns:
3974
+ Output boolean tensor.
3975
+
3976
+ Example:
3977
+ >>> from keras import ops
3978
+ >>> x = ops.array([1+1j, 1+0j, 4.5, 3, 2, 2j], dtype="complex64")
3979
+ >>> ops.isreal(x)
3980
+ array([False, True, True, True, True, False])
3981
+ """
3982
+ if any_symbolic_tensors((x,)):
3983
+ return Isreal().symbolic_call(x)
3984
+ return backend.numpy.isreal(x)
3985
+
3986
+
3849
3987
  class Kron(Operation):
3850
3988
  def call(self, x1, x2):
3851
3989
  return backend.numpy.kron(x1, x2)
@@ -3926,6 +4064,46 @@ def lcm(x1, x2):
3926
4064
  return backend.numpy.lcm(x1, x2)
3927
4065
 
3928
4066
 
4067
+ class Ldexp(Operation):
4068
+ def call(self, x1, x2):
4069
+ return backend.numpy.ldexp(x1, x2)
4070
+
4071
+ def compute_output_spec(self, x1, x2):
4072
+ x1_shape = getattr(x1, "shape", [])
4073
+ x2_shape = getattr(x2, "shape", [])
4074
+ output_shape = broadcast_shapes(x1_shape, x2_shape)
4075
+
4076
+ x1_type = backend.standardize_dtype(getattr(x1, "dtype", type(x1)))
4077
+ x2_type = backend.standardize_dtype(getattr(x2, "dtype", type(x2)))
4078
+ dtype = dtypes.result_type(x1_type, x2_type, float)
4079
+ return KerasTensor(output_shape, dtype=dtype)
4080
+
4081
+
4082
+ @keras_export(["keras.ops.ldexp", "keras.ops.numpy.ldexp"])
4083
+ def ldexp(x1, x2):
4084
+ """Multiply `x1` by 2 raised to the power of `x2`, element-wise.
4085
+
4086
+ This function computes:
4087
+ ldexp(x1, x2) = x1 * 2**x2
4088
+
4089
+ Args:
4090
+ x1: Float input tensor.
4091
+ x2: Integer exponent tensor.
4092
+
4093
+ Returns:
4094
+ Output tensor
4095
+
4096
+ Example:
4097
+ >>> x1 = keras.ops.convert_to_tensor([0.75, 1.5])
4098
+ >>> x2 = keras.ops.convert_to_tensor([1, 2])
4099
+ >>> keras.ops.ldexp(x1, x2)
4100
+ array([1.5, 6. ], dtype=float32)
4101
+ """
4102
+ if any_symbolic_tensors((x1, x2)):
4103
+ return Ldexp().symbolic_call(x1, x2)
4104
+ return backend.numpy.ldexp(x1, x2)
4105
+
4106
+
3929
4107
  class Less(Operation):
3930
4108
  def call(self, x1, x2):
3931
4109
  return backend.numpy.less(x1, x2)
@@ -5278,6 +5456,74 @@ def prod(x, axis=None, keepdims=False, dtype=None):
5278
5456
  return backend.numpy.prod(x, axis=axis, keepdims=keepdims, dtype=dtype)
5279
5457
 
5280
5458
 
5459
+ class Ptp(Operation):
5460
+ def __init__(self, axis=None, keepdims=False, *, name=None):
5461
+ super().__init__(name=name)
5462
+ self.axis = axis
5463
+ self.keepdims = keepdims
5464
+
5465
+ def call(self, x):
5466
+ return backend.numpy.ptp(
5467
+ x,
5468
+ axis=self.axis,
5469
+ keepdims=self.keepdims,
5470
+ )
5471
+
5472
+ def compute_output_spec(self, x):
5473
+ dtype = backend.standardize_dtype(x.dtype)
5474
+ return KerasTensor(
5475
+ reduce_shape(x.shape, axis=self.axis, keepdims=self.keepdims),
5476
+ dtype=dtype,
5477
+ )
5478
+
5479
+
5480
+ @keras_export(["keras.ops.ptp", "keras.ops.numpy.ptp"])
5481
+ def ptp(x, axis=None, keepdims=False):
5482
+ """Return the peak-to-peak (max - min) value of tensor elements
5483
+ over a given axis.
5484
+
5485
+ The peak-to-peak value is defined as the difference between the
5486
+ maximum and minimum values along the specified axis.
5487
+
5488
+ Args:
5489
+ x: Input tensor.
5490
+ axis: Axis or axes along which the peak-to-peak value is computed.
5491
+ The default, `axis=None`, will compute the peak-to-peak value
5492
+ over all elements in the input tensor.
5493
+ keepdims: If this is set to `True`, the axes which are reduced
5494
+ are left in the result as dimensions with size one.
5495
+
5496
+ Returns:
5497
+ A tensor containing the peak-to-peak values of `x` over the
5498
+ given axis or axes.
5499
+
5500
+ Examples:
5501
+ >>> x = keras.ops.array([[1., 3., 2.],
5502
+ ... [4., 0., 5.]])
5503
+
5504
+ >>> # Peak-to-peak over all elements
5505
+ >>> keras.ops.ptp(x)
5506
+ 5.0
5507
+
5508
+ >>> # Peak-to-peak along axis 1
5509
+ >>> keras.ops.ptp(x, axis=1)
5510
+ array([2., 5.], dtype=float32)
5511
+
5512
+ >>> # Peak-to-peak over multiple axes
5513
+ >>> x = keras.ops.reshape(x, (1, 2, 3))
5514
+ >>> keras.ops.ptp(x, axis=(1, 2))
5515
+ array([5.], dtype=float32)
5516
+
5517
+ >>> # Keep reduced dimensions
5518
+ >>> keras.ops.ptp(x, axis=2, keepdims=True)
5519
+ array([[[2.],
5520
+ [5.]]], dtype=float32)
5521
+ """
5522
+ if any_symbolic_tensors((x,)):
5523
+ return Ptp(axis=axis, keepdims=keepdims).symbolic_call(x)
5524
+ return backend.numpy.ptp(x, axis=axis, keepdims=keepdims)
5525
+
5526
+
5281
5527
  class Quantile(Operation):
5282
5528
  def __init__(
5283
5529
  self, axis=None, method="linear", keepdims=False, *, name=None
@@ -5418,10 +5664,10 @@ def unravel_index(indices, shape):
5418
5664
  Tuple of arrays for each dimension with unraveled indices.
5419
5665
 
5420
5666
  Example:
5421
- >>> indices = 5
5422
- >>> shape = (3, 3)
5423
- >>> unravel_index(indices, shape)
5424
- (1, 2) # 5 is at row 1, column 2 in a 3x3 array
5667
+ >>> indices = 5
5668
+ >>> shape = (3, 3)
5669
+ >>> unravel_index(indices, shape)
5670
+ (1, 2) # 5 is at row 1, column 2 in a 3x3 array
5425
5671
  """
5426
5672
  if any_symbolic_tensors((indices,)):
5427
5673
  return UnravelIndex(shape).symbolic_call(indices)
@@ -6278,6 +6524,9 @@ class Tile(Operation):
6278
6524
  repeats = self.repeats
6279
6525
  if isinstance(repeats, int):
6280
6526
  repeats = [repeats]
6527
+ else:
6528
+ repeats = list(repeats)
6529
+
6281
6530
  if len(x_shape) > len(repeats):
6282
6531
  repeats = [1] * (len(x_shape) - len(repeats)) + repeats
6283
6532
  else:
@@ -6285,10 +6534,10 @@ class Tile(Operation):
6285
6534
 
6286
6535
  output_shape = []
6287
6536
  for x_size, repeat in zip(x_shape, repeats):
6288
- if x_size is None:
6289
- output_shape.append(None)
6290
- else:
6537
+ if isinstance(x_size, int):
6291
6538
  output_shape.append(x_size * repeat)
6539
+ else:
6540
+ output_shape.append(None)
6292
6541
  return KerasTensor(output_shape, dtype=x.dtype)
6293
6542
 
6294
6543
 
@@ -6336,8 +6585,13 @@ class Trace(Operation):
6336
6585
  x_shape[self.axis2] = -1
6337
6586
  output_shape = list(filter((-1).__ne__, x_shape))
6338
6587
  output_dtype = backend.standardize_dtype(x.dtype)
6339
- if output_dtype not in ("int64", "uint32", "uint64"):
6340
- output_dtype = dtypes.result_type(output_dtype, "int32")
6588
+ if output_dtype in ("bool", "int8", "int16"):
6589
+ output_dtype = "int32"
6590
+ elif output_dtype in ("uint8", "uint16"):
6591
+ output_dtype = "uint32"
6592
+ if output_dtype == "uint32" and backend.backend() == "torch":
6593
+ # Torch backend doesn't support uint32 dtype.
6594
+ output_dtype = "int32"
6341
6595
  return KerasTensor(output_shape, dtype=output_dtype)
6342
6596
 
6343
6597
 
@@ -6918,6 +7172,49 @@ def negative(x):
6918
7172
  return backend.numpy.negative(x)
6919
7173
 
6920
7174
 
7175
+ class Nextafter(Operation):
7176
+ def call(self, x1, x2):
7177
+ return backend.numpy.nextafter(x1, x2)
7178
+
7179
+ def compute_output_spec(self, x1, x2):
7180
+ x1_shape = getattr(x1, "shape", [])
7181
+ x2_shape = getattr(x2, "shape", [])
7182
+ output_shape = broadcast_shapes(x1_shape, x2_shape)
7183
+
7184
+ x1_type = backend.standardize_dtype(getattr(x1, "dtype", type(x1)))
7185
+ x2_type = backend.standardize_dtype(getattr(x2, "dtype", type(x2)))
7186
+ dtype = dtypes.result_type(x1_type, x2_type, float)
7187
+ return KerasTensor(output_shape, dtype=dtype)
7188
+
7189
+
7190
+ @keras_export(["keras.ops.nextafter", "keras.ops.numpy.nextafter"])
7191
+ def nextafter(x1, x2):
7192
+ """
7193
+ Return the next representable floating-point value after `x1` towards `x2`.
7194
+
7195
+ This function computes the next floating-point value
7196
+ following `x1` in the direction of `x2`, element-wise.
7197
+
7198
+ Args:
7199
+ x1: Input tensor whose values will be moved to the next
7200
+ representable floating-point value.
7201
+ x2: Input tensor indicating the direction toward which
7202
+ `x1` is moved.
7203
+
7204
+ Returns:
7205
+ Output tensor
7206
+
7207
+ Example:
7208
+ >>> x1 = keras.ops.convert_to_tensor([1.0, 1.0])
7209
+ >>> x2 = keras.ops.convert_to_tensor([2.0, 0.0])
7210
+ >>> keras.ops.nextafter(x1, x2)
7211
+ array([1.0000001, 0.99999994], dtype=float32)
7212
+ """
7213
+ if any_symbolic_tensors((x1, x2)):
7214
+ return Nextafter().symbolic_call(x1, x2)
7215
+ return backend.numpy.nextafter(x1, x2)
7216
+
7217
+
6921
7218
  class Square(Operation):
6922
7219
  def call(self, x):
6923
7220
  return backend.numpy.square(x)
@@ -7054,6 +7351,48 @@ def transpose(x, axes=None):
7054
7351
  return backend.numpy.transpose(x, axes=axes)
7055
7352
 
7056
7353
 
7354
+ class Trapezoid(Operation):
7355
+ def __init__(self, x=None, dx=1.0, axis=-1, *, name=None):
7356
+ super().__init__(name=name)
7357
+ self.x = x
7358
+ self.dx = dx
7359
+ self.axis = axis
7360
+
7361
+ def call(self, y):
7362
+ return backend.numpy.trapezoid(y, x=self.x, dx=self.dx, axis=self.axis)
7363
+
7364
+ def compute_output_spec(self, y):
7365
+ out_shape = list(y.shape)
7366
+ if self.axis is not None and len(out_shape) > 0:
7367
+ out_shape.pop(self.axis % len(out_shape))
7368
+ dtype = backend.result_type(getattr(y, "dtype", type(y)), float)
7369
+ return KerasTensor(tuple(out_shape), dtype=dtype)
7370
+
7371
+
7372
+ @keras_export(["keras.ops.trapezoid", "keras.ops.numpy.trapezoid"])
7373
+ def trapezoid(y, x=None, dx=1.0, axis=-1):
7374
+ """Integrate along the given axis using the composite trapezoidal rule.
7375
+
7376
+ Args:
7377
+ y: Input tensor.
7378
+ x: Optional tensor specifying sample points corresponding to `y`.
7379
+ If `None`, spacing is assumed to be `dx`.
7380
+ dx: Spacing between sample points when `x` is `None`.
7381
+ axis: Axis along which to integrate. Default is the last axis.
7382
+
7383
+ Returns:
7384
+ The approximate integral of `y` along the given axis.
7385
+
7386
+ Example:
7387
+ >>> y = keras.ops.convert_to_tensor([[1, 2, 3], [4, 5, 6]])
7388
+ >>> keras.ops.trapezoid(y, axis=1)
7389
+ array([ 4., 10.], dtype=float32)
7390
+ """
7391
+ if any_symbolic_tensors((y,)):
7392
+ return Trapezoid(x=x, dx=dx, axis=axis).symbolic_call(y)
7393
+ return backend.numpy.trapezoid(y, x=x, dx=dx, axis=axis)
7394
+
7395
+
7057
7396
  class Mean(Operation):
7058
7397
  def __init__(self, axis=None, keepdims=False, *, name=None):
7059
7398
  super().__init__(name=name)
@@ -7099,6 +7438,77 @@ def mean(x, axis=None, keepdims=False):
7099
7438
  return backend.numpy.mean(x, axis=axis, keepdims=keepdims)
7100
7439
 
7101
7440
 
7441
+ class Vander(Operation):
7442
+ def __init__(self, N=None, increasing=False, *, name=None):
7443
+ super().__init__(name=name)
7444
+ self.N = N
7445
+ self.increasing = increasing
7446
+
7447
+ def call(self, x):
7448
+ return backend.numpy.vander(x, self.N, self.increasing)
7449
+
7450
+ def compute_output_spec(self, x):
7451
+ if self.N is None:
7452
+ N = x.shape[0]
7453
+ else:
7454
+ N = self.N
7455
+
7456
+ out_shape = x.shape + (N,)
7457
+ return KerasTensor(tuple(out_shape), dtype=x.dtype)
7458
+
7459
+
7460
+ @keras_export(["keras.ops.vander", "keras.ops.numpy.vander"])
7461
+ def vander(x, N=None, increasing=False):
7462
+ """Generate a Vandermonde matrix.
7463
+
7464
+ Args:
7465
+ x: 1D input tensor.
7466
+ N: Number of columns. If `None`, `N` = `len(x)`.
7467
+ increasing: Order of powers. If True, powers increase left to right.
7468
+
7469
+ Returns:
7470
+ Output tensor, Vandermonde matrix of shape `(len(x), N)`.
7471
+
7472
+ Example:
7473
+ >>> import numpy as np
7474
+ >>> import keras
7475
+ >>> x = np.array([1, 2, 3, 5])
7476
+ >>> keras.ops.vander(x)
7477
+ array([[ 1, 1, 1, 1],
7478
+ [ 8, 4, 2, 1],
7479
+ [ 27, 9, 3, 1],
7480
+ [125, 25, 5, 1]])
7481
+ """
7482
+
7483
+ if len(x.shape) != 1:
7484
+ raise ValueError(
7485
+ "Input tensor must be 1-dimensional. "
7486
+ f"Received: input.shape={x.shape}"
7487
+ )
7488
+
7489
+ if N is not None:
7490
+ if not isinstance(N, int):
7491
+ raise TypeError(
7492
+ f"Argument `N` must be of type `int`. "
7493
+ f"Received: N={N} of type {type(N)}"
7494
+ )
7495
+
7496
+ if N < 0:
7497
+ raise ValueError(
7498
+ f"Argument 'N' must be nonnegative. Received: N={N}"
7499
+ )
7500
+
7501
+ if not isinstance(increasing, bool):
7502
+ raise TypeError(
7503
+ f"Argument `increasing` must be of type `bool`. "
7504
+ f"Received: increasing={increasing} of type {type(increasing)}"
7505
+ )
7506
+
7507
+ if any_symbolic_tensors((x,)):
7508
+ return Vander(N=N, increasing=increasing).symbolic_call(x)
7509
+ return backend.numpy.vander(x, N=N, increasing=increasing)
7510
+
7511
+
7102
7512
  class Var(Operation):
7103
7513
  def __init__(self, axis=None, keepdims=False, *, name=None):
7104
7514
  super().__init__(name=name)
@@ -7228,6 +7638,19 @@ def eye(N, M=None, k=0, dtype=None):
7228
7638
  Returns:
7229
7639
  Tensor with ones on the k-th diagonal and zeros elsewhere.
7230
7640
  """
7641
+
7642
+ def is_floating_type(v):
7643
+ return (
7644
+ isinstance(v, float)
7645
+ or getattr(v, "dtype", None) in dtypes.FLOAT_TYPES
7646
+ )
7647
+
7648
+ if is_floating_type(N):
7649
+ raise TypeError("Argument `N` must be an integer or an integer tensor.")
7650
+ if is_floating_type(M):
7651
+ raise TypeError(
7652
+ "Argument `M` must be an integer, an integer tensor, or `None`."
7653
+ )
7231
7654
  return backend.numpy.eye(N, M=M, k=k, dtype=dtype)
7232
7655
 
7233
7656
 
@@ -7379,6 +7802,15 @@ def correlate(x1, x2, mode="valid"):
7379
7802
 
7380
7803
  Returns:
7381
7804
  Output tensor, cross-correlation of `x1` and `x2`.
7805
+
7806
+ Notes:
7807
+ Complex-valued inputs are currently not fully supported on the
7808
+ TensorFlow and PyTorch backends. When complex tensors are passed,
7809
+ they are cast to floating-point types and the imaginary component
7810
+ is discarded.
7811
+
7812
+ This behavior is documented for clarity and may change in the
7813
+ future. See discussion in issue #21617.
7382
7814
  """
7383
7815
  if any_symbolic_tensors((x1, x2)):
7384
7816
  return Correlate(mode=mode).symbolic_call(x1, x2)
@@ -7611,3 +8043,104 @@ def histogram(x, bins=10, range=None):
7611
8043
  f"Received: input.shape={x.shape}"
7612
8044
  )
7613
8045
  return backend.numpy.histogram(x, bins=bins, range=range)
8046
+
8047
+
8048
+ class ArraySplit(Operation):
8049
+ def __init__(self, indices_or_sections, axis=0, *, name=None):
8050
+ super().__init__(name=name)
8051
+
8052
+ self.indices_or_sections = indices_or_sections
8053
+ self.axis = axis
8054
+
8055
+ def call(self, x):
8056
+ return backend.numpy.array_split(
8057
+ x,
8058
+ indices_or_sections=self.indices_or_sections,
8059
+ axis=self.axis,
8060
+ )
8061
+
8062
+ def compute_output_spec(self, x):
8063
+ num_splits = self.indices_or_sections
8064
+
8065
+ axis = self.axis
8066
+ if axis < 0:
8067
+ axis += len(x.shape)
8068
+
8069
+ total_size = x.shape[axis]
8070
+
8071
+ if total_size is None:
8072
+ output_specs = []
8073
+ base_shape = list(x.shape)
8074
+ base_shape[axis] = None
8075
+ for _ in range(num_splits):
8076
+ output_specs.append(
8077
+ KerasTensor(shape=tuple(base_shape), dtype=x.dtype)
8078
+ )
8079
+ return tuple(output_specs)
8080
+
8081
+ split_size = total_size // num_splits
8082
+ remainder = total_size % num_splits
8083
+
8084
+ output_specs = []
8085
+ base_shape = list(x.shape)
8086
+ for i in range(num_splits):
8087
+ size = split_size + (1 if i < remainder else 0)
8088
+ shape = base_shape.copy()
8089
+ shape[axis] = size
8090
+ output_specs.append(KerasTensor(shape=tuple(shape), dtype=x.dtype))
8091
+
8092
+ return list(output_specs)
8093
+
8094
+
8095
+ @keras_export(["keras.ops.array_split", "keras.ops.numpy.array_split"])
8096
+ def array_split(x, indices_or_sections, axis=0):
8097
+ """Splits an array into multiple sub-arrays (unevenly).
8098
+
8099
+ This is similar to `keras.ops.split`, but it allows for
8100
+ unequal splits. `indices_or_sections` must be an integer
8101
+ that indicates the total number of sub-arrays to create.
8102
+ If the tensor cannot be divided evenly, the first `remainder`
8103
+ splits will have size `quotient + 1`, and the rest will
8104
+ have size `quotient`.
8105
+
8106
+ Args:
8107
+ x: Input tensor.
8108
+ indices_or_sections: An integer indicating the number of
8109
+ sub-arrays to create.
8110
+ axis: The axis along which to split. Defaults to 0.
8111
+
8112
+ Returns:
8113
+ A list of sub-tensors.
8114
+
8115
+ Example:
8116
+ >>> x = keras.ops.arange(10)
8117
+ >>> keras.ops.array_split(x, 3)
8118
+ (array([0, 1, 2, 3], dtype=int32),
8119
+ array([4, 5, 6], dtype=int32),
8120
+ array([7, 8, 9], dtype=int32))
8121
+ """
8122
+ if not isinstance(indices_or_sections, int):
8123
+ raise TypeError(
8124
+ "Argument `indices_or_sections` must be of type `int`. "
8125
+ f"Received: indices_or_sections={indices_or_sections}"
8126
+ )
8127
+
8128
+ if indices_or_sections <= 0:
8129
+ raise ValueError(
8130
+ "Argument `indices_or_sections` must be a positive integer. "
8131
+ f"Received: indices_or_sections={indices_or_sections}"
8132
+ )
8133
+
8134
+ if not isinstance(axis, int):
8135
+ raise TypeError(
8136
+ f"Argument `axis` must be of type `int`. Received: {axis}"
8137
+ )
8138
+
8139
+ if any_symbolic_tensors((x,)):
8140
+ return ArraySplit(
8141
+ indices_or_sections=indices_or_sections, axis=axis
8142
+ ).symbolic_call(x)
8143
+
8144
+ return backend.numpy.array_split(
8145
+ x, indices_or_sections=indices_or_sections, axis=axis
8146
+ )