2 """Se Inception-ResNet V2 model for Keras. 4 Model naming and structure follows TF-slim implementation (which has some additional 5 layers and different number of filters from the original arXiv paper): 6 https://github.com/tensorflow/models/blob/master/slim/nets/inception_resnet_v2.py 7 Pre-trained ImageNet weights are also converted from TF-slim, which can be found in: 8 https://github.com/tensorflow/models/tree/master/slim#pre-trained-models 10 Original code from Keras applications 13 - [Inception-v4, Inception-ResNet and the Impact of 14 Residual Connections on Learning](https://arxiv.org/abs/1602.07261) 16 from __future__
import print_function
17 from __future__
import absolute_import
21 from keras.models
import Model
22 from keras.layers
import Activation
23 from keras.layers
import AveragePooling2D
24 from keras.layers
import BatchNormalization
25 from keras.layers
import Concatenate
26 from keras.layers
import Conv2D
27 from keras.layers
import Dense
28 from keras.layers
import GlobalAveragePooling2D
29 from keras.layers
import GlobalMaxPooling2D
30 from keras.layers
import Input
31 from keras.layers
import Lambda
32 from keras.layers
import MaxPooling2D
33 from keras.utils.data_utils
import get_file
34 from keras.engine.topology
import get_source_inputs
35 from keras.applications
import imagenet_utils
36 from keras.applications.imagenet_utils
import _obtain_input_shape
37 from keras.applications.imagenet_utils
import decode_predictions
38 from keras
import backend
as K
40 from se
import squeeze_excite_block
44 """Preprocesses a numpy array encoding a batch of images. 46 x: a 4D numpy array consists of RGB values within [0, 255]. 61 """Utility function to apply conv + BN. 64 filters: filters in `Conv2D`. 65 kernel_size: kernel size as in `Conv2D`. 66 padding: padding mode in `Conv2D`. 67 activation: activation in `Conv2D`. 68 strides: strides in `Conv2D`. 69 name: name of the ops; will become `name + '_ac'` for the activation 70 and `name + '_bn'` for the batch norm layer. 72 Output tensor after applying `Conv2D` and `BatchNormalization`. 81 bn_axis = 1
if K.image_data_format() ==
'channels_first' else 3
82 bn_name =
None if name
is None else name +
'_bn' 83 x = BatchNormalization(axis=bn_axis, scale=
False, name=bn_name)(x)
84 if activation
is not None:
85 ac_name =
None if name
is None else name +
'_ac' 86 x = Activation(activation, name=ac_name)(x)
91 """Adds a Inception-ResNet block with Squeeze and Excitation block at the end. 92 This function builds 3 types of Inception-ResNet blocks mentioned 93 in the paper, controlled by the `block_type` argument (which is the 94 block name used in the official TF-slim implementation): 95 - Inception-ResNet-A: `block_type='block35'` 96 - Inception-ResNet-B: `block_type='block17'` 97 - Inception-ResNet-C: `block_type='block8'` 100 scale: scaling factor to scale the residuals (i.e., the output of 101 passing `x` through an inception module) before adding them 102 to the shortcut branch. Let `r` be the output from the residual branch, 103 the output of this block will be `x + scale * r`. 104 block_type: `'block35'`, `'block17'` or `'block8'`, determines 105 the network structure in the residual branch. 106 block_idx: an `int` used for generating layer names. The Inception-ResNet blocks 107 are repeated many times in this network. We use `block_idx` to identify 108 each of the repetitions. For example, the first Inception-ResNet-A block 109 will have `block_type='block35', block_idx=0`, ane the layer names will have 110 a common prefix `'block35_0'`. 111 activation: activation function to use at the end of the block 112 (see [activations](../activations.md)). 113 When `activation=None`, no activation is applied 114 (i.e., "linear" activation: `a(x) = x`). 116 Output tensor for the block. 118 ValueError: if `block_type` is not one of `'block35'`, 119 `'block17'` or `'block8'`. 121 if block_type ==
'block35':
128 branches = [branch_0, branch_1, branch_2]
129 elif block_type ==
'block17':
132 branch_1 =
conv2d_bn(branch_1, 160, [1, 7])
133 branch_1 =
conv2d_bn(branch_1, 192, [7, 1])
134 branches = [branch_0, branch_1]
135 elif block_type ==
'block8':
138 branch_1 =
conv2d_bn(branch_1, 224, [1, 3])
139 branch_1 =
conv2d_bn(branch_1, 256, [3, 1])
140 branches = [branch_0, branch_1]
142 raise ValueError(
'Unknown Inception-ResNet block type. ' 143 'Expects "block35", "block17" or "block8", ' 144 'but got: ' +
str(block_type))
146 block_name = block_type +
'_' +
str(block_idx)
147 channel_axis = 1
if K.image_data_format() ==
'channels_first' else 3
148 mixed = Concatenate(axis=channel_axis, name=block_name +
'_mixed')(branches)
150 K.int_shape(x)[channel_axis],
154 name=block_name +
'_conv')
156 x = Lambda(
lambda inputs, scale: inputs[0] + inputs[1] * scale,
157 output_shape=K.int_shape(x)[1:],
158 arguments={
'scale': scale},
159 name=block_name)([x, up])
160 if activation
is not None:
161 x = Activation(activation, name=block_name +
'_ac')(x)
174 """Instantiates the SE-Inception-ResNet v2 architecture. 175 Optionally loads weights pre-trained on ImageNet. 176 Note that when using TensorFlow, for best performance you should 177 set `"image_data_format": "channels_last"` in your Keras config 178 at `~/.keras/keras.json`. 179 The model and the weights are compatible with both TensorFlow and Theano 180 backends (but not CNTK). The data format convention used by the model is 181 the one specified in your Keras config file. 182 Note that the default input image size for this model is 299x299, instead 183 of 224x224 as in the VGG16 and ResNet models. Also, the input preprocessing 184 function is different (i.e., do not use `imagenet_utils.preprocess_input()` 185 with this model. Use `preprocess_input()` defined in this module instead). 187 include_top: whether to include the fully-connected 188 layer at the top of the network. 189 weights: one of `None` (random initialization) 190 or `'imagenet'` (pre-training on ImageNet). 191 input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 192 to use as image input for the model. 193 input_shape: optional shape tuple, only to be specified 194 if `include_top` is `False` (otherwise the input shape 195 has to be `(299, 299, 3)` (with `'channels_last'` data format) 196 or `(3, 299, 299)` (with `'channels_first'` data format). 197 It should have exactly 3 inputs channels, 198 and width and height should be no smaller than 139. 199 E.g. `(150, 150, 3)` would be one valid value. 200 pooling: Optional pooling mode for feature extraction 201 when `include_top` is `False`. 202 - `None` means that the output of the model will be 203 the 4D tensor output of the last convolutional layer. 204 - `'avg'` means that global average pooling 205 will be applied to the output of the 206 last convolutional layer, and thus 207 the output of the model will be a 2D tensor. 208 - `'max'` means that global max pooling will be applied. 209 classes: optional number of classes to classify images 210 into, only to be specified if `include_top` is `True`, and 211 if no `weights` argument is specified. 213 A Keras `Model` instance. 215 ValueError: in case of invalid argument for `weights`, 216 or invalid input shape. 217 RuntimeError: If attempting to run this model with an unsupported backend. 219 if K.backend()
in {
'cntk'}:
220 raise RuntimeError(K.backend() +
' backend is currently unsupported for this model.')
222 if weights
not in {
'imagenet',
None}:
223 raise ValueError(
'The `weights` argument should be either ' 224 '`None` (random initialization) or `imagenet` ' 225 '(pre-training on ImageNet).')
227 if weights ==
'imagenet' and include_top
and classes != 1000:
228 raise ValueError(
'If using `weights` as imagenet with `include_top`' 229 ' as true, `classes` should be 1000')
236 data_format=K.image_data_format(),
237 require_flatten=
False,
240 if input_tensor
is None:
241 img_input = Input(shape=input_shape)
243 if not K.is_keras_tensor(input_tensor):
244 img_input = Input(tensor=input_tensor, shape=input_shape)
246 img_input = input_tensor
249 x =
conv2d_bn(img_input, 32, 3, strides=2, padding=
'valid')
252 x = MaxPooling2D(3, strides=2)(x)
254 x =
conv2d_bn(x, 192, 3, padding=
'valid')
255 x = MaxPooling2D(3, strides=2)(x)
264 branch_pool = AveragePooling2D(3, strides=1, padding=
'same')(x)
265 branch_pool =
conv2d_bn(branch_pool, 64, 1)
266 branches = [branch_0, branch_1, branch_2, branch_pool]
267 channel_axis = 1
if K.image_data_format() ==
'channels_first' else 3
268 x = Concatenate(axis=channel_axis, name=
'mixed_5b')(branches)
274 for block_idx
in range(1, 11):
277 block_type=
'block35',
281 branch_0 =
conv2d_bn(x, 384, 3, strides=2, padding=
'valid')
284 branch_1 =
conv2d_bn(branch_1, 384, 3, strides=2, padding=
'valid')
285 branch_pool = MaxPooling2D(3, strides=2, padding=
'valid')(x)
286 branches = [branch_0, branch_1, branch_pool]
287 x = Concatenate(axis=channel_axis, name=
'mixed_6a')(branches)
293 for block_idx
in range(1, 21):
296 block_type=
'block17',
301 branch_0 =
conv2d_bn(branch_0, 384, 3, strides=2, padding=
'valid')
303 branch_1 =
conv2d_bn(branch_1, 288, 3, strides=2, padding=
'valid')
306 branch_2 =
conv2d_bn(branch_2, 320, 3, strides=2, padding=
'valid')
307 branch_pool = MaxPooling2D(3, strides=2, padding=
'valid')(x)
308 branches = [branch_0, branch_1, branch_2, branch_pool]
309 x = Concatenate(axis=channel_axis, name=
'mixed_7a')(branches)
315 for block_idx
in range(1, 10):
330 x =
conv2d_bn(x, 1536, 1, name=
'conv_7b')
334 x = GlobalAveragePooling2D(name=
'avg_pool')(x)
335 x = Dense(classes, activation=
'softmax', name=
'predictions')(x)
338 x = GlobalAveragePooling2D()(x)
339 elif pooling ==
'max':
340 x = GlobalMaxPooling2D()(x)
344 if input_tensor
is not None:
345 inputs = get_source_inputs(input_tensor)
350 model = Model(inputs, x, name=
'se_inception_resnet_v2')
def squeeze_excite_block(input, ratio=16)
def _obtain_input_shape(input_shape, default_size, min_size, data_format, require_flatten, weights=None)
def preprocess_input(x, data_format=None, mode='caffe')
def SEInceptionResNetV2(include_top=True, weights=None, input_tensor=None, input_shape=None, pooling=None, classes=1000)
def inception_resnet_block(x, scale, block_type, block_idx, activation='relu')
def conv2d_bn(x, filters, kernel_size, strides=1, padding='same', activation='relu', use_bias=False, name=None)