def ChannelSE(reduction=16, **kwargs): """ Squeeze and Excitation block, reimplementation inspired by https://github.com/Cadene/pretrained-models.pytorch/blob/master/pretrainedmodels/models/senet.py Args: reduction: channels squeeze factor """ backend, layers, models, keras_utils = get_submodules_from_kwargs(kwargs) channels_axis = 3 if backend.image_data_format() == 'channels_last' else 1 def layer(input_tensor): # get number of channels/filters channels = backend.int_shape(input_tensor)[channels_axis] x = input_tensor # squeeze and excitation block in PyTorch style with x = layers.GlobalAveragePooling2D()(x) x = layers.Lambda(expand_dims, arguments={'channels_axis': channels_axis})(x) x = layers.Conv2D(channels // reduction, (1, 1), kernel_initializer='he_uniform')(x) x = layers.Activation('relu')(x) x = layers.Conv2D(channels, (1, 1), kernel_initializer='he_uniform')(x) x = layers.Activation('sigmoid')(x) # apply attention x = layers.Multiply()([input_tensor, x]) return x return layer
def GroupConv2D(filters, kernel_size, strides=(1, 1), groups=32, kernel_initializer='he_uniform', use_bias=True, activation='linear', padding='valid', **kwargs): """ Grouped Convolution Layer implemented as a Slice, Conv2D and Concatenate layers. Split filters to groups, apply Conv2D and concatenate back. Args: filters: Integer, the dimensionality of the output space (i.e. the number of output filters in the convolution). kernel_size: An integer or tuple/list of a single integer, specifying the length of the 1D convolution window. strides: An integer or tuple/list of a single integer, specifying the stride length of the convolution. groups: Integer, number of groups to split input filters to. kernel_initializer: Regularizer function applied to the kernel weights matrix. use_bias: Boolean, whether the layer uses a bias vector. activation: Activation function to use (see activations). If you don't specify anything, no activation is applied (ie. "linear" activation: a(x) = x). padding: one of "valid" or "same" (case-insensitive). Input shape: 4D tensor with shape: (batch, rows, cols, channels) if data_format is "channels_last". Output shape: 4D tensor with shape: (batch, new_rows, new_cols, filters) if data_format is "channels_last". rows and cols values might have changed due to padding. """ backend, layers, models, keras_utils = get_submodules_from_kwargs(kwargs) slice_axis = 3 if backend.image_data_format() == 'channels_last' else 1 def layer(input_tensor): inp_ch = int(backend.int_shape(input_tensor)[-1] // groups) # input grouped channels out_ch = int(filters // groups) # output grouped channels blocks = [] for c in range(groups): slice_arguments = { 'start': c * inp_ch, 'stop': (c + 1) * inp_ch, 'axis': slice_axis, } x = layers.Lambda(slice_tensor, arguments=slice_arguments)(input_tensor) x = layers.Conv2D(out_ch, kernel_size, strides=strides, kernel_initializer=kernel_initializer, use_bias=use_bias, activation=activation, padding=padding)(x) blocks.append(x) x = layers.Concatenate(axis=slice_axis)(blocks) return x return layer
def SENet( model_params, input_tensor=None, input_shape=None, include_top=True, classes=1000, weights='imagenet', **kwargs ): """Instantiates the ResNet, SEResNet architecture. Optionally loads weights pre-trained on ImageNet. Note that the data format convention used by the model is the one specified in your Keras config at `~/.keras/keras.json`. Args: include_top: whether to include the fully-connected layer at the top of the network. weights: one of `None` (random initialization), 'imagenet' (pre-training on ImageNet), or the path to the weights file to be loaded. input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model. input_shape: optional shape tuple, only to be specified if `include_top` is False (otherwise the input shape has to be `(224, 224, 3)` (with `channels_last` data format) or `(3, 224, 224)` (with `channels_first` data format). It should have exactly 3 inputs channels. classes: optional number of classes to classify images into, only to be specified if `include_top` is True, and if no `weights` argument is specified. Returns: A Keras model instance. Raises: ValueError: in case of invalid argument for `weights`, or invalid input shape. """ global backend, layers, models, keras_utils backend, layers, models, keras_utils = get_submodules_from_kwargs(kwargs) residual_block = model_params.residual_block init_filters = model_params.init_filters bn_params = get_bn_params() # define input if input_tensor is None: input = layers.Input(shape=input_shape, name='input') else: if not backend.is_keras_tensor(input_tensor): input = layers.Input(tensor=input_tensor, shape=input_shape) else: input = input_tensor x = input if model_params.input_3x3: x = layers.ZeroPadding2D(1)(x) x = layers.Conv2D(init_filters, (3, 3), strides=2, use_bias=False, kernel_initializer='he_uniform')(x) x = layers.BatchNormalization(**bn_params)(x) x = layers.Activation('relu')(x) x = layers.ZeroPadding2D(1)(x) x = layers.Conv2D(init_filters, (3, 3), use_bias=False, kernel_initializer='he_uniform')(x) x = layers.BatchNormalization(**bn_params)(x) x = layers.Activation('relu')(x) x = layers.ZeroPadding2D(1)(x) x = layers.Conv2D(init_filters * 2, (3, 3), use_bias=False, kernel_initializer='he_uniform')(x) x = layers.BatchNormalization(**bn_params)(x) x = layers.Activation('relu')(x) else: x = layers.ZeroPadding2D(3)(x) x = layers.Conv2D(init_filters, (7, 7), strides=2, use_bias=False, kernel_initializer='he_uniform')(x) x = layers.BatchNormalization(**bn_params)(x) x = layers.Activation('relu')(x) x = layers.ZeroPadding2D(1)(x) x = layers.MaxPooling2D((3, 3), strides=2)(x) # body of resnet filters = model_params.init_filters * 2 for i, stage in enumerate(model_params.repetitions): # increase number of filters with each stage filters *= 2 for j in range(stage): # decrease spatial dimensions for each stage (except first, because we have maxpool before) if i == 0 and j == 0: x = residual_block(filters, reduction=model_params.reduction, strides=1, groups=model_params.groups, is_first=True, **kwargs)(x) elif i != 0 and j == 0: x = residual_block(filters, reduction=model_params.reduction, strides=2, groups=model_params.groups, **kwargs)(x) else: x = residual_block(filters, reduction=model_params.reduction, strides=1, groups=model_params.groups, **kwargs)(x) if include_top: x = layers.GlobalAveragePooling2D()(x) if model_params.dropout is not None: x = layers.Dropout(model_params.dropout)(x) x = layers.Dense(classes)(x) x = layers.Activation('softmax', name='output')(x) # Ensure that the model takes into account any potential predecessors of `input_tensor`. if input_tensor is not None: inputs = keras_utils.get_source_inputs(input_tensor) else: inputs = input model = models.Model(inputs, x) if weights: if type(weights) == str and os.path.exists(weights): model.load_weights(weights) else: load_model_weights(model, model_params.model_name, weights, classes, include_top, **kwargs) return model
def ResNeXt( model_params, include_top=True, input_tensor=None, input_shape=None, classes=1000, weights='imagenet', **kwargs): """Instantiates the ResNet, SEResNet architecture. Optionally loads weights pre-trained on ImageNet. Note that the data format convention used by the model is the one specified in your Keras config at `~/.keras/keras.json`. Args: include_top: whether to include the fully-connected layer at the top of the network. weights: one of `None` (random initialization), 'imagenet' (pre-training on ImageNet), or the path to the weights file to be loaded. input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model. input_shape: optional shape tuple, only to be specified if `include_top` is False (otherwise the input shape has to be `(224, 224, 3)` (with `channels_last` data format) or `(3, 224, 224)` (with `channels_first` data format). It should have exactly 3 inputs channels. classes: optional number of classes to classify images into, only to be specified if `include_top` is True, and if no `weights` argument is specified. Returns: A Keras model instance. Raises: ValueError: in case of invalid argument for `weights`, or invalid input shape. """ global backend, layers, models, keras_utils backend, layers, models, keras_utils = get_submodules_from_kwargs(kwargs) if input_tensor is None: img_input = layers.Input(shape=input_shape, name='data') else: if not backend.is_keras_tensor(input_tensor): img_input = layers.Input(tensor=input_tensor, shape=input_shape) else: img_input = input_tensor # get parameters for model layers no_scale_bn_params = get_bn_params(scale=False) bn_params = get_bn_params() conv_params = get_conv_params() # resnext bottom x = layers.BatchNormalization(name='bn_data', **no_scale_bn_params)(img_input) x = layers.ZeroPadding2D(padding=(3, 3))(x) x = layers.Conv2D(64, (7, 7), strides=(2, 2), name='conv0', **conv_params)(x) x = layers.BatchNormalization(name='bn0', **bn_params)(x) x = layers.Activation('relu', name='relu0')(x) x = layers.ZeroPadding2D(padding=(1, 1))(x) x = layers.MaxPooling2D((3, 3), strides=(2, 2), padding='valid', name='pooling0')(x) # resnext body init_filters = 128 for stage, rep in enumerate(model_params.repetitions): for block in range(rep): filters = init_filters * (2 ** stage) # first block of first stage without strides because we have maxpooling before if stage == 0 and block == 0: x = conv_block(filters, stage, block, strides=(1, 1), **kwargs)(x) elif block == 0: x = conv_block(filters, stage, block, strides=(2, 2), **kwargs)(x) else: x = identity_block(filters, stage, block, **kwargs)(x) # resnext top if include_top: x = layers.GlobalAveragePooling2D(name='pool1')(x) x = layers.Dense(classes, name='fc1')(x) x = layers.Activation('softmax', name='softmax')(x) # Ensure that the model takes into account any potential predecessors of `input_tensor`. if input_tensor is not None: inputs = keras_utils.get_source_inputs(input_tensor) else: inputs = img_input # Create model model = models.Model(inputs, x) if weights: if type(weights) == str and os.path.exists(weights): model.load_weights(weights) else: load_model_weights(model, model_params.model_name, weights, classes, include_top, **kwargs) return model
def VGG19(include_top=True, weights='imagenet', input_tensor=None, input_shape=None, pooling=None, classes=1000, dropout: float = 0, **kwargs): print('# DROPOUT:', dropout > 0) """Instantiates the VGG19 architecture. Optionally loads weights pre-trained on ImageNet. Note that the data format convention used by the model is the one specified in your Keras config at `~/.keras/keras.json`. # Arguments include_top: whether to include the 3 fully-connected layers at the top of the network. weights: one of `None` (random initialization), 'imagenet' (pre-training on ImageNet), or the path to the weights file to be loaded. input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model. input_shape: optional shape tuple, only to be specified if `include_top` is False (otherwise the input shape has to be `(224, 224, 3)` (with `channels_last` data format) or `(3, 224, 224)` (with `channels_first` data format). It should have exactly 3 inputs channels, and width and height should be no smaller than 32. E.g. `(200, 200, 3)` would be one valid value. pooling: Optional pooling mode for feature extraction when `include_top` is `False`. - `None` means that the output of the model will be the 4D tensor output of the last convolutional block. - `avg` means that global average pooling will be applied to the output of the last convolutional block, and thus the output of the model will be a 2D tensor. - `max` means that global max pooling will be applied. classes: optional number of classes to classify images into, only to be specified if `include_top` is True, and if no `weights` argument is specified. # Returns A Keras model instance. # Raises ValueError: in case of invalid argument for `weights`, or invalid input shape. """ backend, layers, models, keras_utils = get_submodules_from_kwargs(kwargs) if not (weights in {'imagenet', None} or os.path.exists(weights)): raise ValueError('The `weights` argument should be either ' '`None` (random initialization), `imagenet` ' '(pre-training on ImageNet), ' 'or the path to the weights file to be loaded.') if weights == 'imagenet' and include_top and classes != 1000: raise ValueError( 'If using `weights` as `"imagenet"` with `include_top`' ' as true, `classes` should be 1000') # Determine proper input shape input_shape = _obtain_input_shape(input_shape, default_size=224, min_size=32, data_format=backend.image_data_format(), require_flatten=include_top, weights=weights) if input_tensor is None: img_input = layers.Input(shape=input_shape) else: if not backend.is_keras_tensor(input_tensor): img_input = layers.Input(tensor=input_tensor, shape=input_shape) else: img_input = input_tensor # Block 1 x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) x = layers.Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x) x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) x = add_dropout(x, dropout) # Block 2 x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) x = layers.Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x) x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) x = add_dropout(x, dropout) # Block 3 x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x) x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x) x = layers.Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv4')(x) x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) x = add_dropout(x, dropout) # Block 4 x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv4')(x) x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) x = add_dropout(x, dropout) # Block 5 x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x) x = layers.Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv4')(x) x = layers.MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) x = add_dropout(x, dropout) if include_top: # Classification block x = layers.Flatten(name='flatten')(x) x = layers.Dense(4096, activation='relu', name='fc1')(x) x = layers.Dense(4096, activation='relu', name='fc2')(x) x = layers.Dense(classes, activation='softmax', name='predictions')(x) else: if pooling == 'avg': x = layers.GlobalAveragePooling2D()(x) elif pooling == 'max': x = layers.GlobalMaxPooling2D()(x) # Ensure that the model takes into account # any potential predecessors of `input_tensor`. if input_tensor is not None: inputs = keras_utils.get_source_inputs(input_tensor) else: inputs = img_input # Create model. model = models.Model(inputs, x, name='vgg19') # Load weights. if weights == 'imagenet': if include_top: weights_path = keras_utils.get_file( 'vgg19_weights_tf_dim_ordering_tf_kernels.h5', WEIGHTS_PATH, cache_subdir='models', file_hash='cbe5617147190e668d6c5d5026f83318') else: weights_path = keras_utils.get_file( 'vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5', WEIGHTS_PATH_NO_TOP, cache_subdir='models', file_hash='253f8cb515780f3b799900260a226db6') model.load_weights(weights_path) if backend.backend() == 'theano': keras_utils.convert_all_kernels_in_model(model) elif weights is not None: model.load_weights(weights) return model