def auxiliary(x, n_classes, **metaparameters): """ Construct the auxiliary classier x : input to the auxiliary classifier n_classes: number of output classes """ x = AveragePooling2D((5, 5), strides=(3, 3))(x) x = Composable.Conv2D(x, 128, (1, 1), strides=(1, 1), padding='same', use_bias=False, **metaparameters) x = BatchNormalization()(x) x = Composable.ReLU(x) x = Flatten()(x) x = Composable.Dense(x, 1024, activation=Composable.ReLU, **metaparameters) x = Dropout(0.7)(x) output = Composable.Dense(x, n_classes, activation='softmax', **metaparameters) return output
def squeeze_excite_block(x, **metaparameters): """ Construct a Squeeze and Excite block x : input to the block ratio : amount of filter reduction during squeeze """ if 'ratio' in metaparameters: ratio = metaparameters['ratio'] else: ratio = SEResNeXt.ratio # Remember the input shortcut = x # Get the number of filters on the input filters = x.shape[-1] # Squeeze (dimensionality reduction) # Do global average pooling across the filters, which will the output a 1D vector x = GlobalAveragePooling2D()(x) # Reshape into 1x1 feature maps (1x1xC) x = Reshape((1, 1, filters))(x) # Reduce the number of filters (1x1xC/r) x = Composable.Dense(x, filters // ratio, activation='relu', use_bias=False, **metaparameters) # Excitation (dimensionality restoration) # Restore the number of filters (1x1xC) x = Composable.Dense(x, filters, activation='sigmoid', use_bias=False, **metaparameters) # Scale - multiply the squeeze/excitation output with the input (WxHxC) x = Multiply()([shortcut, x]) return x
def squeeze(x, **metaparameters): """ Construct a squeeze block x : input to the squeeze """ del metaparameters['activation'] shortcut = x n_channels = x.shape[-1] x = GlobalAveragePooling2D()(x) x = Composable.Dense(x, n_channels, activation=Composable.ReLU, **metaparameters) x = Composable.Dense(x, n_channels, activation=Composable.HS, **metaparameters) x = Reshape((1, 1, n_channels))(x) x = Multiply()([shortcut, x]) return x