Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/applications/mobilenet_v3.py: 15%
209 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-03 07:57 +0000
1# Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
17"""MobileNet v3 models for Keras."""
19import tensorflow.compat.v2 as tf
21from keras.src import backend
22from keras.src import models
23from keras.src.applications import imagenet_utils
24from keras.src.layers import VersionAwareLayers
25from keras.src.utils import data_utils
26from keras.src.utils import layer_utils
28# isort: off
29from tensorflow.python.platform import tf_logging as logging
30from tensorflow.python.util.tf_export import keras_export
32# TODO(scottzhu): Change this to the GCS path.
33BASE_WEIGHT_PATH = (
34 "https://storage.googleapis.com/tensorflow/keras-applications/mobilenet_v3/"
35)
36WEIGHTS_HASHES = {
37 "large_224_0.75_float": (
38 "765b44a33ad4005b3ac83185abf1d0eb",
39 "40af19a13ebea4e2ee0c676887f69a2e",
40 ),
41 "large_224_1.0_float": (
42 "59e551e166be033d707958cf9e29a6a7",
43 "07fb09a5933dd0c8eaafa16978110389",
44 ),
45 "large_minimalistic_224_1.0_float": (
46 "675e7b876c45c57e9e63e6d90a36599c",
47 "ec5221f64a2f6d1ef965a614bdae7973",
48 ),
49 "small_224_0.75_float": (
50 "cb65d4e5be93758266aa0a7f2c6708b7",
51 "ebdb5cc8e0b497cd13a7c275d475c819",
52 ),
53 "small_224_1.0_float": (
54 "8768d4c2e7dee89b9d02b2d03d65d862",
55 "d3e8ec802a04aa4fc771ee12a9a9b836",
56 ),
57 "small_minimalistic_224_1.0_float": (
58 "99cd97fb2fcdad2bf028eb838de69e37",
59 "cde8136e733e811080d9fcd8a252f7e4",
60 ),
61}
63layers = VersionAwareLayers()
66BASE_DOCSTRING = """Instantiates the {name} architecture.
68 Reference:
69 - [Searching for MobileNetV3](
70 https://arxiv.org/pdf/1905.02244.pdf) (ICCV 2019)
72 The following table describes the performance of MobileNets v3:
73 ------------------------------------------------------------------------
74 MACs stands for Multiply Adds
76 |Classification Checkpoint|MACs(M)|Parameters(M)|Top1 Accuracy|Pixel1 CPU(ms)|
77 |---|---|---|---|---|
78 | mobilenet_v3_large_1.0_224 | 217 | 5.4 | 75.6 | 51.2 |
79 | mobilenet_v3_large_0.75_224 | 155 | 4.0 | 73.3 | 39.8 |
80 | mobilenet_v3_large_minimalistic_1.0_224 | 209 | 3.9 | 72.3 | 44.1 |
81 | mobilenet_v3_small_1.0_224 | 66 | 2.9 | 68.1 | 15.8 |
82 | mobilenet_v3_small_0.75_224 | 44 | 2.4 | 65.4 | 12.8 |
83 | mobilenet_v3_small_minimalistic_1.0_224 | 65 | 2.0 | 61.9 | 12.2 |
85 For image classification use cases, see
86 [this page for detailed examples](
87 https://keras.io/api/applications/#usage-examples-for-image-classification-models).
89 For transfer learning use cases, make sure to read the
90 [guide to transfer learning & fine-tuning](
91 https://keras.io/guides/transfer_learning/).
93 Note: each Keras Application expects a specific kind of input preprocessing.
94 For MobileNetV3, by default input preprocessing is included as a part of the
95 model (as a `Rescaling` layer), and thus
96 `tf.keras.applications.mobilenet_v3.preprocess_input` is actually a
97 pass-through function. In this use case, MobileNetV3 models expect their
98 inputs to be float tensors of pixels with values in the [0-255] range.
99 At the same time, preprocessing as a part of the model (i.e. `Rescaling`
100 layer) can be disabled by setting `include_preprocessing` argument to False.
101 With preprocessing disabled MobileNetV3 models expect their inputs to be float
102 tensors of pixels with values in the [-1, 1] range.
104 Args:
105 input_shape: Optional shape tuple, to be specified if you would
106 like to use a model with an input image resolution that is not
107 (224, 224, 3).
108 It should have exactly 3 inputs channels (224, 224, 3).
109 You can also omit this option if you would like
110 to infer input_shape from an input_tensor.
111 If you choose to include both input_tensor and input_shape then
112 input_shape will be used if they match, if the shapes
113 do not match then we will throw an error.
114 E.g. `(160, 160, 3)` would be one valid value.
115 alpha: controls the width of the network. This is known as the
116 depth multiplier in the MobileNetV3 paper, but the name is kept for
117 consistency with MobileNetV1 in Keras.
118 - If `alpha` < 1.0, proportionally decreases the number
119 of filters in each layer.
120 - If `alpha` > 1.0, proportionally increases the number
121 of filters in each layer.
122 - If `alpha` = 1, default number of filters from the paper
123 are used at each layer.
124 minimalistic: In addition to large and small models this module also
125 contains so-called minimalistic models, these models have the same
126 per-layer dimensions characteristic as MobilenetV3 however, they don't
127 utilize any of the advanced blocks (squeeze-and-excite units, hard-swish,
128 and 5x5 convolutions). While these models are less efficient on CPU, they
129 are much more performant on GPU/DSP.
130 include_top: Boolean, whether to include the fully-connected
131 layer at the top of the network. Defaults to `True`.
132 weights: String, one of `None` (random initialization),
133 'imagenet' (pre-training on ImageNet),
134 or the path to the weights file to be loaded.
135 input_tensor: Optional Keras tensor (i.e. output of
136 `layers.Input()`)
137 to use as image input for the model.
138 pooling: String, optional pooling mode for feature extraction
139 when `include_top` is `False`.
140 - `None` means that the output of the model
141 will be the 4D tensor output of the
142 last convolutional block.
143 - `avg` means that global average pooling
144 will be applied to the output of the
145 last convolutional block, and thus
146 the output of the model will be a
147 2D tensor.
148 - `max` means that global max pooling will
149 be applied.
150 classes: Integer, optional number of classes to classify images
151 into, only to be specified if `include_top` is True, and
152 if no `weights` argument is specified.
153 dropout_rate: fraction of the input units to drop on the last layer.
154 classifier_activation: A `str` or callable. The activation function to use
155 on the "top" layer. Ignored unless `include_top=True`. Set
156 `classifier_activation=None` to return the logits of the "top" layer.
157 When loading pretrained weights, `classifier_activation` can only
158 be `None` or `"softmax"`.
159 include_preprocessing: Boolean, whether to include the preprocessing
160 layer (`Rescaling`) at the bottom of the network. Defaults to `True`.
162 Call arguments:
163 inputs: A floating point `numpy.array` or a `tf.Tensor`, 4D with 3 color
164 channels, with values in the range [0, 255] if `include_preprocessing`
165 is True and in the range [-1, 1] otherwise.
167 Returns:
168 A `keras.Model` instance.
169"""
172def MobileNetV3(
173 stack_fn,
174 last_point_ch,
175 input_shape=None,
176 alpha=1.0,
177 model_type="large",
178 minimalistic=False,
179 include_top=True,
180 weights="imagenet",
181 input_tensor=None,
182 classes=1000,
183 pooling=None,
184 dropout_rate=0.2,
185 classifier_activation="softmax",
186 include_preprocessing=True,
187):
188 if not (weights in {"imagenet", None} or tf.io.gfile.exists(weights)):
189 raise ValueError(
190 "The `weights` argument should be either "
191 "`None` (random initialization), `imagenet` "
192 "(pre-training on ImageNet), "
193 "or the path to the weights file to be loaded. "
194 f"Received weights={weights}"
195 )
197 if weights == "imagenet" and include_top and classes != 1000:
198 raise ValueError(
199 'If using `weights` as `"imagenet"` with `include_top` '
200 "as true, `classes` should be 1000. "
201 f"Received classes={classes}"
202 )
204 # Determine proper input shape and default size.
205 # If both input_shape and input_tensor are used, they should match
206 if input_shape is not None and input_tensor is not None:
207 try:
208 is_input_t_tensor = backend.is_keras_tensor(input_tensor)
209 except ValueError:
210 try:
211 is_input_t_tensor = backend.is_keras_tensor(
212 layer_utils.get_source_inputs(input_tensor)
213 )
214 except ValueError:
215 raise ValueError(
216 "input_tensor: ",
217 input_tensor,
218 "is not type input_tensor. "
219 f"Received type(input_tensor)={type(input_tensor)}",
220 )
221 if is_input_t_tensor:
222 if backend.image_data_format() == "channels_first":
223 if backend.int_shape(input_tensor)[1] != input_shape[1]:
224 raise ValueError(
225 "When backend.image_data_format()=channels_first, "
226 "input_shape[1] must equal "
227 "backend.int_shape(input_tensor)[1]. Received "
228 f"input_shape={input_shape}, "
229 "backend.int_shape(input_tensor)="
230 f"{backend.int_shape(input_tensor)}"
231 )
232 else:
233 if backend.int_shape(input_tensor)[2] != input_shape[1]:
234 raise ValueError(
235 "input_shape[1] must equal "
236 "backend.int_shape(input_tensor)[2]. Received "
237 f"input_shape={input_shape}, "
238 "backend.int_shape(input_tensor)="
239 f"{backend.int_shape(input_tensor)}"
240 )
241 else:
242 raise ValueError(
243 "input_tensor specified: ",
244 input_tensor,
245 "is not a keras tensor",
246 )
248 # If input_shape is None, infer shape from input_tensor
249 if input_shape is None and input_tensor is not None:
251 try:
252 backend.is_keras_tensor(input_tensor)
253 except ValueError:
254 raise ValueError(
255 "input_tensor: ",
256 input_tensor,
257 "is type: ",
258 type(input_tensor),
259 "which is not a valid type",
260 )
262 if backend.is_keras_tensor(input_tensor):
263 if backend.image_data_format() == "channels_first":
264 rows = backend.int_shape(input_tensor)[2]
265 cols = backend.int_shape(input_tensor)[3]
266 input_shape = (3, cols, rows)
267 else:
268 rows = backend.int_shape(input_tensor)[1]
269 cols = backend.int_shape(input_tensor)[2]
270 input_shape = (cols, rows, 3)
271 # If input_shape is None and input_tensor is None using standard shape
272 if input_shape is None and input_tensor is None:
273 input_shape = (None, None, 3)
275 if backend.image_data_format() == "channels_last":
276 row_axis, col_axis = (0, 1)
277 else:
278 row_axis, col_axis = (1, 2)
279 rows = input_shape[row_axis]
280 cols = input_shape[col_axis]
281 if rows and cols and (rows < 32 or cols < 32):
282 raise ValueError(
283 "Input size must be at least 32x32; Received `input_shape="
284 f"{input_shape}`"
285 )
286 if weights == "imagenet":
287 if (
288 not minimalistic
289 and alpha not in [0.75, 1.0]
290 or minimalistic
291 and alpha != 1.0
292 ):
293 raise ValueError(
294 "If imagenet weights are being loaded, "
295 "alpha can be one of `0.75`, `1.0` for non minimalistic "
296 "or `1.0` for minimalistic only."
297 )
299 if rows != cols or rows != 224:
300 logging.warning(
301 "`input_shape` is undefined or non-square, "
302 "or `rows` is not 224. "
303 "Weights for input shape (224, 224) will be "
304 "loaded as the default."
305 )
307 if input_tensor is None:
308 img_input = layers.Input(shape=input_shape)
309 else:
310 if not backend.is_keras_tensor(input_tensor):
311 img_input = layers.Input(tensor=input_tensor, shape=input_shape)
312 else:
313 img_input = input_tensor
315 channel_axis = 1 if backend.image_data_format() == "channels_first" else -1
317 if minimalistic:
318 kernel = 3
319 activation = relu
320 se_ratio = None
321 else:
322 kernel = 5
323 activation = hard_swish
324 se_ratio = 0.25
326 x = img_input
327 if include_preprocessing:
328 x = layers.Rescaling(scale=1.0 / 127.5, offset=-1.0)(x)
329 x = layers.Conv2D(
330 16,
331 kernel_size=3,
332 strides=(2, 2),
333 padding="same",
334 use_bias=False,
335 name="Conv",
336 )(x)
337 x = layers.BatchNormalization(
338 axis=channel_axis, epsilon=1e-3, momentum=0.999, name="Conv/BatchNorm"
339 )(x)
340 x = activation(x)
342 x = stack_fn(x, kernel, activation, se_ratio)
344 last_conv_ch = _depth(backend.int_shape(x)[channel_axis] * 6)
346 # if the width multiplier is greater than 1 we
347 # increase the number of output channels
348 if alpha > 1.0:
349 last_point_ch = _depth(last_point_ch * alpha)
350 x = layers.Conv2D(
351 last_conv_ch,
352 kernel_size=1,
353 padding="same",
354 use_bias=False,
355 name="Conv_1",
356 )(x)
357 x = layers.BatchNormalization(
358 axis=channel_axis, epsilon=1e-3, momentum=0.999, name="Conv_1/BatchNorm"
359 )(x)
360 x = activation(x)
361 if include_top:
362 x = layers.GlobalAveragePooling2D(keepdims=True)(x)
363 x = layers.Conv2D(
364 last_point_ch,
365 kernel_size=1,
366 padding="same",
367 use_bias=True,
368 name="Conv_2",
369 )(x)
370 x = activation(x)
372 if dropout_rate > 0:
373 x = layers.Dropout(dropout_rate)(x)
374 x = layers.Conv2D(
375 classes, kernel_size=1, padding="same", name="Logits"
376 )(x)
377 x = layers.Flatten()(x)
378 imagenet_utils.validate_activation(classifier_activation, weights)
379 x = layers.Activation(
380 activation=classifier_activation, name="Predictions"
381 )(x)
382 else:
383 if pooling == "avg":
384 x = layers.GlobalAveragePooling2D(name="avg_pool")(x)
385 elif pooling == "max":
386 x = layers.GlobalMaxPooling2D(name="max_pool")(x)
387 # Ensure that the model takes into account
388 # any potential predecessors of `input_tensor`.
389 if input_tensor is not None:
390 inputs = layer_utils.get_source_inputs(input_tensor)
391 else:
392 inputs = img_input
394 # Create model.
395 model = models.Model(inputs, x, name="MobilenetV3" + model_type)
397 # Load weights.
398 if weights == "imagenet":
399 model_name = "{}{}_224_{}_float".format(
400 model_type, "_minimalistic" if minimalistic else "", str(alpha)
401 )
402 if include_top:
403 file_name = "weights_mobilenet_v3_" + model_name + ".h5"
404 file_hash = WEIGHTS_HASHES[model_name][0]
405 else:
406 file_name = "weights_mobilenet_v3_" + model_name + "_no_top_v2.h5"
407 file_hash = WEIGHTS_HASHES[model_name][1]
408 weights_path = data_utils.get_file(
409 file_name,
410 BASE_WEIGHT_PATH + file_name,
411 cache_subdir="models",
412 file_hash=file_hash,
413 )
414 model.load_weights(weights_path)
415 elif weights is not None:
416 model.load_weights(weights)
418 return model
421@keras_export("keras.applications.MobileNetV3Small")
422def MobileNetV3Small(
423 input_shape=None,
424 alpha=1.0,
425 minimalistic=False,
426 include_top=True,
427 weights="imagenet",
428 input_tensor=None,
429 classes=1000,
430 pooling=None,
431 dropout_rate=0.2,
432 classifier_activation="softmax",
433 include_preprocessing=True,
434):
435 def stack_fn(x, kernel, activation, se_ratio):
436 def depth(d):
437 return _depth(d * alpha)
439 x = _inverted_res_block(x, 1, depth(16), 3, 2, se_ratio, relu, 0)
440 x = _inverted_res_block(x, 72.0 / 16, depth(24), 3, 2, None, relu, 1)
441 x = _inverted_res_block(x, 88.0 / 24, depth(24), 3, 1, None, relu, 2)
442 x = _inverted_res_block(
443 x, 4, depth(40), kernel, 2, se_ratio, activation, 3
444 )
445 x = _inverted_res_block(
446 x, 6, depth(40), kernel, 1, se_ratio, activation, 4
447 )
448 x = _inverted_res_block(
449 x, 6, depth(40), kernel, 1, se_ratio, activation, 5
450 )
451 x = _inverted_res_block(
452 x, 3, depth(48), kernel, 1, se_ratio, activation, 6
453 )
454 x = _inverted_res_block(
455 x, 3, depth(48), kernel, 1, se_ratio, activation, 7
456 )
457 x = _inverted_res_block(
458 x, 6, depth(96), kernel, 2, se_ratio, activation, 8
459 )
460 x = _inverted_res_block(
461 x, 6, depth(96), kernel, 1, se_ratio, activation, 9
462 )
463 x = _inverted_res_block(
464 x, 6, depth(96), kernel, 1, se_ratio, activation, 10
465 )
466 return x
468 return MobileNetV3(
469 stack_fn,
470 1024,
471 input_shape,
472 alpha,
473 "small",
474 minimalistic,
475 include_top,
476 weights,
477 input_tensor,
478 classes,
479 pooling,
480 dropout_rate,
481 classifier_activation,
482 include_preprocessing,
483 )
486@keras_export("keras.applications.MobileNetV3Large")
487def MobileNetV3Large(
488 input_shape=None,
489 alpha=1.0,
490 minimalistic=False,
491 include_top=True,
492 weights="imagenet",
493 input_tensor=None,
494 classes=1000,
495 pooling=None,
496 dropout_rate=0.2,
497 classifier_activation="softmax",
498 include_preprocessing=True,
499):
500 def stack_fn(x, kernel, activation, se_ratio):
501 def depth(d):
502 return _depth(d * alpha)
504 x = _inverted_res_block(x, 1, depth(16), 3, 1, None, relu, 0)
505 x = _inverted_res_block(x, 4, depth(24), 3, 2, None, relu, 1)
506 x = _inverted_res_block(x, 3, depth(24), 3, 1, None, relu, 2)
507 x = _inverted_res_block(x, 3, depth(40), kernel, 2, se_ratio, relu, 3)
508 x = _inverted_res_block(x, 3, depth(40), kernel, 1, se_ratio, relu, 4)
509 x = _inverted_res_block(x, 3, depth(40), kernel, 1, se_ratio, relu, 5)
510 x = _inverted_res_block(x, 6, depth(80), 3, 2, None, activation, 6)
511 x = _inverted_res_block(x, 2.5, depth(80), 3, 1, None, activation, 7)
512 x = _inverted_res_block(x, 2.3, depth(80), 3, 1, None, activation, 8)
513 x = _inverted_res_block(x, 2.3, depth(80), 3, 1, None, activation, 9)
514 x = _inverted_res_block(
515 x, 6, depth(112), 3, 1, se_ratio, activation, 10
516 )
517 x = _inverted_res_block(
518 x, 6, depth(112), 3, 1, se_ratio, activation, 11
519 )
520 x = _inverted_res_block(
521 x, 6, depth(160), kernel, 2, se_ratio, activation, 12
522 )
523 x = _inverted_res_block(
524 x, 6, depth(160), kernel, 1, se_ratio, activation, 13
525 )
526 x = _inverted_res_block(
527 x, 6, depth(160), kernel, 1, se_ratio, activation, 14
528 )
529 return x
531 return MobileNetV3(
532 stack_fn,
533 1280,
534 input_shape,
535 alpha,
536 "large",
537 minimalistic,
538 include_top,
539 weights,
540 input_tensor,
541 classes,
542 pooling,
543 dropout_rate,
544 classifier_activation,
545 include_preprocessing,
546 )
549MobileNetV3Small.__doc__ = BASE_DOCSTRING.format(name="MobileNetV3Small")
550MobileNetV3Large.__doc__ = BASE_DOCSTRING.format(name="MobileNetV3Large")
553def relu(x):
554 return layers.ReLU()(x)
557def hard_sigmoid(x):
558 return layers.ReLU(6.0)(x + 3.0) * (1.0 / 6.0)
561def hard_swish(x):
562 return layers.Multiply()([x, hard_sigmoid(x)])
565# This function is taken from the original tf repo.
566# It ensures that all layers have a channel number that is divisible by 8
567# It can be seen here:
568# https://github.com/tensorflow/models/blob/master/research/
569# slim/nets/mobilenet/mobilenet.py
572def _depth(v, divisor=8, min_value=None):
573 if min_value is None:
574 min_value = divisor
575 new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
576 # Make sure that round down does not go down by more than 10%.
577 if new_v < 0.9 * v:
578 new_v += divisor
579 return new_v
582def _se_block(inputs, filters, se_ratio, prefix):
583 x = layers.GlobalAveragePooling2D(
584 keepdims=True, name=prefix + "squeeze_excite/AvgPool"
585 )(inputs)
586 x = layers.Conv2D(
587 _depth(filters * se_ratio),
588 kernel_size=1,
589 padding="same",
590 name=prefix + "squeeze_excite/Conv",
591 )(x)
592 x = layers.ReLU(name=prefix + "squeeze_excite/Relu")(x)
593 x = layers.Conv2D(
594 filters,
595 kernel_size=1,
596 padding="same",
597 name=prefix + "squeeze_excite/Conv_1",
598 )(x)
599 x = hard_sigmoid(x)
600 x = layers.Multiply(name=prefix + "squeeze_excite/Mul")([inputs, x])
601 return x
604def _inverted_res_block(
605 x, expansion, filters, kernel_size, stride, se_ratio, activation, block_id
606):
607 channel_axis = 1 if backend.image_data_format() == "channels_first" else -1
608 shortcut = x
609 prefix = "expanded_conv/"
610 infilters = backend.int_shape(x)[channel_axis]
611 if block_id:
612 # Expand
613 prefix = f"expanded_conv_{block_id}/"
614 x = layers.Conv2D(
615 _depth(infilters * expansion),
616 kernel_size=1,
617 padding="same",
618 use_bias=False,
619 name=prefix + "expand",
620 )(x)
621 x = layers.BatchNormalization(
622 axis=channel_axis,
623 epsilon=1e-3,
624 momentum=0.999,
625 name=prefix + "expand/BatchNorm",
626 )(x)
627 x = activation(x)
629 if stride == 2:
630 x = layers.ZeroPadding2D(
631 padding=imagenet_utils.correct_pad(x, kernel_size),
632 name=prefix + "depthwise/pad",
633 )(x)
634 x = layers.DepthwiseConv2D(
635 kernel_size,
636 strides=stride,
637 padding="same" if stride == 1 else "valid",
638 use_bias=False,
639 name=prefix + "depthwise",
640 )(x)
641 x = layers.BatchNormalization(
642 axis=channel_axis,
643 epsilon=1e-3,
644 momentum=0.999,
645 name=prefix + "depthwise/BatchNorm",
646 )(x)
647 x = activation(x)
649 if se_ratio:
650 x = _se_block(x, _depth(infilters * expansion), se_ratio, prefix)
652 x = layers.Conv2D(
653 filters,
654 kernel_size=1,
655 padding="same",
656 use_bias=False,
657 name=prefix + "project",
658 )(x)
659 x = layers.BatchNormalization(
660 axis=channel_axis,
661 epsilon=1e-3,
662 momentum=0.999,
663 name=prefix + "project/BatchNorm",
664 )(x)
666 if stride == 1 and infilters == filters:
667 x = layers.Add(name=prefix + "Add")([shortcut, x])
668 return x
671@keras_export("keras.applications.mobilenet_v3.preprocess_input")
672def preprocess_input(x, data_format=None):
673 """A placeholder method for backward compatibility.
675 The preprocessing logic has been included in the mobilenet_v3 model
676 implementation. Users are no longer required to call this method to
677 normalize the input data. This method does nothing and only kept as a
678 placeholder to align the API surface between old and new version of model.
680 Args:
681 x: A floating point `numpy.array` or a `tf.Tensor`.
682 data_format: Optional data format of the image tensor/array. `None` means
683 the global setting `tf.keras.backend.image_data_format()` is used
684 (unless you changed it, it uses "channels_last").
685 Defaults to `None`.
687 Returns:
688 Unchanged `numpy.array` or `tf.Tensor`.
689 """
690 return x
693@keras_export("keras.applications.mobilenet_v3.decode_predictions")
694def decode_predictions(preds, top=5):
695 return imagenet_utils.decode_predictions(preds, top=top)
698decode_predictions.__doc__ = imagenet_utils.decode_predictions.__doc__