def conv2d_block_as_layers(
        conv_filters: Optional[int],
        config: ModelConfig,
        kernel_size: Any = (1, 1),
        strides: Any = (1, 1),
        use_batch_norm: bool = True,
        use_bias: bool = False,
        activation: Any = None,
        depthwise: bool = False,
        name: Optional[str] = None) -> List[tf.keras.layers.Layer]:
    """A conv2d followed by batch norm and an activation."""
    batch_norm = common_modules.get_batch_norm(config.batch_norm)
    bn_momentum = config.bn_momentum
    bn_epsilon = config.bn_epsilon
    data_format = tf.keras.backend.image_data_format()
    weight_decay = config.weight_decay

    name = name or ''

    # Collect args based on what kind of conv2d block is desired
    init_kwargs = {
        'kernel_size': kernel_size,
        'strides': strides,
        'use_bias': use_bias,
        'padding': 'same',
        'name': name + '_conv2d',
        'kernel_regularizer': tf.keras.regularizers.l2(weight_decay),
        'bias_regularizer': tf.keras.regularizers.l2(weight_decay),
    }

    sequential_layers: List[tf.keras.layers.Layer] = []
    if depthwise:
        conv2d = tf.keras.layers.DepthwiseConv2D
        init_kwargs.update({'depthwise_initializer': CONV_KERNEL_INITIALIZER})
    else:
        conv2d = tf.keras.layers.Conv2D
        init_kwargs.update({
            'filters': conv_filters,
            'kernel_initializer': CONV_KERNEL_INITIALIZER
        })

    sequential_layers.append(conv2d(**init_kwargs))

    if use_batch_norm:
        bn_axis = 1 if data_format == 'channels_first' else -1
        sequential_layers.append(
            batch_norm(axis=bn_axis,
                       momentum=bn_momentum,
                       epsilon=bn_epsilon,
                       name=name + '_bn'))

    if activation is not None:
        sequential_layers.append(
            tf.keras.layers.Activation(activation, name=name + '_activation'))
    return sequential_layers
def groupconv2d_block(conv_filters: Optional[int],
                      config: ModelConfig,
                      kernel_size: Any = (1, 1),
                      strides: Any = (1, 1),
                      group_size: Optional[int] = None,
                      use_batch_norm: bool = True,
                      use_bias: bool = False,
                      activation: Any = None,
                      name: Optional[str] = None) -> tf.keras.layers.Layer:
    """2D group convolution with batchnorm and activation."""
    batch_norm = common_modules.get_batch_norm(config.batch_norm)
    bn_momentum = config.bn_momentum
    bn_epsilon = config.bn_epsilon
    data_format = tf.keras.backend.image_data_format()
    weight_decay = config.weight_decay
    if group_size is None:
        group_size = config.group_base_size

    name = name or ''
    # Compute the # of groups
    if conv_filters % group_size != 0:
        raise ValueError(
            f'Number of filters: {conv_filters} is not divisible by '
            f'size of the groups: {group_size}')
    groups = int(conv_filters / group_size)
    # Collect args based on what kind of groupconv2d block is desired
    init_kwargs = {
        'kernel_size': kernel_size,
        'strides': strides,
        'use_bias': use_bias,
        'padding': 'same',
        'name': name + '_groupconv2d',
        'kernel_regularizer': tf.keras.regularizers.l2(weight_decay),
        'bias_regularizer': tf.keras.regularizers.l2(weight_decay),
        'filters': conv_filters,
        'groups': groups,
        'batch_norm_layer': batch_norm if use_batch_norm else None,
        'bn_epsilon': bn_epsilon,
        'bn_momentum': bn_momentum,
        'activation': activation,
        'data_format': data_format,
    }
    return custom_layers.GroupConv2D(**init_kwargs)
Example #3
0
def build_batch_norm(is_training_bn: bool,
                     beta_initializer: Text = 'zeros',
                     gamma_initializer: Text = 'ones',
                     data_format: Text = 'channels_last',
                     momentum: float = 0.99,
                     epsilon: float = 1e-3,
                     strategy: Optional[Text] = None,
                     name: Text = 'tpu_batch_normalization'):
  """Builds a batch normalization layer.

  Args:
    is_training_bn: `bool` for whether the model is training.
    beta_initializer: `str`, beta initializer.
    gamma_initializer: `str`, gamma initializer.
    data_format: `str` either "channels_first" for `[batch, channels, height,
      width]` or "channels_last for `[batch, height, width, channels]`.
    momentum: `float`, momentume of batch norm.
    epsilon: `float`, small value for numerical stability.
    strategy: `str`, whether to use tpu, gpus or other version of batch norm.
    name: the name of the batch normalization layer

  Returns:
    A normalized `Tensor` with the same `data_format`.
  """
  axis = 1 if data_format == 'channels_first' else -1

  if is_training_bn:
    batch_norm_class = common_modules.get_batch_norm(strategy)
  else:
    batch_norm_class = tf.keras.layers.BatchNormalization

  bn_layer = batch_norm_class(
      axis=axis,
      momentum=momentum,
      epsilon=epsilon,
      center=True,
      scale=True,
      beta_initializer=beta_initializer,
      gamma_initializer=gamma_initializer,
      name=name)

  return bn_layer