Exemple #1
0
def _depthwise_conv_with_fixed_kernel(
    params,
    filters_or_mask,
    kernel_size,
    strides = (1, 1),
    activation = None):
  """Build a depthwise conv, batch norm, and optional activation."""
  result = []
  if isinstance(filters_or_mask, int):
    result.append(
        layers.DepthwiseConv2D(
            kernel_size=kernel_size,
            depthwise_initializer=params['depthwise_initializer'],
            depthwise_regularizer=params['kernel_regularizer'],
            strides=strides))
  else:
    result.append(
        layers.MaskedDepthwiseConv2D(
            kernel_size=kernel_size,
            mask=filters_or_mask,
            depthwise_initializer=params['depthwise_initializer'],
            depthwise_regularizer=params['kernel_regularizer'],
            strides=strides))

  result.append(_batch_norm(params, filters_or_mask))
  if activation is not None:
    result.append(activation)
  return layers.Sequential(result)
Exemple #2
0
def _build_model(params,
                 model_spec):
  """Translate a ConvTowerSpec namedtuple into a rematlib Layer."""
  input_filters = schema.OneOf([3], basic_specs.FILTERS_TAG)
  layer = None
  result = []
  endpoints = []
  for block_spec in model_spec.blocks:
    for layer_spec in block_spec.layers:
      if isinstance(layer_spec, mobile_search_space_v3.DetectionEndpointSpec):
        if layer is None:
          raise ValueError(
              'The first layer of the network cannot be a detection endpoint.')
        endpoints.append(layer)
      else:
        output_filters = block_spec.filters
        if isinstance(output_filters, int):
          output_filters = schema.OneOf(
              [output_filters], basic_specs.FILTERS_TAG)

        layer = _build_layer(
            params, layer_spec, input_filters, output_filters,
            model_spec.filters_base)
        input_filters = output_filters
        result.append(layer)

  result.append(_make_head(params))

  # Build the model
  model = layers.Sequential(result, aux_outputs=endpoints)
  return model
Exemple #3
0
def _conv_with_fixed_kernel(params,
                            input_filters_or_mask,
                            output_filters_or_mask,
                            kernel_size,
                            strides = (1, 1),
                            activation = None,
                            use_batch_norm = True):
  """Construct a Conv2D, followed by a batch norm and optional activation."""
  result = []
  if (isinstance(input_filters_or_mask, int) and
      isinstance(output_filters_or_mask, int)):
    result.append(
        layers.Conv2D(
            filters=output_filters_or_mask,
            kernel_size=kernel_size,
            kernel_initializer=params['kernel_initializer'],
            kernel_regularizer=params['kernel_regularizer'],
            use_bias=not use_batch_norm,
            strides=strides))
  else:
    result.append(
        layers.MaskedConv2D(
            input_mask=_to_filters_mask(input_filters_or_mask),
            output_mask=_to_filters_mask(output_filters_or_mask),
            kernel_size=kernel_size,
            kernel_initializer=params['kernel_initializer'],
            kernel_regularizer=params['kernel_regularizer'],
            use_bias=not use_batch_norm,
            strides=strides))

  if use_batch_norm:
    result.append(_batch_norm(params, output_filters_or_mask))
  if activation is not None:
    result.append(activation)
  return layers.Sequential(result)
Exemple #4
0
def _make_head(params):
  """Construct a classification model head."""
  result = []
  if params['dropout_rate'] > 0:
    result.append(layers.Dropout(params['dropout_rate']))
  result.append(
      layers.Conv2D(filters=params['num_classes'],
                    kernel_size=(1, 1),
                    kernel_initializer=params['dense_initializer'],
                    # kernel_regularizer is not used for the final dense layer:
                    kernel_regularizer=None,
                    use_bias=True))
  result.append(layers.GlobalAveragePool(keepdims=False))
  return layers.Sequential(result)
Exemple #5
0
def _build_separable_conv(params, layer_spec, input_filters, output_filters):
    return layers.Sequential([
        _depthwise_conv(
            params,
            filters_or_mask=_oneof_filters_to_int_or_mask(input_filters),
            kernel_size=layer_spec.kernel_size,
            strides=layer_spec.strides,
            activation=_get_activation(layer_spec.activation)),
        _conv(
            params,
            input_filters_or_mask=_oneof_filters_to_int_or_mask(input_filters),
            output_filters_or_mask=_oneof_filters_to_int_or_mask(
                output_filters),
            kernel_size=(1, 1),
            activation=None),
    ])
Exemple #6
0
def _build_depthwise_bottleneck(
    params,
    layer_spec,
    input_filters,
    output_filters,
    filters_base):
  """Construct a bottleneck layer with a depthwise conv in the middle."""
  input_filters_or_mask = _oneof_filters_to_int_or_mask(input_filters)
  output_filters_or_mask = _oneof_filters_to_int_or_mask(output_filters)
  expansion_filters_or_mask = _oneof_filters_to_int_or_mask(
      layer_spec.expansion_filters, input_filters_or_mask, filters_base)

  result = [
      _conv(
          params,
          input_filters_or_mask=input_filters_or_mask,
          output_filters_or_mask=expansion_filters_or_mask,
          kernel_size=(1, 1),
          activation=_get_activation(layer_spec.activation)),
      _depthwise_conv(
          params,
          filters_or_mask=expansion_filters_or_mask,
          kernel_size=layer_spec.kernel_size,
          strides=layer_spec.strides,
          activation=_get_activation(layer_spec.activation)),
  ]

  result.append(
      _maybe_squeeze_and_excite(
          params,
          expansion_filters_or_mask,
          _get_activation(layer_spec.se_inner_activation),
          _get_activation(layer_spec.se_gating_activation),
          layer_spec.use_squeeze_and_excite))

  result.append(
      _conv(
          params,
          input_filters_or_mask=expansion_filters_or_mask,
          output_filters_or_mask=output_filters_or_mask,
          kernel_size=(1, 1),
          activation=None))

  return layers.Sequential(result)
Exemple #7
0
def _squeeze_and_excite(params,
                        input_filters_or_mask,
                        inner_activation,
                        gating_activation):
  """Generate a squeeze-and-excite layer."""
  # We provide two code paths:
  # 1. For the case where the number of input filters is known at graph
  #    construction time, and input_filters_or_mask is an int. This typically
  #    happens during stand-alone model training.
  # 2. For the case where the number of input filters is not known until
  #    runtime, and input_filters_or_mask is a 1D float tensor. This often
  #    happens during an architecture search.
  if isinstance(input_filters_or_mask, int):
    input_filters = input_filters_or_mask
    hidden_filters = search_space_utils.make_divisible(
        input_filters * _SQUEEZE_AND_EXCITE_RATIO,
        divisor=params['filters_base'])

    return layers.ParallelProduct([
        layers.Identity(),
        layers.Sequential([
            layers.GlobalAveragePool(keepdims=True),
            layers.Conv2D(
                filters=hidden_filters,
                kernel_size=(1, 1),
                kernel_initializer=params['kernel_initializer'],
                kernel_regularizer=params['kernel_regularizer'],
                use_bias=True),
            inner_activation,
            layers.Conv2D(
                filters=input_filters,
                kernel_size=(1, 1),
                kernel_initializer=params['kernel_initializer'],
                kernel_regularizer=params['kernel_regularizer'],
                use_bias=True),
            gating_activation,
        ]),
    ])
  else:
    input_mask = input_filters_or_mask
    input_filters = tf.reduce_sum(input_mask)
    hidden_filters = search_space_utils.tf_make_divisible(
        input_filters * _SQUEEZE_AND_EXCITE_RATIO,
        divisor=params['filters_base'])

    max_input_filters = int(input_mask.shape[0])
    max_hidden_filters = search_space_utils.make_divisible(
        max_input_filters * _SQUEEZE_AND_EXCITE_RATIO,
        divisor=params['filters_base'])

    hidden_mask = tf.sequence_mask(
        hidden_filters, max_hidden_filters, dtype=tf.float32)

    return layers.ParallelProduct([
        layers.Identity(),
        layers.Sequential([
            layers.GlobalAveragePool(keepdims=True),
            layers.MaskedConv2D(
                input_mask=input_mask,
                output_mask=hidden_mask,
                kernel_size=(1, 1),
                kernel_initializer=params['kernel_initializer'],
                kernel_regularizer=params['kernel_regularizer'],
                use_bias=True),
            inner_activation,
            layers.MaskedConv2D(
                input_mask=hidden_mask,
                output_mask=input_mask,
                kernel_size=(1, 1),
                kernel_initializer=params['kernel_initializer'],
                kernel_regularizer=params['kernel_regularizer'],
                use_bias=True),
            gating_activation,
        ])
    ])