keras-nightly 3.12.0.dev2025082103__py3-none-any.whl → 3.12.0.dev2025082303__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 (126) hide show
  1. keras/_tf_keras/keras/ops/__init__.py +1 -0
  2. keras/_tf_keras/keras/ops/numpy/__init__.py +1 -0
  3. keras/_tf_keras/keras/quantizers/__init__.py +1 -0
  4. keras/ops/__init__.py +1 -0
  5. keras/ops/numpy/__init__.py +1 -0
  6. keras/quantizers/__init__.py +1 -0
  7. keras/src/applications/convnext.py +20 -20
  8. keras/src/applications/densenet.py +21 -21
  9. keras/src/applications/efficientnet.py +16 -16
  10. keras/src/applications/efficientnet_v2.py +28 -28
  11. keras/src/applications/inception_resnet_v2.py +7 -7
  12. keras/src/applications/inception_v3.py +5 -5
  13. keras/src/applications/mobilenet_v2.py +13 -20
  14. keras/src/applications/mobilenet_v3.py +15 -15
  15. keras/src/applications/nasnet.py +7 -8
  16. keras/src/applications/resnet.py +32 -32
  17. keras/src/applications/xception.py +10 -10
  18. keras/src/backend/common/dtypes.py +8 -3
  19. keras/src/backend/common/variables.py +3 -1
  20. keras/src/backend/jax/export.py +1 -1
  21. keras/src/backend/jax/numpy.py +6 -0
  22. keras/src/backend/jax/trainer.py +1 -1
  23. keras/src/backend/numpy/numpy.py +28 -0
  24. keras/src/backend/openvino/numpy.py +5 -1
  25. keras/src/backend/tensorflow/numpy.py +22 -0
  26. keras/src/backend/tensorflow/trainer.py +19 -1
  27. keras/src/backend/torch/core.py +6 -9
  28. keras/src/backend/torch/nn.py +1 -2
  29. keras/src/backend/torch/numpy.py +16 -0
  30. keras/src/backend/torch/trainer.py +1 -1
  31. keras/src/callbacks/backup_and_restore.py +2 -2
  32. keras/src/callbacks/csv_logger.py +1 -1
  33. keras/src/callbacks/model_checkpoint.py +1 -1
  34. keras/src/callbacks/tensorboard.py +6 -6
  35. keras/src/constraints/constraints.py +9 -7
  36. keras/src/datasets/boston_housing.py +1 -1
  37. keras/src/datasets/california_housing.py +1 -1
  38. keras/src/datasets/cifar10.py +1 -1
  39. keras/src/datasets/cifar100.py +2 -2
  40. keras/src/datasets/imdb.py +2 -2
  41. keras/src/datasets/mnist.py +1 -1
  42. keras/src/datasets/reuters.py +2 -2
  43. keras/src/dtype_policies/dtype_policy.py +1 -1
  44. keras/src/dtype_policies/dtype_policy_map.py +1 -1
  45. keras/src/export/tf2onnx_lib.py +1 -3
  46. keras/src/initializers/constant_initializers.py +9 -5
  47. keras/src/layers/input_spec.py +6 -6
  48. keras/src/layers/layer.py +1 -1
  49. keras/src/layers/preprocessing/category_encoding.py +3 -3
  50. keras/src/layers/preprocessing/data_layer.py +159 -0
  51. keras/src/layers/preprocessing/discretization.py +3 -3
  52. keras/src/layers/preprocessing/feature_space.py +4 -4
  53. keras/src/layers/preprocessing/image_preprocessing/aug_mix.py +7 -4
  54. keras/src/layers/preprocessing/image_preprocessing/auto_contrast.py +3 -0
  55. keras/src/layers/preprocessing/image_preprocessing/base_image_preprocessing_layer.py +2 -2
  56. keras/src/layers/preprocessing/image_preprocessing/center_crop.py +1 -1
  57. keras/src/layers/preprocessing/image_preprocessing/cut_mix.py +6 -3
  58. keras/src/layers/preprocessing/image_preprocessing/equalization.py +1 -1
  59. keras/src/layers/preprocessing/image_preprocessing/max_num_bounding_box.py +3 -0
  60. keras/src/layers/preprocessing/image_preprocessing/mix_up.py +7 -4
  61. keras/src/layers/preprocessing/image_preprocessing/rand_augment.py +3 -1
  62. keras/src/layers/preprocessing/image_preprocessing/random_brightness.py +1 -1
  63. keras/src/layers/preprocessing/image_preprocessing/random_color_degeneration.py +3 -0
  64. keras/src/layers/preprocessing/image_preprocessing/random_color_jitter.py +3 -0
  65. keras/src/layers/preprocessing/image_preprocessing/random_contrast.py +1 -1
  66. keras/src/layers/preprocessing/image_preprocessing/random_crop.py +1 -1
  67. keras/src/layers/preprocessing/image_preprocessing/random_elastic_transform.py +3 -0
  68. keras/src/layers/preprocessing/image_preprocessing/random_erasing.py +6 -3
  69. keras/src/layers/preprocessing/image_preprocessing/random_flip.py +1 -1
  70. keras/src/layers/preprocessing/image_preprocessing/random_gaussian_blur.py +3 -0
  71. keras/src/layers/preprocessing/image_preprocessing/random_grayscale.py +1 -1
  72. keras/src/layers/preprocessing/image_preprocessing/random_hue.py +3 -0
  73. keras/src/layers/preprocessing/image_preprocessing/random_invert.py +3 -0
  74. keras/src/layers/preprocessing/image_preprocessing/random_perspective.py +3 -0
  75. keras/src/layers/preprocessing/image_preprocessing/random_posterization.py +3 -0
  76. keras/src/layers/preprocessing/image_preprocessing/random_rotation.py +1 -1
  77. keras/src/layers/preprocessing/image_preprocessing/random_saturation.py +3 -0
  78. keras/src/layers/preprocessing/image_preprocessing/random_sharpness.py +3 -0
  79. keras/src/layers/preprocessing/image_preprocessing/random_shear.py +3 -0
  80. keras/src/layers/preprocessing/image_preprocessing/random_translation.py +3 -3
  81. keras/src/layers/preprocessing/image_preprocessing/random_zoom.py +3 -3
  82. keras/src/layers/preprocessing/image_preprocessing/resizing.py +3 -3
  83. keras/src/layers/preprocessing/image_preprocessing/solarization.py +3 -0
  84. keras/src/layers/preprocessing/mel_spectrogram.py +29 -25
  85. keras/src/layers/preprocessing/normalization.py +5 -2
  86. keras/src/layers/preprocessing/rescaling.py +3 -3
  87. keras/src/layers/rnn/bidirectional.py +4 -4
  88. keras/src/legacy/backend.py +9 -23
  89. keras/src/legacy/preprocessing/image.py +11 -22
  90. keras/src/legacy/preprocessing/text.py +1 -1
  91. keras/src/models/functional.py +2 -2
  92. keras/src/models/model.py +21 -3
  93. keras/src/ops/function.py +1 -1
  94. keras/src/ops/numpy.py +49 -5
  95. keras/src/ops/operation.py +3 -2
  96. keras/src/optimizers/base_optimizer.py +3 -4
  97. keras/src/optimizers/schedules/learning_rate_schedule.py +16 -9
  98. keras/src/quantizers/gptq.py +350 -0
  99. keras/src/quantizers/gptq_config.py +169 -0
  100. keras/src/quantizers/gptq_core.py +335 -0
  101. keras/src/quantizers/gptq_quant.py +133 -0
  102. keras/src/saving/file_editor.py +22 -20
  103. keras/src/saving/object_registration.py +1 -1
  104. keras/src/saving/saving_lib.py +4 -4
  105. keras/src/saving/serialization_lib.py +3 -5
  106. keras/src/trainers/compile_utils.py +1 -1
  107. keras/src/trainers/data_adapters/array_data_adapter.py +9 -3
  108. keras/src/trainers/data_adapters/data_adapter_utils.py +15 -5
  109. keras/src/trainers/data_adapters/generator_data_adapter.py +2 -0
  110. keras/src/trainers/data_adapters/grain_dataset_adapter.py +8 -2
  111. keras/src/trainers/data_adapters/tf_dataset_adapter.py +4 -2
  112. keras/src/trainers/data_adapters/torch_data_loader_adapter.py +3 -1
  113. keras/src/tree/dmtree_impl.py +19 -3
  114. keras/src/tree/optree_impl.py +3 -3
  115. keras/src/tree/tree_api.py +5 -2
  116. keras/src/utils/file_utils.py +13 -5
  117. keras/src/utils/io_utils.py +1 -1
  118. keras/src/utils/model_visualization.py +1 -1
  119. keras/src/utils/progbar.py +5 -5
  120. keras/src/utils/summary_utils.py +4 -4
  121. keras/src/version.py +1 -1
  122. {keras_nightly-3.12.0.dev2025082103.dist-info → keras_nightly-3.12.0.dev2025082303.dist-info}/METADATA +1 -1
  123. {keras_nightly-3.12.0.dev2025082103.dist-info → keras_nightly-3.12.0.dev2025082303.dist-info}/RECORD +125 -121
  124. keras/src/layers/preprocessing/tf_data_layer.py +0 -78
  125. {keras_nightly-3.12.0.dev2025082103.dist-info → keras_nightly-3.12.0.dev2025082303.dist-info}/WHEEL +0 -0
  126. {keras_nightly-3.12.0.dev2025082103.dist-info → keras_nightly-3.12.0.dev2025082303.dist-info}/top_level.txt +0 -0
@@ -101,7 +101,9 @@ def list_to_tuple(maybe_list):
101
101
 
102
102
 
103
103
  def check_data_cardinality(data):
104
- num_samples = set(int(i.shape[0]) for i in tree.flatten(data))
104
+ num_samples = set(
105
+ int(i.shape[0]) for i in tree.flatten(data) if i is not None
106
+ )
105
107
  if len(num_samples) > 1:
106
108
  msg = (
107
109
  "Data cardinality is ambiguous. "
@@ -186,7 +188,9 @@ def get_keras_tensor_spec(batches):
186
188
  else:
187
189
  return backend.KerasTensor(shape=shape, dtype=dtype)
188
190
 
189
- return tree.map_structure(get_single_tensor_spec, *batches)
191
+ return tree.map_structure(
192
+ get_single_tensor_spec, *batches, none_is_leaf=False
193
+ )
190
194
 
191
195
 
192
196
  def convert_to_tf_tensor_spec(keras_tensor, batch_axis_to_none=True):
@@ -199,6 +203,8 @@ def convert_to_tf_tensor_spec(keras_tensor, batch_axis_to_none=True):
199
203
  """
200
204
  from keras.src.utils.module_utils import tensorflow as tf
201
205
 
206
+ if keras_tensor is None:
207
+ return tf.OptionalSpec(None)
202
208
  if not isinstance(keras_tensor, backend.KerasTensor):
203
209
  raise TypeError(
204
210
  f"Expected a KerasTensor, but got {keras_tensor} of type "
@@ -252,7 +258,9 @@ def get_jax_iterator(iterable):
252
258
  return np.asarray(x)
253
259
 
254
260
  for batch in iterable:
255
- yield tree.map_structure(convert_to_jax_compatible, batch)
261
+ yield tree.map_structure(
262
+ convert_to_jax_compatible, batch, none_is_leaf=False
263
+ )
256
264
 
257
265
 
258
266
  def get_numpy_iterator(iterable):
@@ -268,7 +276,7 @@ def get_numpy_iterator(iterable):
268
276
  return x
269
277
 
270
278
  for batch in iterable:
271
- yield tree.map_structure(convert_to_numpy, batch)
279
+ yield tree.map_structure(convert_to_numpy, batch, none_is_leaf=False)
272
280
 
273
281
 
274
282
  def get_torch_dataloader(iterable):
@@ -282,7 +290,9 @@ def get_torch_dataloader(iterable):
282
290
 
283
291
  def __iter__(self):
284
292
  for batch in self.iterable:
285
- yield tree.map_structure(convert_to_tensor, batch)
293
+ yield tree.map_structure(
294
+ convert_to_tensor, batch, none_is_leaf=False
295
+ )
286
296
 
287
297
  dataset = ConverterIterableDataset(iterable)
288
298
  # `batch_size=None` indicates that we should not re-batch
@@ -32,6 +32,8 @@ class GeneratorDataAdapter(DataAdapter):
32
32
  from keras.src.utils.module_utils import tensorflow as tf
33
33
 
34
34
  def convert_to_tf(x, spec):
35
+ if x is None:
36
+ return tf.experimental.Optional.empty(None)
35
37
  if data_adapter_utils.is_scipy_sparse(x):
36
38
  x = data_adapter_utils.scipy_sparse_to_tf_sparse(x)
37
39
  elif data_adapter_utils.is_jax_sparse(x):
@@ -80,7 +80,9 @@ class GrainDatasetAdapter(DataAdapter):
80
80
 
81
81
  class ConvertToNumpy(grain.transforms.Map):
82
82
  def map(self, x):
83
- return tree.map_structure(convert_to_numpy, x)
83
+ return tree.map_structure(
84
+ convert_to_numpy, x, none_is_leaf=False
85
+ )
84
86
 
85
87
  if isinstance(self._dataset, (grain.MapDataset, grain.IterDataset)):
86
88
  dataset = self._dataset.map(ConvertToNumpy())
@@ -109,7 +111,9 @@ class GrainDatasetAdapter(DataAdapter):
109
111
 
110
112
  class ConvertToJaxCompatible(grain.transforms.Map):
111
113
  def map(self, x):
112
- return tree.map_structure(convert_to_jax_compatible, x)
114
+ return tree.map_structure(
115
+ convert_to_jax_compatible, x, none_is_leaf=False
116
+ )
113
117
 
114
118
  if isinstance(self._dataset, (grain.MapDataset, grain.IterDataset)):
115
119
  dataset = self._dataset.map(ConvertToJaxCompatible())
@@ -131,6 +135,8 @@ class GrainDatasetAdapter(DataAdapter):
131
135
 
132
136
  def get_tf_dataset(self):
133
137
  def convert_to_tf(x):
138
+ if x is None:
139
+ return tf.experimental.Optional.empty(None)
134
140
  if data_adapter_utils.is_scipy_sparse(x):
135
141
  x = data_adapter_utils.scipy_sparse_to_tf_sparse(x)
136
142
  elif data_adapter_utils.is_jax_sparse(x):
@@ -38,7 +38,9 @@ class TFDatasetAdapter(DataAdapter):
38
38
  from keras.src.backend.tensorflow.core import convert_to_numpy
39
39
 
40
40
  for batch in self._dataset:
41
- yield tree.map_structure(convert_to_numpy, batch)
41
+ yield tree.map_structure(
42
+ convert_to_numpy, batch, none_is_leaf=False
43
+ )
42
44
 
43
45
  def get_jax_iterator(self):
44
46
  from keras.src.backend.tensorflow.core import convert_to_numpy
@@ -52,7 +54,7 @@ class TFDatasetAdapter(DataAdapter):
52
54
  return convert_to_numpy(x)
53
55
 
54
56
  for batch in self._dataset:
55
- yield tree.map_structure(convert_to_jax, batch)
57
+ yield tree.map_structure(convert_to_jax, batch, none_is_leaf=False)
56
58
 
57
59
  def get_tf_dataset(self):
58
60
  return self._dataset
@@ -35,7 +35,9 @@ class TorchDataLoaderAdapter(DataAdapter):
35
35
  for batch in self._dataloader:
36
36
  # shared memory using `np.asarray`
37
37
  yield tuple(
38
- tree.map_structure(lambda x: np.asarray(x.cpu()), batch)
38
+ tree.map_structure(
39
+ lambda x: np.asarray(x.cpu()), batch, none_is_leaf=False
40
+ )
39
41
  )
40
42
 
41
43
  def get_jax_iterator(self):
@@ -194,16 +194,32 @@ def flatten_with_path(structure):
194
194
  return flattened
195
195
 
196
196
 
197
- def map_structure(func, *structures):
197
+ def map_structure(func, *structures, none_is_leaf=True):
198
198
  if not callable(func):
199
199
  raise TypeError(
200
200
  f"`func` must be callable, got {func} of type {type(func)}"
201
201
  )
202
202
 
203
+ map_func = func
204
+ if not none_is_leaf:
205
+
206
+ def func_skipping_none(*args):
207
+ # Check if the reference entry (first one) is None
208
+ if args[0] is None:
209
+ if not all(s is None for s in args):
210
+ raise ValueError(
211
+ "Structure mismatch: some arguments are None, others "
212
+ f"are not. Received arguments: {args}."
213
+ )
214
+ return None
215
+ return func(*args)
216
+
217
+ map_func = func_skipping_none
218
+
203
219
  def func_traverse_wrapper(s):
204
220
  if is_nested(s):
205
221
  return None
206
- ret = func(s)
222
+ ret = map_func(s)
207
223
  if ret is None:
208
224
  return dmtree.MAP_TO_NONE
209
225
  return ret
@@ -212,7 +228,7 @@ def map_structure(func, *structures):
212
228
  return traverse(func_traverse_wrapper, structures[0])
213
229
 
214
230
  with TypeErrorRemapping():
215
- return dmtree.map_structure(func, *structures)
231
+ return dmtree.map_structure(map_func, *structures)
216
232
 
217
233
 
218
234
  def map_structure_up_to(shallow_structure, func, *structures):
@@ -93,14 +93,14 @@ def flatten_with_path(structure):
93
93
  return list(zip(paths, leaves))
94
94
 
95
95
 
96
- def map_structure(func, *structures):
96
+ def map_structure(func, *structures, none_is_leaf=True):
97
97
  if not structures:
98
98
  raise ValueError("Must provide at least one structure")
99
99
 
100
100
  # Add check for same structures, otherwise optree just maps to shallowest.
101
101
  def func_with_check(*args):
102
102
  if not all(
103
- optree.tree_is_leaf(s, none_is_leaf=True, namespace="keras")
103
+ optree.tree_is_leaf(s, none_is_leaf=none_is_leaf, namespace="keras")
104
104
  for s in args
105
105
  ):
106
106
  raise ValueError("Structures don't have the same nested structure.")
@@ -109,7 +109,7 @@ def map_structure(func, *structures):
109
109
  map_func = func_with_check if len(structures) > 1 else func
110
110
 
111
111
  return optree.tree_map(
112
- map_func, *structures, none_is_leaf=True, namespace="keras"
112
+ map_func, *structures, none_is_leaf=none_is_leaf, namespace="keras"
113
113
  )
114
114
 
115
115
 
@@ -160,7 +160,7 @@ def flatten_with_path(structure):
160
160
 
161
161
 
162
162
  @keras_export("keras.tree.map_structure")
163
- def map_structure(func, *structures):
163
+ def map_structure(func, *structures, none_is_leaf=True):
164
164
  """Maps `func` through given structures.
165
165
 
166
166
  Examples:
@@ -179,6 +179,9 @@ def map_structure(func, *structures):
179
179
  Args:
180
180
  func: A callable that accepts as many arguments as there are structures.
181
181
  *structures: Arbitrarily nested structures of the same layout.
182
+ none_is_leaf: If True, `func` will be called on `None` leaves. If False,
183
+ `None` values are not passed to `func` and are returned in the
184
+ output directly.
182
185
 
183
186
  Returns:
184
187
  A new structure with the same layout as the given ones.
@@ -189,7 +192,7 @@ def map_structure(func, *structures):
189
192
  the nested structures don't match according to the rules of
190
193
  `assert_same_structure`.
191
194
  """
192
- return tree_impl.map_structure(func, *structures)
195
+ return tree_impl.map_structure(func, *structures, none_is_leaf=none_is_leaf)
193
196
 
194
197
 
195
198
  @keras_export("keras.tree.map_structure_up_to")
@@ -3,7 +3,10 @@ import os
3
3
  import re
4
4
  import shutil
5
5
  import tarfile
6
+ import tempfile
6
7
  import urllib
8
+ import urllib.error
9
+ import urllib.parse
7
10
  import warnings
8
11
  import zipfile
9
12
  from urllib.request import urlretrieve
@@ -159,7 +162,7 @@ def get_file(
159
162
  ```python
160
163
  path_to_downloaded_file = get_file(
161
164
  origin="https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz",
162
- extract=True,
165
+ extract=True
163
166
  )
164
167
  ```
165
168
 
@@ -221,7 +224,9 @@ def get_file(
221
224
  hash_algorithm = "md5"
222
225
  datadir_base = os.path.expanduser(cache_dir)
223
226
  if not os.access(datadir_base, os.W_OK):
224
- datadir_base = os.path.join("/tmp", ".keras")
227
+ datadir_base = os.path.join(
228
+ "/tmp" if os.path.isdir("/tmp") else tempfile.gettempdir(), ".keras"
229
+ )
225
230
  datadir = os.path.join(datadir_base, cache_subdir)
226
231
  os.makedirs(datadir, exist_ok=True)
227
232
 
@@ -249,13 +254,13 @@ def get_file(
249
254
  if "." in fname:
250
255
  download_target = os.path.join(datadir, fname)
251
256
  fname = fname[: fname.find(".")]
252
- extraction_dir = os.path.join(datadir, fname + "_extracted")
257
+ extraction_dir = os.path.join(datadir, f"{fname}_extracted")
253
258
  else:
254
259
  extraction_dir = os.path.join(datadir, fname)
255
- download_target = os.path.join(datadir, fname + "_archive")
260
+ download_target = os.path.join(datadir, f"{fname}_archive")
256
261
  else:
257
262
  extraction_dir = os.path.join(datadir, fname)
258
- download_target = os.path.join(datadir, fname + "_archive")
263
+ download_target = os.path.join(datadir, f"{fname}_archive")
259
264
  else:
260
265
  download_target = os.path.join(datadir, fname)
261
266
 
@@ -520,3 +525,6 @@ def makedirs(path):
520
525
  else:
521
526
  _raise_if_no_gfile(path)
522
527
  return os.makedirs(path)
528
+
529
+
530
+ "/fo"
@@ -93,7 +93,7 @@ def print_msg(message, line_break=True):
93
93
  """Print the message to absl logging or stdout."""
94
94
  message = str(message)
95
95
  if is_interactive_logging_enabled():
96
- message = message + "\n" if line_break else message
96
+ message = f"{message}\n" if line_break else message
97
97
  try:
98
98
  sys.stdout.write(message)
99
99
  except UnicodeEncodeError:
@@ -178,7 +178,7 @@ def make_layer_label(layer, **kwargs):
178
178
  colspan = 1
179
179
 
180
180
  if cols:
181
- table += "<tr>" + "".join(cols) + "</tr>"
181
+ table += f"<tr>{''.join(cols)}</tr>"
182
182
  table += "</table>>"
183
183
  return table
184
184
 
@@ -120,16 +120,16 @@ class Progbar:
120
120
 
121
121
  if self.target is not None:
122
122
  numdigits = int(math.log10(self.target)) + 1
123
- bar = ("%" + str(numdigits) + "d/%d") % (current, self.target)
123
+ bar = (f"%{numdigits}d/%d") % (current, self.target)
124
124
  bar = f"\x1b[1m{bar}\x1b[0m "
125
125
  special_char_len += 8
126
126
  prog = float(current) / self.target
127
127
  prog_width = int(self.width * prog)
128
128
 
129
129
  if prog_width > 0:
130
- bar += "\33[32m" + "" * prog_width + "\x1b[0m"
130
+ bar += f"\33[32m{'' * prog_width}\x1b[0m"
131
131
  special_char_len += 9
132
- bar += "\33[37m" + "" * (self.width - prog_width) + "\x1b[0m"
132
+ bar += f"\33[37m{'' * (self.width - prog_width)}\x1b[0m"
133
133
  special_char_len += 9
134
134
 
135
135
  else:
@@ -189,9 +189,9 @@ class Progbar:
189
189
  elif self.verbose == 2:
190
190
  if finalize:
191
191
  numdigits = int(math.log10(self.target)) + 1
192
- count = ("%" + str(numdigits) + "d/%d") % (current, self.target)
192
+ count = f"%{numdigits}d/%d" % (current, self.target)
193
193
  info = f"{count} - {now - self._start:.0f}s"
194
- info += " -" + self._format_time(time_per_unit, self.unit_name)
194
+ info += f" -{self._format_time(time_per_unit, self.unit_name)}"
195
195
  for k in self._values_order:
196
196
  info += f" - {k}:"
197
197
  avg = backend.convert_to_numpy(
@@ -87,7 +87,7 @@ def format_layer_shape(layer):
87
87
 
88
88
  def format_shape(shape):
89
89
  highlighted = [highlight_number(x) for x in shape]
90
- return "(" + ", ".join(highlighted) + ")"
90
+ return f"({', '.join(highlighted)})"
91
91
 
92
92
  # There are 2 approaches to get output shapes:
93
93
  # 1. Using `layer._inbound_nodes`, which is possible if the model is a
@@ -268,7 +268,7 @@ def print_summary(
268
268
 
269
269
  def get_layer_fields(layer, prefix=""):
270
270
  output_shape = format_layer_shape(layer)
271
- name = prefix + layer.name
271
+ name = f"{prefix}{layer.name}"
272
272
  cls_name = layer.__class__.__name__
273
273
  name = rich.markup.escape(name)
274
274
  name += f" ({highlight_symbol(rich.markup.escape(cls_name))})"
@@ -276,7 +276,7 @@ def print_summary(
276
276
  if not hasattr(layer, "built"):
277
277
  params = highlight_number(0)
278
278
  elif not layer.built:
279
- params = highlight_number(0) + " (unbuilt)"
279
+ params = f"{highlight_number(0)} (unbuilt)"
280
280
  else:
281
281
  params = highlight_number(f"{layer.count_params():,}")
282
282
 
@@ -296,7 +296,7 @@ def print_summary(
296
296
 
297
297
  def print_layer(layer, nested_level=0):
298
298
  if nested_level:
299
- prefix = " " * nested_level + "└" + " "
299
+ prefix = " " * nested_level + "└ "
300
300
  else:
301
301
  prefix = ""
302
302
 
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.12.0.dev2025082103"
4
+ __version__ = "3.12.0.dev2025082303"
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.12.0.dev2025082103
3
+ Version: 3.12.0.dev2025082303
4
4
  Summary: Multi-backend Keras
5
5
  Author-email: Keras team <keras-users@googlegroups.com>
6
6
  License: Apache License 2.0