Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/applications/resnet.py: 20%
172 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 2015 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# ==============================================================================
16"""ResNet models for Keras.
18Reference:
19 - [Deep Residual Learning for Image Recognition](
20 https://arxiv.org/abs/1512.03385) (CVPR 2015)
21"""
23import tensorflow.compat.v2 as tf
25from keras.src import backend
26from keras.src.applications import imagenet_utils
27from keras.src.engine import training
28from keras.src.layers import VersionAwareLayers
29from keras.src.utils import data_utils
30from keras.src.utils import layer_utils
32# isort: off
33from tensorflow.python.util.tf_export import keras_export
35BASE_WEIGHTS_PATH = (
36 "https://storage.googleapis.com/tensorflow/keras-applications/resnet/"
37)
38WEIGHTS_HASHES = {
39 "resnet50": (
40 "2cb95161c43110f7111970584f804107",
41 "4d473c1dd8becc155b73f8504c6f6626",
42 ),
43 "resnet101": (
44 "f1aeb4b969a6efcfb50fad2f0c20cfc5",
45 "88cf7a10940856eca736dc7b7e228a21",
46 ),
47 "resnet152": (
48 "100835be76be38e30d865e96f2aaae62",
49 "ee4c566cf9a93f14d82f913c2dc6dd0c",
50 ),
51 "resnet50v2": (
52 "3ef43a0b657b3be2300d5770ece849e0",
53 "fac2f116257151a9d068a22e544a4917",
54 ),
55 "resnet101v2": (
56 "6343647c601c52e1368623803854d971",
57 "c0ed64b8031c3730f411d2eb4eea35b5",
58 ),
59 "resnet152v2": (
60 "a49b44d1979771252814e80f8ec446f9",
61 "ed17cf2e0169df9d443503ef94b23b33",
62 ),
63 "resnext50": (
64 "67a5b30d522ed92f75a1f16eef299d1a",
65 "62527c363bdd9ec598bed41947b379fc",
66 ),
67 "resnext101": (
68 "34fb605428fcc7aa4d62f44404c11509",
69 "0f678c91647380debd923963594981b3",
70 ),
71}
73layers = None
76def ResNet(
77 stack_fn,
78 preact,
79 use_bias,
80 model_name="resnet",
81 include_top=True,
82 weights="imagenet",
83 input_tensor=None,
84 input_shape=None,
85 pooling=None,
86 classes=1000,
87 classifier_activation="softmax",
88 **kwargs,
89):
90 """Instantiates the ResNet, ResNetV2, and ResNeXt architecture.
92 Args:
93 stack_fn: a function that returns output tensor for the
94 stacked residual blocks.
95 preact: whether to use pre-activation or not
96 (True for ResNetV2, False for ResNet and ResNeXt).
97 use_bias: whether to use biases for convolutional layers or not
98 (True for ResNet and ResNetV2, False for ResNeXt).
99 model_name: string, model name.
100 include_top: whether to include the fully-connected
101 layer at the top of the network.
102 weights: one of `None` (random initialization),
103 'imagenet' (pre-training on ImageNet),
104 or the path to the weights file to be loaded.
105 input_tensor: optional Keras tensor
106 (i.e. output of `layers.Input()`)
107 to use as image input for the model.
108 input_shape: optional shape tuple, only to be specified
109 if `include_top` is False (otherwise the input shape
110 has to be `(224, 224, 3)` (with `channels_last` data format)
111 or `(3, 224, 224)` (with `channels_first` data format).
112 It should have exactly 3 inputs channels.
113 pooling: optional pooling mode for feature extraction
114 when `include_top` is `False`.
115 - `None` means that the output of the model will be
116 the 4D tensor output of the
117 last convolutional layer.
118 - `avg` means that global average pooling
119 will be applied to the output of the
120 last convolutional layer, and thus
121 the output of the model will be a 2D tensor.
122 - `max` means that global max pooling will
123 be applied.
124 classes: optional number of classes to classify images
125 into, only to be specified if `include_top` is True, and
126 if no `weights` argument is specified.
127 classifier_activation: A `str` or callable. The activation function to use
128 on the "top" layer. Ignored unless `include_top=True`. Set
129 `classifier_activation=None` to return the logits of the "top" layer.
130 When loading pretrained weights, `classifier_activation` can only
131 be `None` or `"softmax"`.
132 **kwargs: For backwards compatibility only.
134 Returns:
135 A `keras.Model` instance.
136 """
137 global layers
138 if "layers" in kwargs:
139 layers = kwargs.pop("layers")
140 else:
141 layers = VersionAwareLayers()
142 if kwargs:
143 raise ValueError(f"Unknown argument(s): {kwargs}")
144 if not (weights in {"imagenet", None} or tf.io.gfile.exists(weights)):
145 raise ValueError(
146 "The `weights` argument should be either "
147 "`None` (random initialization), `imagenet` "
148 "(pre-training on ImageNet), "
149 "or the path to the weights file to be loaded."
150 )
152 if weights == "imagenet" and include_top and classes != 1000:
153 raise ValueError(
154 'If using `weights` as `"imagenet"` with `include_top`'
155 " as true, `classes` should be 1000"
156 )
158 # Determine proper input shape
159 input_shape = imagenet_utils.obtain_input_shape(
160 input_shape,
161 default_size=224,
162 min_size=32,
163 data_format=backend.image_data_format(),
164 require_flatten=include_top,
165 weights=weights,
166 )
168 if input_tensor is None:
169 img_input = layers.Input(shape=input_shape)
170 else:
171 if not backend.is_keras_tensor(input_tensor):
172 img_input = layers.Input(tensor=input_tensor, shape=input_shape)
173 else:
174 img_input = input_tensor
176 bn_axis = 3 if backend.image_data_format() == "channels_last" else 1
178 x = layers.ZeroPadding2D(padding=((3, 3), (3, 3)), name="conv1_pad")(
179 img_input
180 )
181 x = layers.Conv2D(64, 7, strides=2, use_bias=use_bias, name="conv1_conv")(x)
183 if not preact:
184 x = layers.BatchNormalization(
185 axis=bn_axis, epsilon=1.001e-5, name="conv1_bn"
186 )(x)
187 x = layers.Activation("relu", name="conv1_relu")(x)
189 x = layers.ZeroPadding2D(padding=((1, 1), (1, 1)), name="pool1_pad")(x)
190 x = layers.MaxPooling2D(3, strides=2, name="pool1_pool")(x)
192 x = stack_fn(x)
194 if preact:
195 x = layers.BatchNormalization(
196 axis=bn_axis, epsilon=1.001e-5, name="post_bn"
197 )(x)
198 x = layers.Activation("relu", name="post_relu")(x)
200 if include_top:
201 x = layers.GlobalAveragePooling2D(name="avg_pool")(x)
202 imagenet_utils.validate_activation(classifier_activation, weights)
203 x = layers.Dense(
204 classes, activation=classifier_activation, name="predictions"
205 )(x)
206 else:
207 if pooling == "avg":
208 x = layers.GlobalAveragePooling2D(name="avg_pool")(x)
209 elif pooling == "max":
210 x = layers.GlobalMaxPooling2D(name="max_pool")(x)
212 # Ensure that the model takes into account
213 # any potential predecessors of `input_tensor`.
214 if input_tensor is not None:
215 inputs = layer_utils.get_source_inputs(input_tensor)
216 else:
217 inputs = img_input
219 # Create model.
220 model = training.Model(inputs, x, name=model_name)
222 # Load weights.
223 if (weights == "imagenet") and (model_name in WEIGHTS_HASHES):
224 if include_top:
225 file_name = model_name + "_weights_tf_dim_ordering_tf_kernels.h5"
226 file_hash = WEIGHTS_HASHES[model_name][0]
227 else:
228 file_name = (
229 model_name + "_weights_tf_dim_ordering_tf_kernels_notop.h5"
230 )
231 file_hash = WEIGHTS_HASHES[model_name][1]
232 weights_path = data_utils.get_file(
233 file_name,
234 BASE_WEIGHTS_PATH + file_name,
235 cache_subdir="models",
236 file_hash=file_hash,
237 )
238 model.load_weights(weights_path)
239 elif weights is not None:
240 model.load_weights(weights)
242 return model
245def block1(x, filters, kernel_size=3, stride=1, conv_shortcut=True, name=None):
246 """A residual block.
248 Args:
249 x: input tensor.
250 filters: integer, filters of the bottleneck layer.
251 kernel_size: default 3, kernel size of the bottleneck layer.
252 stride: default 1, stride of the first layer.
253 conv_shortcut: default True, use convolution shortcut if True,
254 otherwise identity shortcut.
255 name: string, block label.
257 Returns:
258 Output tensor for the residual block.
259 """
260 bn_axis = 3 if backend.image_data_format() == "channels_last" else 1
262 if conv_shortcut:
263 shortcut = layers.Conv2D(
264 4 * filters, 1, strides=stride, name=name + "_0_conv"
265 )(x)
266 shortcut = layers.BatchNormalization(
267 axis=bn_axis, epsilon=1.001e-5, name=name + "_0_bn"
268 )(shortcut)
269 else:
270 shortcut = x
272 x = layers.Conv2D(filters, 1, strides=stride, name=name + "_1_conv")(x)
273 x = layers.BatchNormalization(
274 axis=bn_axis, epsilon=1.001e-5, name=name + "_1_bn"
275 )(x)
276 x = layers.Activation("relu", name=name + "_1_relu")(x)
278 x = layers.Conv2D(
279 filters, kernel_size, padding="SAME", name=name + "_2_conv"
280 )(x)
281 x = layers.BatchNormalization(
282 axis=bn_axis, epsilon=1.001e-5, name=name + "_2_bn"
283 )(x)
284 x = layers.Activation("relu", name=name + "_2_relu")(x)
286 x = layers.Conv2D(4 * filters, 1, name=name + "_3_conv")(x)
287 x = layers.BatchNormalization(
288 axis=bn_axis, epsilon=1.001e-5, name=name + "_3_bn"
289 )(x)
291 x = layers.Add(name=name + "_add")([shortcut, x])
292 x = layers.Activation("relu", name=name + "_out")(x)
293 return x
296def stack1(x, filters, blocks, stride1=2, name=None):
297 """A set of stacked residual blocks.
299 Args:
300 x: input tensor.
301 filters: integer, filters of the bottleneck layer in a block.
302 blocks: integer, blocks in the stacked blocks.
303 stride1: default 2, stride of the first layer in the first block.
304 name: string, stack label.
306 Returns:
307 Output tensor for the stacked blocks.
308 """
309 x = block1(x, filters, stride=stride1, name=name + "_block1")
310 for i in range(2, blocks + 1):
311 x = block1(
312 x, filters, conv_shortcut=False, name=name + "_block" + str(i)
313 )
314 return x
317def block2(x, filters, kernel_size=3, stride=1, conv_shortcut=False, name=None):
318 """A residual block.
320 Args:
321 x: input tensor.
322 filters: integer, filters of the bottleneck layer.
323 kernel_size: default 3, kernel size of the bottleneck layer.
324 stride: default 1, stride of the first layer.
325 conv_shortcut: default False, use convolution shortcut if True,
326 otherwise identity shortcut.
327 name: string, block label.
329 Returns:
330 Output tensor for the residual block.
331 """
332 bn_axis = 3 if backend.image_data_format() == "channels_last" else 1
334 preact = layers.BatchNormalization(
335 axis=bn_axis, epsilon=1.001e-5, name=name + "_preact_bn"
336 )(x)
337 preact = layers.Activation("relu", name=name + "_preact_relu")(preact)
339 if conv_shortcut:
340 shortcut = layers.Conv2D(
341 4 * filters, 1, strides=stride, name=name + "_0_conv"
342 )(preact)
343 else:
344 shortcut = (
345 layers.MaxPooling2D(1, strides=stride)(x) if stride > 1 else x
346 )
348 x = layers.Conv2D(
349 filters, 1, strides=1, use_bias=False, name=name + "_1_conv"
350 )(preact)
351 x = layers.BatchNormalization(
352 axis=bn_axis, epsilon=1.001e-5, name=name + "_1_bn"
353 )(x)
354 x = layers.Activation("relu", name=name + "_1_relu")(x)
356 x = layers.ZeroPadding2D(padding=((1, 1), (1, 1)), name=name + "_2_pad")(x)
357 x = layers.Conv2D(
358 filters,
359 kernel_size,
360 strides=stride,
361 use_bias=False,
362 name=name + "_2_conv",
363 )(x)
364 x = layers.BatchNormalization(
365 axis=bn_axis, epsilon=1.001e-5, name=name + "_2_bn"
366 )(x)
367 x = layers.Activation("relu", name=name + "_2_relu")(x)
369 x = layers.Conv2D(4 * filters, 1, name=name + "_3_conv")(x)
370 x = layers.Add(name=name + "_out")([shortcut, x])
371 return x
374def stack2(x, filters, blocks, stride1=2, name=None):
375 """A set of stacked residual blocks.
377 Args:
378 x: input tensor.
379 filters: integer, filters of the bottleneck layer in a block.
380 blocks: integer, blocks in the stacked blocks.
381 stride1: default 2, stride of the first layer in the first block.
382 name: string, stack label.
384 Returns:
385 Output tensor for the stacked blocks.
386 """
387 x = block2(x, filters, conv_shortcut=True, name=name + "_block1")
388 for i in range(2, blocks):
389 x = block2(x, filters, name=name + "_block" + str(i))
390 x = block2(x, filters, stride=stride1, name=name + "_block" + str(blocks))
391 return x
394def block3(
395 x,
396 filters,
397 kernel_size=3,
398 stride=1,
399 groups=32,
400 conv_shortcut=True,
401 name=None,
402):
403 """A residual block.
405 Args:
406 x: input tensor.
407 filters: integer, filters of the bottleneck layer.
408 kernel_size: default 3, kernel size of the bottleneck layer.
409 stride: default 1, stride of the first layer.
410 groups: default 32, group size for grouped convolution.
411 conv_shortcut: default True, use convolution shortcut if True,
412 otherwise identity shortcut.
413 name: string, block label.
415 Returns:
416 Output tensor for the residual block.
417 """
418 bn_axis = 3 if backend.image_data_format() == "channels_last" else 1
420 if conv_shortcut:
421 shortcut = layers.Conv2D(
422 (64 // groups) * filters,
423 1,
424 strides=stride,
425 use_bias=False,
426 name=name + "_0_conv",
427 )(x)
428 shortcut = layers.BatchNormalization(
429 axis=bn_axis, epsilon=1.001e-5, name=name + "_0_bn"
430 )(shortcut)
431 else:
432 shortcut = x
434 x = layers.Conv2D(filters, 1, use_bias=False, name=name + "_1_conv")(x)
435 x = layers.BatchNormalization(
436 axis=bn_axis, epsilon=1.001e-5, name=name + "_1_bn"
437 )(x)
438 x = layers.Activation("relu", name=name + "_1_relu")(x)
440 c = filters // groups
441 x = layers.ZeroPadding2D(padding=((1, 1), (1, 1)), name=name + "_2_pad")(x)
442 x = layers.DepthwiseConv2D(
443 kernel_size,
444 strides=stride,
445 depth_multiplier=c,
446 use_bias=False,
447 name=name + "_2_conv",
448 )(x)
449 x_shape = backend.shape(x)[:-1]
450 x = backend.reshape(x, backend.concatenate([x_shape, (groups, c, c)]))
451 x = layers.Lambda(
452 lambda x: sum(x[:, :, :, :, i] for i in range(c)),
453 name=name + "_2_reduce",
454 )(x)
455 x = backend.reshape(x, backend.concatenate([x_shape, (filters,)]))
456 x = layers.BatchNormalization(
457 axis=bn_axis, epsilon=1.001e-5, name=name + "_2_bn"
458 )(x)
459 x = layers.Activation("relu", name=name + "_2_relu")(x)
461 x = layers.Conv2D(
462 (64 // groups) * filters, 1, use_bias=False, name=name + "_3_conv"
463 )(x)
464 x = layers.BatchNormalization(
465 axis=bn_axis, epsilon=1.001e-5, name=name + "_3_bn"
466 )(x)
468 x = layers.Add(name=name + "_add")([shortcut, x])
469 x = layers.Activation("relu", name=name + "_out")(x)
470 return x
473def stack3(x, filters, blocks, stride1=2, groups=32, name=None):
474 """A set of stacked residual blocks.
476 Args:
477 x: input tensor.
478 filters: integer, filters of the bottleneck layer in a block.
479 blocks: integer, blocks in the stacked blocks.
480 stride1: default 2, stride of the first layer in the first block.
481 groups: default 32, group size for grouped convolution.
482 name: string, stack label.
484 Returns:
485 Output tensor for the stacked blocks.
486 """
487 x = block3(x, filters, stride=stride1, groups=groups, name=name + "_block1")
488 for i in range(2, blocks + 1):
489 x = block3(
490 x,
491 filters,
492 groups=groups,
493 conv_shortcut=False,
494 name=name + "_block" + str(i),
495 )
496 return x
499@keras_export(
500 "keras.applications.resnet50.ResNet50",
501 "keras.applications.resnet.ResNet50",
502 "keras.applications.ResNet50",
503)
504def ResNet50(
505 include_top=True,
506 weights="imagenet",
507 input_tensor=None,
508 input_shape=None,
509 pooling=None,
510 classes=1000,
511 **kwargs,
512):
513 """Instantiates the ResNet50 architecture."""
515 def stack_fn(x):
516 x = stack1(x, 64, 3, stride1=1, name="conv2")
517 x = stack1(x, 128, 4, name="conv3")
518 x = stack1(x, 256, 6, name="conv4")
519 return stack1(x, 512, 3, name="conv5")
521 return ResNet(
522 stack_fn,
523 False,
524 True,
525 "resnet50",
526 include_top,
527 weights,
528 input_tensor,
529 input_shape,
530 pooling,
531 classes,
532 **kwargs,
533 )
536@keras_export(
537 "keras.applications.resnet.ResNet101", "keras.applications.ResNet101"
538)
539def ResNet101(
540 include_top=True,
541 weights="imagenet",
542 input_tensor=None,
543 input_shape=None,
544 pooling=None,
545 classes=1000,
546 **kwargs,
547):
548 """Instantiates the ResNet101 architecture."""
550 def stack_fn(x):
551 x = stack1(x, 64, 3, stride1=1, name="conv2")
552 x = stack1(x, 128, 4, name="conv3")
553 x = stack1(x, 256, 23, name="conv4")
554 return stack1(x, 512, 3, name="conv5")
556 return ResNet(
557 stack_fn,
558 False,
559 True,
560 "resnet101",
561 include_top,
562 weights,
563 input_tensor,
564 input_shape,
565 pooling,
566 classes,
567 **kwargs,
568 )
571@keras_export(
572 "keras.applications.resnet.ResNet152", "keras.applications.ResNet152"
573)
574def ResNet152(
575 include_top=True,
576 weights="imagenet",
577 input_tensor=None,
578 input_shape=None,
579 pooling=None,
580 classes=1000,
581 **kwargs,
582):
583 """Instantiates the ResNet152 architecture."""
585 def stack_fn(x):
586 x = stack1(x, 64, 3, stride1=1, name="conv2")
587 x = stack1(x, 128, 8, name="conv3")
588 x = stack1(x, 256, 36, name="conv4")
589 return stack1(x, 512, 3, name="conv5")
591 return ResNet(
592 stack_fn,
593 False,
594 True,
595 "resnet152",
596 include_top,
597 weights,
598 input_tensor,
599 input_shape,
600 pooling,
601 classes,
602 **kwargs,
603 )
606@keras_export(
607 "keras.applications.resnet50.preprocess_input",
608 "keras.applications.resnet.preprocess_input",
609)
610def preprocess_input(x, data_format=None):
611 return imagenet_utils.preprocess_input(
612 x, data_format=data_format, mode="caffe"
613 )
616@keras_export(
617 "keras.applications.resnet50.decode_predictions",
618 "keras.applications.resnet.decode_predictions",
619)
620def decode_predictions(preds, top=5):
621 return imagenet_utils.decode_predictions(preds, top=top)
624preprocess_input.__doc__ = imagenet_utils.PREPROCESS_INPUT_DOC.format(
625 mode="",
626 ret=imagenet_utils.PREPROCESS_INPUT_RET_DOC_CAFFE,
627 error=imagenet_utils.PREPROCESS_INPUT_ERROR_DOC,
628)
629decode_predictions.__doc__ = imagenet_utils.decode_predictions.__doc__
631DOC = """
633 Reference:
634 - [Deep Residual Learning for Image Recognition](
635 https://arxiv.org/abs/1512.03385) (CVPR 2015)
637 For image classification use cases, see
638 [this page for detailed examples](
639 https://keras.io/api/applications/#usage-examples-for-image-classification-models).
641 For transfer learning use cases, make sure to read the
642 [guide to transfer learning & fine-tuning](
643 https://keras.io/guides/transfer_learning/).
645 Note: each Keras Application expects a specific kind of input preprocessing.
646 For ResNet, call `tf.keras.applications.resnet.preprocess_input` on your
647 inputs before passing them to the model.
648 `resnet.preprocess_input` will convert the input images from RGB to BGR,
649 then will zero-center each color channel with respect to the ImageNet dataset,
650 without scaling.
652 Args:
653 include_top: whether to include the fully-connected
654 layer at the top of the network.
655 weights: one of `None` (random initialization),
656 'imagenet' (pre-training on ImageNet),
657 or the path to the weights file to be loaded.
658 input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)
659 to use as image input for the model.
660 input_shape: optional shape tuple, only to be specified
661 if `include_top` is False (otherwise the input shape
662 has to be `(224, 224, 3)` (with `'channels_last'` data format)
663 or `(3, 224, 224)` (with `'channels_first'` data format).
664 It should have exactly 3 inputs channels,
665 and width and height should be no smaller than 32.
666 E.g. `(200, 200, 3)` would be one valid value.
667 pooling: Optional pooling mode for feature extraction
668 when `include_top` is `False`.
669 - `None` means that the output of the model will be
670 the 4D tensor output of the
671 last convolutional block.
672 - `avg` means that global average pooling
673 will be applied to the output of the
674 last convolutional block, and thus
675 the output of the model will be a 2D tensor.
676 - `max` means that global max pooling will
677 be applied.
678 classes: optional number of classes to classify images
679 into, only to be specified if `include_top` is True, and
680 if no `weights` argument is specified.
681 classifier_activation: A `str` or callable. The activation function to use
682 on the "top" layer. Ignored unless `include_top=True`. Set
683 `classifier_activation=None` to return the logits of the "top" layer.
684 When loading pretrained weights, `classifier_activation` can only
685 be `None` or `"softmax"`.
687 Returns:
688 A Keras model instance.
689"""
691setattr(ResNet50, "__doc__", ResNet50.__doc__ + DOC)
692setattr(ResNet101, "__doc__", ResNet101.__doc__ + DOC)
693setattr(ResNet152, "__doc__", ResNet152.__doc__ + DOC)