keras-nightly 3.14.0.dev2026012504__py3-none-any.whl → 3.14.0.dev2026012704__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.
@@ -2270,7 +2270,16 @@ def prod(x, axis=None, keepdims=False, dtype=None):
2270
2270
 
2271
2271
 
2272
2272
  def ptp(x, axis=None, keepdims=False):
2273
- raise NotImplementedError("`ptp` is not supported with openvino backend")
2273
+ if axis == ():
2274
+ return zeros_like(x)
2275
+ x = get_ov_output(x)
2276
+
2277
+ x_resolved, resolved_axis = _resolve_axis(x, axis)
2278
+
2279
+ max_val = ov_opset.reduce_max(x_resolved, resolved_axis, keepdims)
2280
+ min_val = ov_opset.reduce_min(x_resolved, resolved_axis, keepdims)
2281
+
2282
+ return OpenVINOKerasTensor(ov_opset.subtract(max_val, min_val).output(0))
2274
2283
 
2275
2284
 
2276
2285
  def quantile(x, q, axis=None, method="linear", keepdims=False):
@@ -2682,7 +2691,23 @@ def tensordot(x1, x2, axes=2):
2682
2691
 
2683
2692
 
2684
2693
  def round(x, decimals=0):
2685
- raise NotImplementedError("`round` is not supported with openvino backend")
2694
+ x = get_ov_output(x)
2695
+ x_type = x.get_element_type()
2696
+ if x_type.is_integral() or x_type == Type.boolean:
2697
+ x = ov_opset.convert(x, OPENVINO_DTYPES[config.floatx()])
2698
+
2699
+ if decimals == 0:
2700
+ result = ov_opset.round(x, "half_to_even")
2701
+ else:
2702
+ factor = ov_opset.constant(10.0**decimals, x.get_element_type())
2703
+ scaled = ov_opset.multiply(x, factor)
2704
+ rounded = ov_opset.round(scaled, "half_to_even")
2705
+ result = ov_opset.divide(rounded, factor)
2706
+
2707
+ if x_type.is_integral():
2708
+ result = ov_opset.convert(result, x_type)
2709
+
2710
+ return OpenVINOKerasTensor(result.output(0))
2686
2711
 
2687
2712
 
2688
2713
  def tile(x, repeats):
@@ -2803,7 +2828,17 @@ def vdot(x1, x2):
2803
2828
 
2804
2829
 
2805
2830
  def vstack(xs):
2806
- raise NotImplementedError("`vstack` is not supported with openvino backend")
2831
+ if not isinstance(xs, (list, tuple)):
2832
+ xs = (xs,)
2833
+ elems = [convert_to_tensor(elem) for elem in xs]
2834
+ element_type = elems[0].output.get_element_type()
2835
+ elems = [get_ov_output(elem, element_type) for elem in elems]
2836
+ axis = 0
2837
+ for i in range(1, len(elems)):
2838
+ elems[0], elems[i] = _align_operand_types(
2839
+ elems[0], elems[i], "vstack()"
2840
+ )
2841
+ return OpenVINOKerasTensor(ov_opset.concat(elems, axis).output(0))
2807
2842
 
2808
2843
 
2809
2844
  def vectorize(pyfunc, *, excluded=None, signature=None):
@@ -2859,9 +2894,20 @@ def divide(x1, x2):
2859
2894
 
2860
2895
 
2861
2896
  def divide_no_nan(x1, x2):
2862
- raise NotImplementedError(
2863
- "`divide_no_nan` is not supported with openvino backend"
2864
- )
2897
+ element_type = None
2898
+ if isinstance(x1, OpenVINOKerasTensor):
2899
+ element_type = x1.output.get_element_type()
2900
+ if isinstance(x2, OpenVINOKerasTensor):
2901
+ element_type = x2.output.get_element_type()
2902
+ x1 = get_ov_output(x1, element_type)
2903
+ x2 = get_ov_output(x2, element_type)
2904
+ x1, x2 = _align_operand_types(x1, x2, "divide_no_nan()")
2905
+
2906
+ zero = ov_opset.constant(0, x2.get_element_type())
2907
+ div = ov_opset.divide(x1, x2)
2908
+ is_zero = ov_opset.equal(x2, zero)
2909
+ result = ov_opset.select(is_zero, zero, div)
2910
+ return OpenVINOKerasTensor(result.output(0))
2865
2911
 
2866
2912
 
2867
2913
  def true_divide(x1, x2):
@@ -36,15 +36,31 @@ class TorchExportArchive:
36
36
  )
37
37
 
38
38
  sample_inputs = tree.map_structure(
39
- lambda x: convert_spec_to_tensor(x, replace_none_number=1),
39
+ lambda x: convert_spec_to_tensor(x, replace_none_number=2),
40
40
  input_signature,
41
41
  )
42
42
  sample_inputs = tuple(sample_inputs)
43
43
 
44
+ # Build dynamic_shapes from input_signature where shape has None
45
+ # Use a shared "batch" dim for dimension 0 across all inputs
46
+ batch_dim = torch.export.Dim("batch", min=1)
47
+ dynamic_shapes = []
48
+ for spec in input_signature:
49
+ dim_spec = {}
50
+ for dim_idx, dim_val in enumerate(spec.shape):
51
+ if dim_val is None:
52
+ if dim_idx == 0:
53
+ dim_spec[dim_idx] = batch_dim
54
+ else:
55
+ dim_spec[dim_idx] = torch.export.Dim(
56
+ f"dim_{len(dynamic_shapes)}_{dim_idx}", min=1
57
+ )
58
+ dynamic_shapes.append(dim_spec if dim_spec else None)
59
+ dynamic_shapes = tuple(dynamic_shapes) if any(dynamic_shapes) else None
60
+
44
61
  # Ref: torch_xla.tf_saved_model_integration
45
- # TODO: Utilize `dynamic_shapes`
46
62
  exported = torch.export.export(
47
- resource, sample_inputs, dynamic_shapes=None, strict=False
63
+ resource, sample_inputs, dynamic_shapes=dynamic_shapes, strict=False
48
64
  )
49
65
  options = torch_xla.stablehlo.StableHLOExportOptions(
50
66
  override_tracing_arguments=sample_inputs
@@ -8,6 +8,26 @@ from keras.src.layers.input_spec import InputSpec
8
8
  from keras.src.layers.layer import Layer
9
9
 
10
10
 
11
+ # TODO(abheesht17): Move this to utils?
12
+ def _clone_initializer(initializer):
13
+ """Clones an initializer to ensure a new seed.
14
+
15
+ Args:
16
+ initializer: The initializer to clone.
17
+
18
+ Returns:
19
+ A cloned initializer if it is clonable, otherwise the original one.
20
+
21
+ As of tensorflow 2.10, we need to clone user passed initializers when
22
+ invoking them twice to avoid creating the same randomized initialization.
23
+ """
24
+ if isinstance(initializer, initializers.Initializer):
25
+ config = initializer.get_config()
26
+ return initializer.__class__.from_config(config)
27
+ # If we get a string or dict, just return as we cannot and should not clone.
28
+ return initializer
29
+
30
+
11
31
  @keras_export("keras.layers.BatchNormalization")
12
32
  class BatchNormalization(Layer):
13
33
  """Layer that normalizes its inputs.
@@ -72,6 +92,22 @@ class BatchNormalization(Layer):
72
92
  variance) for the layer across all devices at each training step
73
93
  in a distributed training strategy.
74
94
  If `False`, each replica uses its own local batch statistics.
95
+ renorm: Whether to use
96
+ [Batch Renormalization](https://arxiv.org/abs/1702.03275). This
97
+ adds extra variables during training. The inference is the same
98
+ for either value of this parameter.
99
+ renorm_clipping: Dictionary, valid only if `renorm = True`.
100
+ Maps optional keys `"rmax"`, `"rmin"`, `"dmax"` to floats used to
101
+ clip the renorm correction. The correction `(r, d)` is used as
102
+ `corrected_value = normalized_value * r + d`, with `r` clipped to
103
+ `[rmin, rmax]`, and `d` to `[-dmax, dmax]`. Missing `rmax`, `rmin`,
104
+ `dmax` are set to `inf`, `0`, `inf`, respectively.
105
+ renorm_momentum: Momentum used to update the moving means and standard
106
+ deviations with renorm. Valid only if `renorm= True`. Unlike
107
+ `momentum`, this affects training and should be neither too small
108
+ (which would add noise) nor too large (which would give stale
109
+ estimates). Note that `momentum` is still applied to get the means
110
+ and variances for inference.
75
111
  **kwargs: Base layer keyword arguments (e.g. `name` and `dtype`).
76
112
 
77
113
  Call arguments:
@@ -136,6 +172,9 @@ class BatchNormalization(Layer):
136
172
  gamma_regularizer=None,
137
173
  beta_constraint=None,
138
174
  gamma_constraint=None,
175
+ renorm=False,
176
+ renorm_clipping=None,
177
+ renorm_momentum=0.99,
139
178
  synchronized=False,
140
179
  **kwargs,
141
180
  ):
@@ -165,6 +204,33 @@ class BatchNormalization(Layer):
165
204
  self.gamma_constraint = constraints.get(gamma_constraint)
166
205
  self.supports_masking = True
167
206
 
207
+ self.renorm = renorm
208
+ if renorm:
209
+ renorm_clipping = renorm_clipping or {}
210
+ keys = ["rmax", "rmin", "dmax"]
211
+ if set(renorm_clipping) - set(keys):
212
+ raise ValueError(
213
+ "Received invalid keys for `renorm_clipping` argument: "
214
+ f"{renorm_clipping}. Supported values: {keys}."
215
+ )
216
+ rmax = renorm_clipping.get("rmax")
217
+ rmin = renorm_clipping.get("rmin")
218
+ dmax = renorm_clipping.get("dmax")
219
+
220
+ if rmax is not None and rmin is not None and rmax < rmin:
221
+ raise ValueError(
222
+ "rmax should be greater than rmin in the `renorm_clipping` "
223
+ "argument. Received: rmax={rmax}, rmin={rmin}."
224
+ )
225
+ if dmax is not None and dmax < 0:
226
+ raise ValueError(
227
+ "dmax should be non-negative in the `renorm_clipping` "
228
+ """argument. Received: dmax={dmax}."""
229
+ )
230
+
231
+ self.renorm_clipping = renorm_clipping
232
+ self.renorm_momentum = renorm_momentum
233
+
168
234
  self.gamma = None
169
235
  self.beta = None
170
236
  self.moving_mean = None
@@ -208,6 +274,40 @@ class BatchNormalization(Layer):
208
274
  autocast=False,
209
275
  )
210
276
 
277
+ if self.renorm:
278
+ # In batch renormalization we track the inference moving stddev
279
+ # instead of the moving variance to more closely align with the
280
+ # paper. The stddev is initialized as sqrt of the variance
281
+ # initializer.
282
+ def moving_stddev_initializer(shape, dtype=None):
283
+ cloned = _clone_initializer(self.moving_variance_initializer)
284
+ return ops.sqrt(cloned(shape, dtype=dtype))
285
+
286
+ self.moving_stddev = self.add_weight(
287
+ shape=shape,
288
+ name="moving_stddev",
289
+ initializer=moving_stddev_initializer,
290
+ trainable=False,
291
+ autocast=False,
292
+ )
293
+ # Create variables to maintain the moving mean and standard
294
+ # deviation. These are used in training and thus are different
295
+ # from the moving averages above.
296
+ self.renorm_mean = self.add_weight(
297
+ shape=shape,
298
+ name="renorm_mean",
299
+ initializer=_clone_initializer(self.moving_mean_initializer),
300
+ trainable=False,
301
+ autocast=False,
302
+ )
303
+ self.renorm_stddev = self.add_weight(
304
+ shape=shape,
305
+ name="renorm_stddev",
306
+ initializer=moving_stddev_initializer,
307
+ trainable=False,
308
+ autocast=False,
309
+ )
310
+
211
311
  self.input_spec = InputSpec(
212
312
  ndim=len(input_shape), axes={self.axis: input_shape[self.axis]}
213
313
  )
@@ -250,20 +350,6 @@ class BatchNormalization(Layer):
250
350
  moving_mean = ops.cast(self.moving_mean, inputs.dtype)
251
351
  moving_variance = ops.cast(self.moving_variance, inputs.dtype)
252
352
 
253
- if training and self.trainable:
254
- mean, variance = self._moments(inputs, mask)
255
-
256
- self.moving_mean.assign(
257
- moving_mean * self.momentum + mean * (1.0 - self.momentum)
258
- )
259
- self.moving_variance.assign(
260
- moving_variance * self.momentum
261
- + variance * (1.0 - self.momentum)
262
- )
263
- else:
264
- mean = moving_mean
265
- variance = moving_variance
266
-
267
353
  if self.scale:
268
354
  gamma = ops.cast(self.gamma, inputs.dtype)
269
355
  else:
@@ -274,6 +360,39 @@ class BatchNormalization(Layer):
274
360
  else:
275
361
  beta = None
276
362
 
363
+ if training and self.trainable:
364
+ mean, variance = self._moments(inputs, mask)
365
+
366
+ if self.renorm:
367
+ # Compute renorm corrections (r and d).
368
+ (
369
+ r,
370
+ d,
371
+ mean,
372
+ variance,
373
+ ) = self._renorm_correction_and_moments(mean, variance)
374
+
375
+ # x = x * gamma + beta without renorm, and
376
+ # (x * r + d) * gamma + beta = x * (r * gamma) + (d * gamma +
377
+ # beta) with renorm.
378
+ gamma, beta = self._compose_transforms(
379
+ r, d, gamma, beta, inputs.dtype
380
+ )
381
+
382
+ # Update moving statistics.
383
+ self._update_renorm_statistics(mean, variance)
384
+ else:
385
+ self.moving_mean.assign(
386
+ moving_mean * self.momentum + mean * (1.0 - self.momentum)
387
+ )
388
+ self.moving_variance.assign(
389
+ moving_variance * self.momentum
390
+ + variance * (1.0 - self.momentum)
391
+ )
392
+ else:
393
+ mean = moving_mean
394
+ variance = moving_variance
395
+
277
396
  outputs = ops.batch_normalization(
278
397
  x=inputs,
279
398
  mean=mean,
@@ -306,6 +425,9 @@ class BatchNormalization(Layer):
306
425
  "beta_constraint": constraints.serialize(self.beta_constraint),
307
426
  "gamma_constraint": constraints.serialize(self.gamma_constraint),
308
427
  "synchronized": self.synchronized,
428
+ "renorm": self.renorm,
429
+ "renorm_clipping": self.renorm_clipping,
430
+ "renorm_momentum": self.renorm_momentum,
309
431
  }
310
432
  return {**base_config, **config}
311
433
 
@@ -346,3 +468,115 @@ class BatchNormalization(Layer):
346
468
  variance = weighted_distsq / (sum_of_weights + backend.epsilon())
347
469
 
348
470
  return ops.squeeze(mean), ops.squeeze(variance)
471
+
472
+ def _renorm_correction_and_moments(self, mean, variance):
473
+ """Computes the correction for batch renormalization.
474
+
475
+ This method computes the r and d correction factors.
476
+
477
+ Args:
478
+ mean: The mean of the current batch.
479
+ variance: The variance of the current batch.
480
+
481
+ Returns:
482
+ A tuple (r, s, mean, variance) where r and d are the correction
483
+ factors, and mean/variance are passed through unchanged.
484
+ """
485
+ stddev = ops.sqrt(variance + self.epsilon)
486
+
487
+ # Get the renorm moving statistics.
488
+ renorm_mean = ops.cast(self.renorm_mean, mean.dtype)
489
+ # Avoid divide by zero early on in training.
490
+ renorm_stddev = ops.maximum(
491
+ ops.cast(self.renorm_stddev, mean.dtype),
492
+ ops.sqrt(ops.cast(self.epsilon, mean.dtype)),
493
+ )
494
+
495
+ # Compute the corrections for batch renorm.
496
+ r = ops.divide(stddev, renorm_stddev)
497
+ d = ops.divide(ops.subtract(mean, renorm_mean), renorm_stddev)
498
+
499
+ # Apply clipping.
500
+ rmin = self.renorm_clipping.get("rmin")
501
+ rmax = self.renorm_clipping.get("rmax")
502
+ dmax = self.renorm_clipping.get("dmax")
503
+
504
+ if rmin is not None:
505
+ r = ops.maximum(r, rmin)
506
+ if rmax is not None:
507
+ r = ops.minimum(r, rmax)
508
+ if dmax is not None:
509
+ d = ops.clip(d, -dmax, dmax)
510
+
511
+ return r, d, mean, variance
512
+
513
+ def _compose_transforms(self, r, d, gamma, beta, dtype):
514
+ """Composes the renorm correction with gamma and beta.
515
+
516
+ When training with renorm, the normalized values (x) are transformed
517
+ as: (x * r + d) * gamma + beta = x * (r * gamma) + (d * gamma + beta).
518
+ This method computes the effective scale and offset.
519
+
520
+ Args:
521
+ r: The r correction factor.
522
+ d: The d correction factor.
523
+ gamma: The gamma (scale) parameter, or None.
524
+ beta: The beta (offset) parameter, or None.
525
+ dtype: The dtype for the output.
526
+
527
+ Returns:
528
+ A tuple (effective_gamma, effective_beta).
529
+ """
530
+ r = ops.stop_gradient(r)
531
+ d = ops.stop_gradient(d)
532
+
533
+ if gamma is not None:
534
+ effective_gamma = ops.multiply(r, gamma)
535
+ effective_beta = ops.multiply(d, gamma)
536
+ else:
537
+ effective_gamma = ops.cast(r, dtype)
538
+ effective_beta = ops.cast(d, dtype)
539
+
540
+ if beta is not None:
541
+ effective_beta = ops.add(effective_beta, beta)
542
+
543
+ return effective_gamma, effective_beta
544
+
545
+ def _update_renorm_statistics(self, mean, variance):
546
+ """Updates the renorm and moving statistics.
547
+ Args:
548
+ mean: The mean of the current batch.
549
+ variance: The variance of the current batch.
550
+ """
551
+ stddev = ops.sqrt(variance + self.epsilon)
552
+
553
+ # Update renorm moving mean and stddev.
554
+ renorm_mean = ops.cast(self.renorm_mean, mean.dtype)
555
+ renorm_stddev = ops.cast(self.renorm_stddev, mean.dtype)
556
+
557
+ self.renorm_mean.assign(
558
+ renorm_mean * self.renorm_momentum
559
+ + mean * (1.0 - self.renorm_momentum)
560
+ )
561
+ self.renorm_stddev.assign(
562
+ renorm_stddev * self.renorm_momentum
563
+ + stddev * (1.0 - self.renorm_momentum)
564
+ )
565
+
566
+ moving_mean = ops.cast(self.moving_mean, mean.dtype)
567
+ moving_stddev = ops.cast(self.moving_stddev, mean.dtype)
568
+
569
+ self.moving_mean.assign(
570
+ moving_mean * self.momentum + mean * (1.0 - self.momentum)
571
+ )
572
+
573
+ new_moving_stddev = moving_stddev * self.momentum + stddev * (
574
+ 1.0 - self.momentum
575
+ )
576
+ self.moving_stddev.assign(new_moving_stddev)
577
+
578
+ # Derive `moving_variance` from `moving_stddev`, applying ReLU in case
579
+ # floating point rounding causes it to go negative.
580
+ self.moving_variance.assign(
581
+ ops.relu(new_moving_stddev * new_moving_stddev - self.epsilon)
582
+ )
keras/src/version.py CHANGED
@@ -1,7 +1,7 @@
1
1
  from keras.src.api_export import keras_export
2
2
 
3
3
  # Unique source of truth for the version number.
4
- __version__ = "3.14.0.dev2026012504"
4
+ __version__ = "3.14.0.dev2026012704"
5
5
 
6
6
 
7
7
  @keras_export("keras.version")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: keras-nightly
3
- Version: 3.14.0.dev2026012504
3
+ Version: 3.14.0.dev2026012704
4
4
  Summary: Multi-backend Keras
5
5
  Author-email: Keras team <keras-users@googlegroups.com>
6
6
  License: Apache License 2.0
@@ -128,7 +128,7 @@ keras/regularizers/__init__.py,sha256=542Shphw7W8h4Dyf2rmqMKUECVZ8IVBvN9g1LWhz-b
128
128
  keras/saving/__init__.py,sha256=KvL2GZxjvgFgEhvEnkvqjIR9JSNHKz-NWZacXajsjLI,1298
129
129
  keras/src/__init__.py,sha256=Gi4S7EiCMkE03PbdGNpFdaUYySWDs_FcAJ8Taz9Y1BE,684
130
130
  keras/src/api_export.py,sha256=gXOkBOnmscV013WAc75lc4Up01-Kkg9EylIAT_QWctg,1173
131
- keras/src/version.py,sha256=bQtm_6Y21nPnPQeuyoizFh4GZwI1cNN9G4HofRYl9LE,204
131
+ keras/src/version.py,sha256=NJIml5PJgVtz-3KeL-ybBmxHJGE7ed1_h7tLzegDbmY,204
132
132
  keras/src/activations/__init__.py,sha256=0nL3IFDB9unlrMz8ninKOWo-uCHasTUpTo1tXZb2u44,4433
133
133
  keras/src/activations/activations.py,sha256=mogPggtp4CGldI3VOPNmesRxp6EbiR1_i4KLGaVwzL8,17614
134
134
  keras/src/applications/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -198,7 +198,7 @@ keras/src/backend/openvino/layer.py,sha256=5RdvaH1yOyPAphjKiuQAK1H_yZFYKE1Hp7c5b
198
198
  keras/src/backend/openvino/linalg.py,sha256=L6a4MFGND2wWzPVCh44cwuOgkcC4wJTo8Xy3HwW04lg,1614
199
199
  keras/src/backend/openvino/math.py,sha256=qw9kX2sJ2qr0dBJF12Ey0E2GcwixPUqoev6UcNra4NI,3944
200
200
  keras/src/backend/openvino/nn.py,sha256=zULPxdwVO7JDZUUtsuoEEPCLQ09ew8z8T6G_i_NEqrM,23741
201
- keras/src/backend/openvino/numpy.py,sha256=qmw4X3u0oJZptzqNHM33FPjTd_Ku6xY9dxxYFqW8c0g,109966
201
+ keras/src/backend/openvino/numpy.py,sha256=ML-PW8BvLpdqkYVo0KsebSHRwH8OaAnZUbmfB1LZAy4,111639
202
202
  keras/src/backend/openvino/random.py,sha256=4hRUtIP6qJxO3Qy9uH1x6jSuJna3nWPdUf4x2QU8-ew,5575
203
203
  keras/src/backend/openvino/rnn.py,sha256=ErmuZLPSgG9qU-NfYPPvBZ6Ysy8k-fA4g19Vhqq7OVQ,866
204
204
  keras/src/backend/openvino/trainer.py,sha256=bMmtSALqydqdS6ke-5sYW5fgxZDshDH810p_C0xCRTg,9087
@@ -221,7 +221,7 @@ keras/src/backend/tensorflow/trackable.py,sha256=QZn0JvpBJ7Kx4e6zM2IVIWz9ADcWDB-
221
221
  keras/src/backend/tensorflow/trainer.py,sha256=otJ4CciSmE2-QH17bEyjaL-oQxiCD5eWgbkEglxjt4w,37191
222
222
  keras/src/backend/torch/__init__.py,sha256=0SiJ91WMaE_tO5q1zUsLEnU6hmPTpGKPIOkmIWaHlhk,2131
223
223
  keras/src/backend/torch/core.py,sha256=cMo5dCDxWicWgezOargrq1qx-tlS1GJzzYXm--PS1l0,24506
224
- keras/src/backend/torch/export.py,sha256=yYc5-4JxSiaCkbFWpfCIdcm4dDBv_9uG_uH6JR6oGx0,4909
224
+ keras/src/backend/torch/export.py,sha256=9efHPdN_xvSWB0pndr_X9JJmQNwWyvrGBQOr_xOQDHc,5685
225
225
  keras/src/backend/torch/image.py,sha256=eer8LZwDMz3k2Dh5gxeTQfwrxPemM_H6eHMIP3AwRss,39149
226
226
  keras/src/backend/torch/layer.py,sha256=htECdpv9ioHWM8_zqQkEdxgDsgLu8XJi5yXgnLl-JFw,2084
227
227
  keras/src/backend/torch/linalg.py,sha256=wgPCfnscp5HOBmX9_-m-57lzxs1ttLNzmHqj2VYYq7k,2108
@@ -344,7 +344,7 @@ keras/src/layers/merging/minimum.py,sha256=f8RN1O5yYzDqJbXuVTBKC0TKdEw_VU4bC4pZX
344
344
  keras/src/layers/merging/multiply.py,sha256=WvBX5gOpouqfQYnpioKMw2Tj6HRQQ2LNBuvKsRo_6P0,3185
345
345
  keras/src/layers/merging/subtract.py,sha256=ijpJDomo1JSMCw97Rn55LXiVLsI50lcvUxmZiv_HIzo,2684
346
346
  keras/src/layers/normalization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
347
- keras/src/layers/normalization/batch_normalization.py,sha256=Hov8hKKqAOl1TDRtmH0S6jn8iutjdcVlw_Q_EcElDBc,14138
347
+ keras/src/layers/normalization/batch_normalization.py,sha256=RXvCB4Nq0I9c5qPtL9UlhuOaomfsjBtrs7B-sAUYZhg,23453
348
348
  keras/src/layers/normalization/group_normalization.py,sha256=S8w40kMCi_aEN079vwDPxaV7K02Ny0HocZJ1ATX4SpA,9367
349
349
  keras/src/layers/normalization/layer_normalization.py,sha256=4GHBLQf2BSRLv2-73rPRWTgLKwYU7V0wXKZ99dA2jhw,8622
350
350
  keras/src/layers/normalization/rms_normalization.py,sha256=IJMNWEg41ELWWd_V5PfUZaseB2lIKKpE0KC-M-T4INY,3008
@@ -618,7 +618,7 @@ keras/utils/bounding_boxes/__init__.py,sha256=jtvQll4u8ZY0Z96HwNhP1nxWEG9FM3gI-6
618
618
  keras/utils/legacy/__init__.py,sha256=oSYZz6uS8UxSElRaaJYWJEoweJ4GAasZjnn7fNaOlog,342
619
619
  keras/visualization/__init__.py,sha256=UKWmiy6sps4SWlmQi9WX8_Z53cPpLlphz2zIeHdwJpQ,722
620
620
  keras/wrappers/__init__.py,sha256=QkS-O5K8qGS7C3sytF8MpmO6PasATpNVGF8qtb7Ojsw,407
621
- keras_nightly-3.14.0.dev2026012504.dist-info/METADATA,sha256=_fzNIH13HkMcj6ERuQnmrIeco8jGSNaDYsBwg3I8o9s,6339
622
- keras_nightly-3.14.0.dev2026012504.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
623
- keras_nightly-3.14.0.dev2026012504.dist-info/top_level.txt,sha256=ptcw_-QuGZ4ZDjMdwi_Z0clZm8QAqFdvzzFnDEOTs9o,6
624
- keras_nightly-3.14.0.dev2026012504.dist-info/RECORD,,
621
+ keras_nightly-3.14.0.dev2026012704.dist-info/METADATA,sha256=wRM5XhLX-CtFBWe6lPjmVjDb-4-WwjDQT2DTE--cn5s,6339
622
+ keras_nightly-3.14.0.dev2026012704.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
623
+ keras_nightly-3.14.0.dev2026012704.dist-info/top_level.txt,sha256=ptcw_-QuGZ4ZDjMdwi_Z0clZm8QAqFdvzzFnDEOTs9o,6
624
+ keras_nightly-3.14.0.dev2026012704.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.1)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5