-# Copyright 2018 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Implementation of Mobilenet V2.
-
-Architecture: https://arxiv.org/abs/1801.04381
-
-The base model gives 72.2% accuracy on ImageNet, with 300MMadds,
-3.4 M parameters.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import copy
-
-import tensorflow as tf
-
-from libs.networks.mobilenet import conv_blocks as ops
-from libs.networks.mobilenet import mobilenet as lib
-
-slim = tf.contrib.slim
-op = lib.op
-
-expand_input = ops.expand_input_by_factor
-
-# pyformat: disable
-# Architecture: https://arxiv.org/abs/1801.04381
-V2_DEF = dict(
- defaults={
- # Note: these parameters of batch norm affect the architecture
- # that's why they are here and not in training_scope.
- (slim.batch_norm,): {'center': True, 'scale': True},
- (slim.conv2d, slim.fully_connected, slim.separable_conv2d): {
- 'normalizer_fn': slim.batch_norm, 'activation_fn': tf.nn.relu6
- },
- (ops.expanded_conv,): {
- 'expansion_size': expand_input(6),
- 'split_expansion': 1,
- 'normalizer_fn': slim.batch_norm,
- 'residual': True
- },
- (slim.conv2d, slim.separable_conv2d): {'padding': 'SAME'}
- },
- spec=[
- op(slim.conv2d, stride=2, num_outputs=32, kernel_size=[3, 3]),
- op(ops.expanded_conv,
- expansion_size=expand_input(1, divisible_by=1),
- num_outputs=16),
- op(ops.expanded_conv, stride=2, num_outputs=24),
- op(ops.expanded_conv, stride=1, num_outputs=24),
- op(ops.expanded_conv, stride=2, num_outputs=32),
- op(ops.expanded_conv, stride=1, num_outputs=32),
- op(ops.expanded_conv, stride=1, num_outputs=32),
- op(ops.expanded_conv, stride=2, num_outputs=64),
- op(ops.expanded_conv, stride=1, num_outputs=64),
- op(ops.expanded_conv, stride=1, num_outputs=64),
- op(ops.expanded_conv, stride=1, num_outputs=64),
- op(ops.expanded_conv, stride=1, num_outputs=96),
- op(ops.expanded_conv, stride=1, num_outputs=96),
- op(ops.expanded_conv, stride=1, num_outputs=96),
- op(ops.expanded_conv, stride=2, num_outputs=160),
- op(ops.expanded_conv, stride=1, num_outputs=160),
- op(ops.expanded_conv, stride=1, num_outputs=160),
- op(ops.expanded_conv, stride=1, num_outputs=320),
- op(slim.conv2d, stride=1, kernel_size=[1, 1], num_outputs=1280)
- ],
-)
-# pyformat: enable
-
-
-@slim.add_arg_scope
-def mobilenet(input_tensor,
- num_classes=1001,
- depth_multiplier=1.0,
- scope='MobilenetV2',
- conv_defs=None,
- finegrain_classification_mode=False,
- min_depth=None,
- divisible_by=None,
- **kwargs):
- """Creates mobilenet V2 network.
-
- Inference mode is created by default. To create training use training_scope
- below.
-
- with tf.contrib.slim.arg_scope(mobilenet_v2.training_scope()):
- logits, endpoints = mobilenet_v2.mobilenet(input_tensor)
-
- Args:
- input_tensor: The input tensor
- num_classes: number of classes
- depth_multiplier: The multiplier applied to scale number of
- channels in each layer. Note: this is called depth multiplier in the
- paper but the name is kept for consistency with slim's model builder.
- scope: Scope of the operator
- conv_defs: Allows to override default conv def.
- finegrain_classification_mode: When set to True, the model
- will keep the last layer large even for small multipliers. Following
- https://arxiv.org/abs/1801.04381
- suggests that it improves performance for ImageNet-type of problems.
- *Note* ignored if final_endpoint makes the builder exit earlier.
- min_depth: If provided, will ensure that all layers will have that
- many channels after application of depth multiplier.
- divisible_by: If provided will ensure that all layers # channels
- will be divisible by this number.
- **kwargs: passed directly to mobilenet.mobilenet:
- prediciton_fn- what prediction function to use.
- reuse-: whether to reuse variables (if reuse set to true, scope
- must be given).
- Returns:
- logits/endpoints pair
-
- Raises:
- ValueError: On invalid arguments
- """
- if conv_defs is None:
- conv_defs = V2_DEF
- if 'multiplier' in kwargs:
- raise ValueError('mobilenetv2 doesn\'t support generic '
- 'multiplier parameter use "depth_multiplier" instead.')
- if finegrain_classification_mode:
- conv_defs = copy.deepcopy(conv_defs)
- if depth_multiplier < 1:
- conv_defs['spec'][-1].params['num_outputs'] /= depth_multiplier
-
- depth_args = {}
- # NB: do not set depth_args unless they are provided to avoid overriding
- # whatever default depth_multiplier might have thanks to arg_scope.
- if min_depth is not None:
- depth_args['min_depth'] = min_depth
- if divisible_by is not None:
- depth_args['divisible_by'] = divisible_by
-
- with slim.arg_scope((lib.depth_multiplier,), **depth_args):
- return lib.mobilenet(
- input_tensor,
- num_classes=num_classes,
- conv_defs=conv_defs,
- scope=scope,
- multiplier=depth_multiplier,
- **kwargs)
-
-
-@slim.add_arg_scope
-def mobilenet_base(input_tensor, depth_multiplier=1.0, **kwargs):
- """Creates base of the mobilenet (no pooling and no logits) ."""
- return mobilenet(input_tensor,
- depth_multiplier=depth_multiplier,
- base_only=True, **kwargs)
-
-
-def training_scope(**kwargs):
- """Defines MobilenetV2 training scope.
-
- Usage:
- with tf.contrib.slim.arg_scope(mobilenet_v2.training_scope()):
- logits, endpoints = mobilenet_v2.mobilenet(input_tensor)
-
- with slim.
-
- Args:
- **kwargs: Passed to mobilenet.training_scope. The following parameters
- are supported:
- weight_decay- The weight decay to use for regularizing the model.
- stddev- Standard deviation for initialization, if negative uses xavier.
- dropout_keep_prob- dropout keep probability
- bn_decay- decay for the batch norm moving averages.
-
- Returns:
- An `arg_scope` to use for the mobilenet v2 model.
- """
- return lib.training_scope(**kwargs)
-
-
-__all__ = ['training_scope', 'mobilenet_base', 'mobilenet', 'V2_DEF']