def test_prune_simple_model_spec_validation_no_tags(self): model_spec = [ schema.OneOf(['a', 'b', 'c'], basic_specs.OP_TAG), schema.OneOf(['z', 'w'], basic_specs.FILTERS_TAG), ] with self.assertRaisesWithLiteralMatch( ValueError, 'Genotype contains 1 oneofs but model_spec contains 2'): search_space_utils.prune_model_spec(model_spec=model_spec, genotype=[0], prune_filters_by_value=True)
def test_prune_model_spec_prune_filters_by_value_with_invalid_value(self): model_spec = { 'op': schema.OneOf(['a', 'b', 'c'], basic_specs.OP_TAG), 'filters': schema.OneOf([128, 256, 512], basic_specs.FILTERS_TAG), } genotype = { basic_specs.OP_TAG: [1], basic_specs.FILTERS_TAG: [1024], # Use values instead of indices } with self.assertRaises(ValueError): search_space_utils.prune_model_spec(model_spec, genotype, prune_filters_by_value=True)
def mnasnet_b1(): model_spec = _proxylessnas_search_base( mobile_model_archive.MNASNET_FILTERS) model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: mobile_model_archive.MNASNET_OPERATIONS}) return model_spec
def test_prune_model_spec_with_path_dropout_rate_tensor(self): model_spec = { 'op1': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=2, strides=2), basic_specs.ZeroSpec(), ], basic_specs.OP_TAG), 'op2': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=3, strides=4), ], basic_specs.OP_TAG), 'filter': schema.OneOf([32], basic_specs.FILTERS_TAG), } model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: [0, 0]}, path_dropout_rate=tf.constant(2.0) / tf.constant(10.0), training=True) self.assertCountEqual(model_spec.keys(), ['op1', 'op2', 'filter']) self.assertEqual(model_spec['op1'].mask.shape, tf.TensorShape([1])) self.assertIsNone(model_spec['op2'].mask) self.assertIsNone(model_spec['filter'].mask) # The value should either be 0 or 1 / (1 - path_dropout_rate) = 1.25 op_mask_value = self.evaluate(model_spec['op1'].mask) self.assertTrue( abs(op_mask_value - 0) < 1e-6 or abs(op_mask_value - 1.25) < 1e-6, msg='Unexpected op_mask_value: {}'.format(op_mask_value))
def proxylessnas_mobile(): model_spec = _proxylessnas_search_base( mobile_model_archive.PROXYLESSNAS_MOBILE_FILTERS) model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: mobile_model_archive.PROXYLESSNAS_MOBILE_OPERATIONS}) return model_spec
def mobilenet_v2(): """Specification for MobileNet V2 w/ relative expansion filters.""" model_spec = _proxylessnas_search_base( mobile_model_archive.MOBILENET_V2_FILTERS) model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: mobile_model_archive.MOBILENET_V2_OPERATIONS}) return model_spec
def test_prune_model_spec_with_path_dropout_training(self): model_spec = { 'op1': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=2, strides=2), basic_specs.ZeroSpec(), ], basic_specs.OP_TAG), 'op2': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=3, strides=4), ], basic_specs.OP_TAG), 'filter': schema.OneOf([32], basic_specs.FILTERS_TAG), } model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: [0, 0]}, path_dropout_rate=0.2, training=True) self.assertCountEqual(model_spec.keys(), ['op1', 'op2', 'filter']) self.assertEqual(model_spec['op1'].mask.shape, tf.TensorShape([1])) self.assertIsNone(model_spec['op2'].mask) self.assertIsNone(model_spec['filter'].mask) self.assertEqual( model_spec['op1'].choices, [mobile_search_space_v3.ConvSpec(kernel_size=2, strides=2)]) self.assertEqual( model_spec['op2'].choices, [mobile_search_space_v3.ConvSpec(kernel_size=3, strides=4)]) self.assertEqual(model_spec['filter'].choices, [32]) self.assertEqual(model_spec['op1'].tag, basic_specs.OP_TAG) self.assertEqual(model_spec['op2'].tag, basic_specs.OP_TAG) self.assertEqual(model_spec['filter'].tag, basic_specs.FILTERS_TAG) op_mask_sum = 0 for _ in range(100): # The value should either be 0 or 1 / (1 - path_dropout_rate) = 1.25 op_mask_value = self.evaluate(model_spec['op1'].mask) self.assertTrue( abs(op_mask_value - 0) < 1e-6 or abs(op_mask_value - 1.25) < 1e-6, msg='Unexpected op_mask_value: {}'.format(op_mask_value)) op_mask_sum += op_mask_value[0] # The probability of this test failing by random chance is roughly 0.002%. # Our random number generators are deterministically seeded, so the test # shouldn't be flakey. self.assertGreaterEqual(op_mask_sum, 75) self.assertLessEqual(op_mask_sum, 113)
def test_prune_simple_model_spec_no_tags(self): pruned_spec = search_space_utils.prune_model_spec( model_spec=[ schema.OneOf(['a', 'b', 'c'], basic_specs.OP_TAG), schema.OneOf(['z', 'w'], basic_specs.FILTERS_TAG), ], genotype=[2, 1], prune_filters_by_value=True) self.assertEqual(pruned_spec, [ schema.OneOf(['c'], basic_specs.OP_TAG), schema.OneOf(['w'], basic_specs.FILTERS_TAG), ])
def get_model_spec(ssd, filters=None, op_indices=None, indices=None, filters_multipliers=1.0, path_dropout_rate=0.0, training=None): """Get a model spec namedtuple for the given search space definition. Args: ssd: Search space definition to use. filters: List of filter sizes to use. Required for V2 search spaces. op_indices: List of integers specifying the operations to select. indices: List of integers specifying the values to use for all the operations in the search space. If specified, this will override op_indices and filters. filters_multipliers: Single value or a list of possible values, used to scale up/down the number of filters in each layer of the network. path_dropout_rate: Rate of path dropout to use during stand-alone training. training: Boolean. Only needs to be specified if path_dropout_rate > 0. Returns: A basic_specs.ConvTowerSpec namedtuple. """ if ssd in mobile_search_space_v3.ALL_SSDS: model_spec = mobile_search_space_v3.get_search_space_spec(ssd) else: raise ValueError('Unsupported SSD: {}'.format(ssd)) if indices: genotype = indices else: genotype = dict() if op_indices: genotype[basic_specs.OP_TAG] = op_indices if filters and ssd in mobile_search_space_v3.ALL_SSDS: genotype[basic_specs.FILTERS_TAG] = filters model_spec = search_space_utils.prune_model_spec( model_spec, genotype, prune_filters_by_value=True, path_dropout_rate=path_dropout_rate, training=training) model_spec = search_space_utils.scale_conv_tower_spec( model_spec, filters_multipliers) return model_spec
def test_prune_model_spec_prune_filters_by_value(self): model_spec = { 'op': schema.OneOf(['a', 'b', 'c'], basic_specs.OP_TAG), 'filters': schema.OneOf([128, 256, 512], basic_specs.FILTERS_TAG), } genotype = { basic_specs.OP_TAG: [1], basic_specs.FILTERS_TAG: [512], # Use values instead of indices } pruned_spec = search_space_utils.prune_model_spec( model_spec, genotype, prune_filters_by_value=True) expected_spec = { 'op': schema.OneOf(['b'], basic_specs.OP_TAG), 'filters': schema.OneOf([512], basic_specs.FILTERS_TAG), } self.assertEqual(pruned_spec, expected_spec)
def test_prune_model_spec_with_path_dropout_eval(self): model_spec = { 'op1': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=2, strides=2), basic_specs.ZeroSpec(), ], basic_specs.OP_TAG), 'op2': schema.OneOf([ mobile_search_space_v3.ConvSpec(kernel_size=3, strides=4), ], basic_specs.OP_TAG), 'filter': schema.OneOf([32], basic_specs.FILTERS_TAG), } model_spec = search_space_utils.prune_model_spec( model_spec, {basic_specs.OP_TAG: [0, 0]}, path_dropout_rate=0.2, training=False) self.assertCountEqual(model_spec.keys(), ['op1', 'op2', 'filter']) # Even though path_dropout_rate=0.2, the controller should not populate # the mask for op1 because we called prune_model_spec() with training=False. # In other words, path_dropout_rate should only affect the behavior during # training, not during evaluation. self.assertIsNone(model_spec['op1'].mask) self.assertIsNone(model_spec['op2'].mask) self.assertIsNone(model_spec['filter'].mask) self.assertEqual(model_spec['op1'].tag, basic_specs.OP_TAG) self.assertEqual(model_spec['op2'].tag, basic_specs.OP_TAG) self.assertEqual(model_spec['filter'].tag, basic_specs.FILTERS_TAG) self.assertEqual( model_spec['op1'].choices, [mobile_search_space_v3.ConvSpec(kernel_size=2, strides=2)]) self.assertEqual( model_spec['op2'].choices, [mobile_search_space_v3.ConvSpec(kernel_size=3, strides=4)]) self.assertEqual(model_spec['filter'].choices, [32])