slim-transfer-learning

Transfer learning on TensorFlow-Slim image classification model library

Download ZIP
# 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.# =============================================================================="""Tests for mobilenet_v2."""from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport copyfrom six.moves import rangeimport tensorflow.compat.v1 as tfimport tf_slim as slimfrom nets.mobilenet import conv_blocks as opsfrom nets.mobilenet import mobilenetfrom nets.mobilenet import mobilenet_v2def find_ops(optype):  """Find ops of a given type in graphdef or a graph.  Args:    optype: operation type (e.g. Conv2D)  Returns:     List of operations.  """  gd = tf.get_default_graph()  return [var for var in gd.get_operations() if var.type == optype]class MobilenetV2Test(tf.test.TestCase):  def testCreation(self):    spec = dict(mobilenet_v2.V2_DEF)    _, ep = mobilenet.mobilenet(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=spec)    num_convs = len(find_ops('Conv2D'))    # This is mostly a sanity test. No deep reason for these particular    # constants.    #    # All but first 2 and last one have  two convolutions, and there is one    # extra conv that is not in the spec. (logits)    self.assertEqual(num_convs, len(spec['spec']) * 2 - 2)    # Check that depthwise are exposed.    for i in range(2, 17):      self.assertIn('layer_%d/depthwise_output' % i, ep)  def testCreationNoClasses(self):    spec = copy.deepcopy(mobilenet_v2.V2_DEF)    net, ep = mobilenet.mobilenet(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=spec,        num_classes=None)    self.assertIs(net, ep['global_pool'])  def testImageSizes(self):    for input_size, output_size in [(224, 7), (192, 6), (160, 5),                                    (128, 4), (96, 3)]:      tf.reset_default_graph()      _, ep = mobilenet_v2.mobilenet(          tf.placeholder(tf.float32, (10, input_size, input_size, 3)))      self.assertEqual(ep['layer_18/output'].get_shape().as_list()[1:3],                       [output_size] * 2)  def testWithSplits(self):    spec = copy.deepcopy(mobilenet_v2.V2_DEF)    spec['overrides'] = {        (ops.expanded_conv,): dict(split_expansion=2),    }    _, _ = mobilenet.mobilenet(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=spec)    num_convs = len(find_ops('Conv2D'))    # All but 3 op has 3 conv operatore, the remainign 3 have one    # and there is one unaccounted.    self.assertEqual(num_convs, len(spec['spec']) * 3 - 5)  def testWithOutputStride8(self):    out, _ = mobilenet.mobilenet_base(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=mobilenet_v2.V2_DEF,        output_stride=8,        scope='MobilenetV2')    self.assertEqual(out.get_shape().as_list()[1:3], [28, 28])  def testDivisibleBy(self):    tf.reset_default_graph()    mobilenet_v2.mobilenet(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=mobilenet_v2.V2_DEF,        divisible_by=16,        min_depth=32)    s = [op.outputs[0].get_shape().as_list()[-1] for op in find_ops('Conv2D')]    s = set(s)    self.assertSameElements([32, 64, 96, 160, 192, 320, 384, 576, 960, 1280,                             1001], s)  def testDivisibleByWithArgScope(self):    tf.reset_default_graph()    # Verifies that depth_multiplier arg scope actually works    # if no default min_depth is provided.    with slim.arg_scope((mobilenet.depth_multiplier,), min_depth=32):      mobilenet_v2.mobilenet(          tf.placeholder(tf.float32, (10, 224, 224, 2)),          conv_defs=mobilenet_v2.V2_DEF,          depth_multiplier=0.1)      s = [op.outputs[0].get_shape().as_list()[-1] for op in find_ops('Conv2D')]      s = set(s)      self.assertSameElements(s, [32, 192, 128, 1001])  def testFineGrained(self):    tf.reset_default_graph()    # Verifies that depth_multiplier arg scope actually works    # if no default min_depth is provided.    mobilenet_v2.mobilenet(        tf.placeholder(tf.float32, (10, 224, 224, 2)),        conv_defs=mobilenet_v2.V2_DEF,        depth_multiplier=0.01,        finegrain_classification_mode=True)    s = [op.outputs[0].get_shape().as_list()[-1] for op in find_ops('Conv2D')]    s = set(s)    # All convolutions will be 8->48, except for the last one.    self.assertSameElements(s, [8, 48, 1001, 1280])  def testMobilenetBase(self):    tf.reset_default_graph()    # Verifies that mobilenet_base returns pre-pooling layer.    with slim.arg_scope((mobilenet.depth_multiplier,), min_depth=32):      net, _ = mobilenet_v2.mobilenet_base(          tf.placeholder(tf.float32, (10, 224, 224, 16)),          conv_defs=mobilenet_v2.V2_DEF,          depth_multiplier=0.1)      self.assertEqual(net.get_shape().as_list(), [10, 7, 7, 128])  def testWithOutputStride16(self):    tf.reset_default_graph()    out, _ = mobilenet.mobilenet_base(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=mobilenet_v2.V2_DEF,        output_stride=16)    self.assertEqual(out.get_shape().as_list()[1:3], [14, 14])  def testMultiplier(self):    op = mobilenet.op    new_def = copy.deepcopy(mobilenet_v2.V2_DEF)    def inverse_multiplier(output_params, multiplier):      output_params['num_outputs'] = int(          output_params['num_outputs'] / multiplier)    new_def['spec'][0] = op(        slim.conv2d,        kernel_size=(3, 3),        multiplier_func=inverse_multiplier,        num_outputs=16)    _ = mobilenet_v2.mobilenet_base(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=new_def,        depth_multiplier=0.1)    s = [op.outputs[0].get_shape().as_list()[-1] for op in find_ops('Conv2D')]    # Expect first layer to be 160 (16 / 0.1), and other layers    # their max(original size * 0.1, 8)    self.assertEqual([160, 8, 48, 8, 48], s[:5])  def testWithOutputStride8AndExplicitPadding(self):    tf.reset_default_graph()    out, _ = mobilenet.mobilenet_base(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=mobilenet_v2.V2_DEF,        output_stride=8,        use_explicit_padding=True,        scope='MobilenetV2')    self.assertEqual(out.get_shape().as_list()[1:3], [28, 28])  def testWithOutputStride16AndExplicitPadding(self):    tf.reset_default_graph()    out, _ = mobilenet.mobilenet_base(        tf.placeholder(tf.float32, (10, 224, 224, 16)),        conv_defs=mobilenet_v2.V2_DEF,        output_stride=16,        use_explicit_padding=True)    self.assertEqual(out.get_shape().as_list()[1:3], [14, 14])  def testBatchNormScopeDoesNotHaveIsTrainingWhenItsSetToNone(self):    sc = mobilenet.training_scope(is_training=None)    self.assertNotIn('is_training', sc[slim.arg_scope_func_key(        slim.batch_norm)])  def testBatchNormScopeDoesHasIsTrainingWhenItsNotNone(self):    sc = mobilenet.training_scope(is_training=False)    self.assertIn('is_training', sc[slim.arg_scope_func_key(slim.batch_norm)])    sc = mobilenet.training_scope(is_training=True)    self.assertIn('is_training', sc[slim.arg_scope_func_key(slim.batch_norm)])    sc = mobilenet.training_scope()    self.assertIn('is_training', sc[slim.arg_scope_func_key(slim.batch_norm)])if __name__ == '__main__':  tf.test.main()