Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/keras/src/applications/inception_resnet_v2.py: 18%

154 statements  

« prev     ^ index     » next       coverage.py v7.4.0, created at 2024-01-03 07:57 +0000

1# Copyright 2017 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# ============================================================================== 

15 

16"""Inception-ResNet V2 model for Keras. 

17 

18Reference: 

19 - [Inception-v4, Inception-ResNet and the Impact of 

20 Residual Connections on Learning](https://arxiv.org/abs/1602.07261) 

21 (AAAI 2017) 

22""" 

23 

24import tensorflow.compat.v2 as tf 

25 

26import keras.src as keras 

27from keras.src import backend 

28from keras.src import layers as keras_layers 

29from keras.src.applications import imagenet_utils 

30from keras.src.engine import training 

31from keras.src.layers import VersionAwareLayers 

32from keras.src.utils import data_utils 

33from keras.src.utils import layer_utils 

34 

35# isort: off 

36from tensorflow.python.util.tf_export import keras_export 

37 

38BASE_WEIGHT_URL = ( 

39 "https://storage.googleapis.com/tensorflow/" 

40 "keras-applications/inception_resnet_v2/" 

41) 

42layers = None 

43 

44 

45@keras_export( 

46 "keras.applications.inception_resnet_v2.InceptionResNetV2", 

47 "keras.applications.InceptionResNetV2", 

48) 

49def InceptionResNetV2( 

50 include_top=True, 

51 weights="imagenet", 

52 input_tensor=None, 

53 input_shape=None, 

54 pooling=None, 

55 classes=1000, 

56 classifier_activation="softmax", 

57 **kwargs, 

58): 

59 """Instantiates the Inception-ResNet v2 architecture. 

60 

61 Reference: 

62 - [Inception-v4, Inception-ResNet and the Impact of 

63 Residual Connections on Learning](https://arxiv.org/abs/1602.07261) 

64 (AAAI 2017) 

65 

66 This function returns a Keras image classification model, 

67 optionally loaded with weights pre-trained on ImageNet. 

68 

69 For image classification use cases, see 

70 [this page for detailed examples]( 

71 https://keras.io/api/applications/#usage-examples-for-image-classification-models). 

72 

73 For transfer learning use cases, make sure to read the 

74 [guide to transfer learning & fine-tuning]( 

75 https://keras.io/guides/transfer_learning/). 

76 

77 Note: each Keras Application expects a specific kind of input preprocessing. 

78 For InceptionResNetV2, call 

79 `tf.keras.applications.inception_resnet_v2.preprocess_input` 

80 on your inputs before passing them to the model. 

81 `inception_resnet_v2.preprocess_input` 

82 will scale input pixels between -1 and 1. 

83 

84 Args: 

85 include_top: whether to include the fully-connected 

86 layer at the top of the network. 

87 weights: one of `None` (random initialization), 

88 'imagenet' (pre-training on ImageNet), 

89 or the path to the weights file to be loaded. 

90 input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 

91 to use as image input for the model. 

92 input_shape: optional shape tuple, only to be specified 

93 if `include_top` is `False` (otherwise the input shape 

94 has to be `(299, 299, 3)` (with `'channels_last'` data format) 

95 or `(3, 299, 299)` (with `'channels_first'` data format). 

96 It should have exactly 3 inputs channels, 

97 and width and height should be no smaller than 75. 

98 E.g. `(150, 150, 3)` would be one valid value. 

99 pooling: Optional pooling mode for feature extraction 

100 when `include_top` is `False`. 

101 - `None` means that the output of the model will be 

102 the 4D tensor output of the last convolutional block. 

103 - `'avg'` means that global average pooling 

104 will be applied to the output of the 

105 last convolutional block, and thus 

106 the output of the model will be a 2D tensor. 

107 - `'max'` means that global max pooling will be applied. 

108 classes: optional number of classes to classify images 

109 into, only to be specified if `include_top` is `True`, and 

110 if no `weights` argument is specified. 

111 classifier_activation: A `str` or callable. The activation function to use 

112 on the "top" layer. Ignored unless `include_top=True`. Set 

113 `classifier_activation=None` to return the logits of the "top" layer. 

114 When loading pretrained weights, `classifier_activation` can only 

115 be `None` or `"softmax"`. 

116 **kwargs: For backwards compatibility only. 

117 

118 Returns: 

119 A `keras.Model` instance. 

120 """ 

121 global layers 

122 if "layers" in kwargs: 

123 layers = kwargs.pop("layers") 

124 else: 

125 layers = VersionAwareLayers() 

126 if kwargs: 

127 raise ValueError(f"Unknown argument(s): {kwargs}") 

128 if not (weights in {"imagenet", None} or tf.io.gfile.exists(weights)): 

129 raise ValueError( 

130 "The `weights` argument should be either " 

131 "`None` (random initialization), `imagenet` " 

132 "(pre-training on ImageNet), " 

133 "or the path to the weights file to be loaded." 

134 ) 

135 

136 if weights == "imagenet" and include_top and classes != 1000: 

137 raise ValueError( 

138 'If using `weights` as `"imagenet"` with `include_top`' 

139 " as true, `classes` should be 1000" 

140 ) 

141 

142 # Determine proper input shape 

143 input_shape = imagenet_utils.obtain_input_shape( 

144 input_shape, 

145 default_size=299, 

146 min_size=75, 

147 data_format=backend.image_data_format(), 

148 require_flatten=include_top, 

149 weights=weights, 

150 ) 

151 

152 if input_tensor is None: 

153 img_input = layers.Input(shape=input_shape) 

154 else: 

155 if not backend.is_keras_tensor(input_tensor): 

156 img_input = layers.Input(tensor=input_tensor, shape=input_shape) 

157 else: 

158 img_input = input_tensor 

159 

160 # Stem block: 35 x 35 x 192 

161 x = conv2d_bn(img_input, 32, 3, strides=2, padding="valid") 

162 x = conv2d_bn(x, 32, 3, padding="valid") 

163 x = conv2d_bn(x, 64, 3) 

164 x = layers.MaxPooling2D(3, strides=2)(x) 

165 x = conv2d_bn(x, 80, 1, padding="valid") 

166 x = conv2d_bn(x, 192, 3, padding="valid") 

167 x = layers.MaxPooling2D(3, strides=2)(x) 

168 

169 # Mixed 5b (Inception-A block): 35 x 35 x 320 

170 branch_0 = conv2d_bn(x, 96, 1) 

171 branch_1 = conv2d_bn(x, 48, 1) 

172 branch_1 = conv2d_bn(branch_1, 64, 5) 

173 branch_2 = conv2d_bn(x, 64, 1) 

174 branch_2 = conv2d_bn(branch_2, 96, 3) 

175 branch_2 = conv2d_bn(branch_2, 96, 3) 

176 branch_pool = layers.AveragePooling2D(3, strides=1, padding="same")(x) 

177 branch_pool = conv2d_bn(branch_pool, 64, 1) 

178 branches = [branch_0, branch_1, branch_2, branch_pool] 

179 channel_axis = 1 if backend.image_data_format() == "channels_first" else 3 

180 x = layers.Concatenate(axis=channel_axis, name="mixed_5b")(branches) 

181 

182 # 10x block35 (Inception-ResNet-A block): 35 x 35 x 320 

183 for block_idx in range(1, 11): 

184 x = inception_resnet_block( 

185 x, scale=0.17, block_type="block35", block_idx=block_idx 

186 ) 

187 

188 # Mixed 6a (Reduction-A block): 17 x 17 x 1088 

189 branch_0 = conv2d_bn(x, 384, 3, strides=2, padding="valid") 

190 branch_1 = conv2d_bn(x, 256, 1) 

191 branch_1 = conv2d_bn(branch_1, 256, 3) 

192 branch_1 = conv2d_bn(branch_1, 384, 3, strides=2, padding="valid") 

193 branch_pool = layers.MaxPooling2D(3, strides=2, padding="valid")(x) 

194 branches = [branch_0, branch_1, branch_pool] 

195 x = layers.Concatenate(axis=channel_axis, name="mixed_6a")(branches) 

196 

197 # 20x block17 (Inception-ResNet-B block): 17 x 17 x 1088 

198 for block_idx in range(1, 21): 

199 x = inception_resnet_block( 

200 x, scale=0.1, block_type="block17", block_idx=block_idx 

201 ) 

202 

203 # Mixed 7a (Reduction-B block): 8 x 8 x 2080 

204 branch_0 = conv2d_bn(x, 256, 1) 

205 branch_0 = conv2d_bn(branch_0, 384, 3, strides=2, padding="valid") 

206 branch_1 = conv2d_bn(x, 256, 1) 

207 branch_1 = conv2d_bn(branch_1, 288, 3, strides=2, padding="valid") 

208 branch_2 = conv2d_bn(x, 256, 1) 

209 branch_2 = conv2d_bn(branch_2, 288, 3) 

210 branch_2 = conv2d_bn(branch_2, 320, 3, strides=2, padding="valid") 

211 branch_pool = layers.MaxPooling2D(3, strides=2, padding="valid")(x) 

212 branches = [branch_0, branch_1, branch_2, branch_pool] 

213 x = layers.Concatenate(axis=channel_axis, name="mixed_7a")(branches) 

214 

215 # 10x block8 (Inception-ResNet-C block): 8 x 8 x 2080 

216 for block_idx in range(1, 10): 

217 x = inception_resnet_block( 

218 x, scale=0.2, block_type="block8", block_idx=block_idx 

219 ) 

220 x = inception_resnet_block( 

221 x, scale=1.0, activation=None, block_type="block8", block_idx=10 

222 ) 

223 

224 # Final convolution block: 8 x 8 x 1536 

225 x = conv2d_bn(x, 1536, 1, name="conv_7b") 

226 

227 if include_top: 

228 # Classification block 

229 x = layers.GlobalAveragePooling2D(name="avg_pool")(x) 

230 imagenet_utils.validate_activation(classifier_activation, weights) 

231 x = layers.Dense( 

232 classes, activation=classifier_activation, name="predictions" 

233 )(x) 

234 else: 

235 if pooling == "avg": 

236 x = layers.GlobalAveragePooling2D()(x) 

237 elif pooling == "max": 

238 x = layers.GlobalMaxPooling2D()(x) 

239 

240 # Ensure that the model takes into account 

241 # any potential predecessors of `input_tensor`. 

242 if input_tensor is not None: 

243 inputs = layer_utils.get_source_inputs(input_tensor) 

244 else: 

245 inputs = img_input 

246 

247 # Create model. 

248 model = training.Model(inputs, x, name="inception_resnet_v2") 

249 

250 # Load weights. 

251 if weights == "imagenet": 

252 if include_top: 

253 fname = "inception_resnet_v2_weights_tf_dim_ordering_tf_kernels.h5" 

254 weights_path = data_utils.get_file( 

255 fname, 

256 BASE_WEIGHT_URL + fname, 

257 cache_subdir="models", 

258 file_hash="e693bd0210a403b3192acc6073ad2e96", 

259 ) 

260 else: 

261 fname = ( 

262 "inception_resnet_v2_weights_" 

263 "tf_dim_ordering_tf_kernels_notop.h5" 

264 ) 

265 weights_path = data_utils.get_file( 

266 fname, 

267 BASE_WEIGHT_URL + fname, 

268 cache_subdir="models", 

269 file_hash="d19885ff4a710c122648d3b5c3b684e4", 

270 ) 

271 model.load_weights(weights_path) 

272 elif weights is not None: 

273 model.load_weights(weights) 

274 

275 return model 

276 

277 

278def conv2d_bn( 

279 x, 

280 filters, 

281 kernel_size, 

282 strides=1, 

283 padding="same", 

284 activation="relu", 

285 use_bias=False, 

286 name=None, 

287): 

288 """Utility function to apply conv + BN. 

289 

290 Args: 

291 x: input tensor. 

292 filters: filters in `Conv2D`. 

293 kernel_size: kernel size as in `Conv2D`. 

294 strides: strides in `Conv2D`. 

295 padding: padding mode in `Conv2D`. 

296 activation: activation in `Conv2D`. 

297 use_bias: whether to use a bias in `Conv2D`. 

298 name: name of the ops; will become `name + '_ac'` for the activation 

299 and `name + '_bn'` for the batch norm layer. 

300 

301 Returns: 

302 Output tensor after applying `Conv2D` and `BatchNormalization`. 

303 """ 

304 x = layers.Conv2D( 

305 filters, 

306 kernel_size, 

307 strides=strides, 

308 padding=padding, 

309 use_bias=use_bias, 

310 name=name, 

311 )(x) 

312 if not use_bias: 

313 bn_axis = 1 if backend.image_data_format() == "channels_first" else 3 

314 bn_name = None if name is None else name + "_bn" 

315 x = layers.BatchNormalization(axis=bn_axis, scale=False, name=bn_name)( 

316 x 

317 ) 

318 if activation is not None: 

319 ac_name = None if name is None else name + "_ac" 

320 x = layers.Activation(activation, name=ac_name)(x) 

321 return x 

322 

323 

324@keras.utils.register_keras_serializable() 

325class CustomScaleLayer(keras_layers.Layer): 

326 def __init__(self, scale, **kwargs): 

327 super().__init__(**kwargs) 

328 self.scale = scale 

329 

330 def get_config(self): 

331 config = super().get_config() 

332 config.update({"scale": self.scale}) 

333 return config 

334 

335 def call(self, inputs): 

336 return inputs[0] + inputs[1] * self.scale 

337 

338 

339def inception_resnet_block(x, scale, block_type, block_idx, activation="relu"): 

340 """Adds an Inception-ResNet block. 

341 

342 This function builds 3 types of Inception-ResNet blocks mentioned 

343 in the paper, controlled by the `block_type` argument (which is the 

344 block name used in the official TF-slim implementation): 

345 - Inception-ResNet-A: `block_type='block35'` 

346 - Inception-ResNet-B: `block_type='block17'` 

347 - Inception-ResNet-C: `block_type='block8'` 

348 

349 Args: 

350 x: input tensor. 

351 scale: scaling factor to scale the residuals (i.e., the output of passing 

352 `x` through an inception module) before adding them to the shortcut 

353 branch. Let `r` be the output from the residual branch, the output of 

354 this block will be `x + scale * r`. 

355 block_type: `'block35'`, `'block17'` or `'block8'`, determines the network 

356 structure in the residual branch. 

357 block_idx: an `int` used for generating layer names. The Inception-ResNet 

358 blocks are repeated many times in this network. We use `block_idx` to 

359 identify each of the repetitions. For example, the first 

360 Inception-ResNet-A block will have `block_type='block35', block_idx=0`, 

361 and the layer names will have a common prefix `'block35_0'`. 

362 activation: activation function to use at the end of the block (see 

363 [activations](../activations.md)). When `activation=None`, no activation 

364 is applied 

365 (i.e., "linear" activation: `a(x) = x`). 

366 

367 Returns: 

368 Output tensor for the block. 

369 

370 Raises: 

371 ValueError: if `block_type` is not one of `'block35'`, 

372 `'block17'` or `'block8'`. 

373 """ 

374 if block_type == "block35": 

375 branch_0 = conv2d_bn(x, 32, 1) 

376 branch_1 = conv2d_bn(x, 32, 1) 

377 branch_1 = conv2d_bn(branch_1, 32, 3) 

378 branch_2 = conv2d_bn(x, 32, 1) 

379 branch_2 = conv2d_bn(branch_2, 48, 3) 

380 branch_2 = conv2d_bn(branch_2, 64, 3) 

381 branches = [branch_0, branch_1, branch_2] 

382 elif block_type == "block17": 

383 branch_0 = conv2d_bn(x, 192, 1) 

384 branch_1 = conv2d_bn(x, 128, 1) 

385 branch_1 = conv2d_bn(branch_1, 160, [1, 7]) 

386 branch_1 = conv2d_bn(branch_1, 192, [7, 1]) 

387 branches = [branch_0, branch_1] 

388 elif block_type == "block8": 

389 branch_0 = conv2d_bn(x, 192, 1) 

390 branch_1 = conv2d_bn(x, 192, 1) 

391 branch_1 = conv2d_bn(branch_1, 224, [1, 3]) 

392 branch_1 = conv2d_bn(branch_1, 256, [3, 1]) 

393 branches = [branch_0, branch_1] 

394 else: 

395 raise ValueError( 

396 "Unknown Inception-ResNet block type. " 

397 'Expects "block35", "block17" or "block8", ' 

398 "but got: " + str(block_type) 

399 ) 

400 

401 block_name = block_type + "_" + str(block_idx) 

402 channel_axis = 1 if backend.image_data_format() == "channels_first" else 3 

403 mixed = layers.Concatenate(axis=channel_axis, name=block_name + "_mixed")( 

404 branches 

405 ) 

406 up = conv2d_bn( 

407 mixed, 

408 backend.int_shape(x)[channel_axis], 

409 1, 

410 activation=None, 

411 use_bias=True, 

412 name=block_name + "_conv", 

413 ) 

414 

415 x = CustomScaleLayer(scale)([x, up]) 

416 if activation is not None: 

417 x = layers.Activation(activation, name=block_name + "_ac")(x) 

418 return x 

419 

420 

421@keras_export("keras.applications.inception_resnet_v2.preprocess_input") 

422def preprocess_input(x, data_format=None): 

423 return imagenet_utils.preprocess_input( 

424 x, data_format=data_format, mode="tf" 

425 ) 

426 

427 

428@keras_export("keras.applications.inception_resnet_v2.decode_predictions") 

429def decode_predictions(preds, top=5): 

430 return imagenet_utils.decode_predictions(preds, top=top) 

431 

432 

433preprocess_input.__doc__ = imagenet_utils.PREPROCESS_INPUT_DOC.format( 

434 mode="", 

435 ret=imagenet_utils.PREPROCESS_INPUT_RET_DOC_TF, 

436 error=imagenet_utils.PREPROCESS_INPUT_ERROR_DOC, 

437) 

438decode_predictions.__doc__ = imagenet_utils.decode_predictions.__doc__ 

439