"...composable_kernel.git" did not exist on "34c661e71cc8cf4753843a58786c8f6211ec5e22"
Unverified Commit f505cecd authored by pkulzc's avatar pkulzc Committed by GitHub
Browse files

Update slim and fix minor issue in object detection (#5354)

* Merged commit includes the following changes:
213899768  by Sergio Guadarrama:

    Fixes #3819.

--
213493831  by Sergio Guadarrama:

    Internal change

212057654  by Sergio Guadarrama:

    Internal change

210747685  by Sergio Guadarrama:

    For FPN, when use_depthwise is set to true, use slightly modified mobilenet v1 config.

--
210128931  by Sergio Guadarrama:

    Allow user-defined current_step in NASNet.

--
209092664  by Sergio Guadarrama:

    Add quantized fine-tuning / training / eval and export to slim image classifier binaries.

--
207651347  by Sergio Guadarrama:

    Update mobilenet v1 docs to include revised tflite models.

--
207165245  by Sergio Guadarrama:

    Internal change

207095064  by Sergio Guadarrama:

    Internal change

PiperOrigin-RevId: 213899768

* Update model_lib.py to fix eval_spec name issue.
parent d4e1f97f
...@@ -641,7 +641,7 @@ def create_train_and_eval_specs(train_input_fn, ...@@ -641,7 +641,7 @@ def create_train_and_eval_specs(train_input_fn,
input_fn=train_input_fn, max_steps=train_steps) input_fn=train_input_fn, max_steps=train_steps)
if eval_spec_names is None: if eval_spec_names is None:
eval_spec_names = range(len(eval_input_fns)) eval_spec_names = [ str(i) for i in range(len(eval_input_fns)) ]
eval_specs = [] eval_specs = []
for eval_spec_name, eval_input_fn in zip(eval_spec_names, eval_input_fns): for eval_spec_name, eval_input_fn in zip(eval_spec_names, eval_input_fns):
......
...@@ -80,7 +80,7 @@ py_binary( ...@@ -80,7 +80,7 @@ py_binary(
], ],
) )
py_binary( py_library(
name = "cifar10", name = "cifar10",
srcs = ["datasets/cifar10.py"], srcs = ["datasets/cifar10.py"],
deps = [ deps = [
...@@ -89,7 +89,7 @@ py_binary( ...@@ -89,7 +89,7 @@ py_binary(
], ],
) )
py_binary( py_library(
name = "flowers", name = "flowers",
srcs = ["datasets/flowers.py"], srcs = ["datasets/flowers.py"],
deps = [ deps = [
...@@ -98,7 +98,7 @@ py_binary( ...@@ -98,7 +98,7 @@ py_binary(
], ],
) )
py_binary( py_library(
name = "imagenet", name = "imagenet",
srcs = ["datasets/imagenet.py"], srcs = ["datasets/imagenet.py"],
deps = [ deps = [
...@@ -107,7 +107,7 @@ py_binary( ...@@ -107,7 +107,7 @@ py_binary(
], ],
) )
py_binary( py_library(
name = "mnist", name = "mnist",
srcs = ["datasets/mnist.py"], srcs = ["datasets/mnist.py"],
deps = [ deps = [
...@@ -715,8 +715,8 @@ py_binary( ...@@ -715,8 +715,8 @@ py_binary(
], ],
) )
py_binary( py_library(
name = "eval_image_classifier", name = "eval_image_classifier_lib",
srcs = ["eval_image_classifier.py"], srcs = ["eval_image_classifier.py"],
deps = [ deps = [
":dataset_factory", ":dataset_factory",
...@@ -726,6 +726,14 @@ py_binary( ...@@ -726,6 +726,14 @@ py_binary(
], ],
) )
py_binary(
name = "eval_image_classifier",
srcs = ["eval_image_classifier.py"],
deps = [
":eval_image_classifier_lib",
],
)
py_binary( py_binary(
name = "export_inference_graph", name = "export_inference_graph",
srcs = ["export_inference_graph.py"], srcs = ["export_inference_graph.py"],
......
...@@ -79,6 +79,9 @@ tf.app.flags.DEFINE_float( ...@@ -79,6 +79,9 @@ tf.app.flags.DEFINE_float(
tf.app.flags.DEFINE_integer( tf.app.flags.DEFINE_integer(
'eval_image_size', None, 'Eval image size') 'eval_image_size', None, 'Eval image size')
tf.app.flags.DEFINE_bool(
'quantize', False, 'whether to use quantized graph or not.')
FLAGS = tf.app.flags.FLAGS FLAGS = tf.app.flags.FLAGS
...@@ -138,6 +141,9 @@ def main(_): ...@@ -138,6 +141,9 @@ def main(_):
#################### ####################
logits, _ = network_fn(images) logits, _ = network_fn(images)
if FLAGS.quantize:
tf.contrib.quantize.create_eval_graph()
if FLAGS.moving_average_decay: if FLAGS.moving_average_decay:
variable_averages = tf.train.ExponentialMovingAverage( variable_averages = tf.train.ExponentialMovingAverage(
FLAGS.moving_average_decay, tf_global_step) FLAGS.moving_average_decay, tf_global_step)
......
...@@ -96,6 +96,9 @@ tf.app.flags.DEFINE_string( ...@@ -96,6 +96,9 @@ tf.app.flags.DEFINE_string(
tf.app.flags.DEFINE_string( tf.app.flags.DEFINE_string(
'dataset_dir', '', 'Directory to save intermediate dataset files to') 'dataset_dir', '', 'Directory to save intermediate dataset files to')
tf.app.flags.DEFINE_bool(
'quantize', False, 'whether to use quantized graph or not.')
FLAGS = tf.app.flags.FLAGS FLAGS = tf.app.flags.FLAGS
...@@ -115,6 +118,10 @@ def main(_): ...@@ -115,6 +118,10 @@ def main(_):
shape=[FLAGS.batch_size, image_size, shape=[FLAGS.batch_size, image_size,
image_size, 3]) image_size, 3])
network_fn(placeholder) network_fn(placeholder)
if FLAGS.quantize:
tf.contrib.quantize.create_eval_graph()
graph_def = graph.as_graph_def() graph_def = graph.as_graph_def()
with gfile.GFile(FLAGS.output_file, 'wb') as f: with gfile.GFile(FLAGS.output_file, 'wb') as f:
f.write(graph_def.SerializeToString()) f.write(graph_def.SerializeToString())
......
...@@ -91,6 +91,7 @@ def mobilenet(input_tensor, ...@@ -91,6 +91,7 @@ def mobilenet(input_tensor,
finegrain_classification_mode=False, finegrain_classification_mode=False,
min_depth=None, min_depth=None,
divisible_by=None, divisible_by=None,
activation_fn=None,
**kwargs): **kwargs):
"""Creates mobilenet V2 network. """Creates mobilenet V2 network.
...@@ -117,6 +118,8 @@ def mobilenet(input_tensor, ...@@ -117,6 +118,8 @@ def mobilenet(input_tensor,
many channels after application of depth multiplier. many channels after application of depth multiplier.
divisible_by: If provided will ensure that all layers # channels divisible_by: If provided will ensure that all layers # channels
will be divisible by this number. will be divisible by this number.
activation_fn: Activation function to use, defaults to tf.nn.relu6 if not
specified.
**kwargs: passed directly to mobilenet.mobilenet: **kwargs: passed directly to mobilenet.mobilenet:
prediction_fn- what prediction function to use. prediction_fn- what prediction function to use.
reuse-: whether to reuse variables (if reuse set to true, scope reuse-: whether to reuse variables (if reuse set to true, scope
...@@ -136,6 +139,12 @@ def mobilenet(input_tensor, ...@@ -136,6 +139,12 @@ def mobilenet(input_tensor,
conv_defs = copy.deepcopy(conv_defs) conv_defs = copy.deepcopy(conv_defs)
if depth_multiplier < 1: if depth_multiplier < 1:
conv_defs['spec'][-1].params['num_outputs'] /= depth_multiplier conv_defs['spec'][-1].params['num_outputs'] /= depth_multiplier
if activation_fn:
conv_defs = copy.deepcopy(conv_defs)
defaults = conv_defs['defaults']
conv_defaults = (
defaults[(slim.conv2d, slim.fully_connected, slim.separable_conv2d)])
conv_defaults['activation_fn'] = activation_fn
depth_args = {} depth_args = {}
# NB: do not set depth_args unless they are provided to avoid overriding # NB: do not set depth_args unless they are provided to avoid overriding
...@@ -154,6 +163,8 @@ def mobilenet(input_tensor, ...@@ -154,6 +163,8 @@ def mobilenet(input_tensor,
multiplier=depth_multiplier, multiplier=depth_multiplier,
**kwargs) **kwargs)
mobilenet.default_image_size = 224
def wrapped_partial(func, *args, **kwargs): def wrapped_partial(func, *args, **kwargs):
partial_func = functools.partial(func, *args, **kwargs) partial_func = functools.partial(func, *args, **kwargs)
......
...@@ -120,8 +120,8 @@ slim = tf.contrib.slim ...@@ -120,8 +120,8 @@ slim = tf.contrib.slim
Conv = namedtuple('Conv', ['kernel', 'stride', 'depth']) Conv = namedtuple('Conv', ['kernel', 'stride', 'depth'])
DepthSepConv = namedtuple('DepthSepConv', ['kernel', 'stride', 'depth']) DepthSepConv = namedtuple('DepthSepConv', ['kernel', 'stride', 'depth'])
# _CONV_DEFS specifies the MobileNet body # MOBILENETV1_CONV_DEFS specifies the MobileNet body
_CONV_DEFS = [ MOBILENETV1_CONV_DEFS = [
Conv(kernel=[3, 3], stride=2, depth=32), Conv(kernel=[3, 3], stride=2, depth=32),
DepthSepConv(kernel=[3, 3], stride=1, depth=64), DepthSepConv(kernel=[3, 3], stride=1, depth=64),
DepthSepConv(kernel=[3, 3], stride=2, depth=128), DepthSepConv(kernel=[3, 3], stride=2, depth=128),
...@@ -221,7 +221,7 @@ def mobilenet_v1_base(inputs, ...@@ -221,7 +221,7 @@ def mobilenet_v1_base(inputs,
raise ValueError('depth_multiplier is not greater than zero.') raise ValueError('depth_multiplier is not greater than zero.')
if conv_defs is None: if conv_defs is None:
conv_defs = _CONV_DEFS conv_defs = MOBILENETV1_CONV_DEFS
if output_stride is not None and output_stride not in [8, 16, 32]: if output_stride is not None and output_stride not in [8, 16, 32]:
raise ValueError('Only allowed output_stride values are 8, 16, 32.') raise ValueError('Only allowed output_stride values are 8, 16, 32.')
......
...@@ -245,7 +245,7 @@ def _build_aux_head(net, end_points, num_classes, hparams, scope): ...@@ -245,7 +245,7 @@ def _build_aux_head(net, end_points, num_classes, hparams, scope):
end_points['AuxLogits'] = aux_logits end_points['AuxLogits'] = aux_logits
def _imagenet_stem(inputs, hparams, stem_cell): def _imagenet_stem(inputs, hparams, stem_cell, current_step=None):
"""Stem used for models trained on ImageNet.""" """Stem used for models trained on ImageNet."""
num_stem_cells = 2 num_stem_cells = 2
...@@ -266,7 +266,8 @@ def _imagenet_stem(inputs, hparams, stem_cell): ...@@ -266,7 +266,8 @@ def _imagenet_stem(inputs, hparams, stem_cell):
filter_scaling=filter_scaling, filter_scaling=filter_scaling,
stride=2, stride=2,
prev_layer=cell_outputs[-2], prev_layer=cell_outputs[-2],
cell_num=cell_num) cell_num=cell_num,
current_step=current_step)
cell_outputs.append(net) cell_outputs.append(net)
filter_scaling *= hparams.filter_scaling_rate filter_scaling *= hparams.filter_scaling_rate
return net, cell_outputs return net, cell_outputs
...@@ -286,7 +287,8 @@ def _cifar_stem(inputs, hparams): ...@@ -286,7 +287,8 @@ def _cifar_stem(inputs, hparams):
def build_nasnet_cifar(images, num_classes, def build_nasnet_cifar(images, num_classes,
is_training=True, is_training=True,
config=None): config=None,
current_step=None):
"""Build NASNet model for the Cifar Dataset.""" """Build NASNet model for the Cifar Dataset."""
hparams = cifar_config() if config is None else copy.deepcopy(config) hparams = cifar_config() if config is None else copy.deepcopy(config)
_update_hparams(hparams, is_training) _update_hparams(hparams, is_training)
...@@ -326,14 +328,16 @@ def build_nasnet_cifar(images, num_classes, ...@@ -326,14 +328,16 @@ def build_nasnet_cifar(images, num_classes,
num_classes=num_classes, num_classes=num_classes,
hparams=hparams, hparams=hparams,
is_training=is_training, is_training=is_training,
stem_type='cifar') stem_type='cifar',
current_step=current_step)
build_nasnet_cifar.default_image_size = 32 build_nasnet_cifar.default_image_size = 32
def build_nasnet_mobile(images, num_classes, def build_nasnet_mobile(images, num_classes,
is_training=True, is_training=True,
final_endpoint=None, final_endpoint=None,
config=None): config=None,
current_step=None):
"""Build NASNet Mobile model for the ImageNet Dataset.""" """Build NASNet Mobile model for the ImageNet Dataset."""
hparams = (mobile_imagenet_config() if config is None hparams = (mobile_imagenet_config() if config is None
else copy.deepcopy(config)) else copy.deepcopy(config))
...@@ -377,14 +381,16 @@ def build_nasnet_mobile(images, num_classes, ...@@ -377,14 +381,16 @@ def build_nasnet_mobile(images, num_classes,
hparams=hparams, hparams=hparams,
is_training=is_training, is_training=is_training,
stem_type='imagenet', stem_type='imagenet',
final_endpoint=final_endpoint) final_endpoint=final_endpoint,
current_step=current_step)
build_nasnet_mobile.default_image_size = 224 build_nasnet_mobile.default_image_size = 224
def build_nasnet_large(images, num_classes, def build_nasnet_large(images, num_classes,
is_training=True, is_training=True,
final_endpoint=None, final_endpoint=None,
config=None): config=None,
current_step=None):
"""Build NASNet Large model for the ImageNet Dataset.""" """Build NASNet Large model for the ImageNet Dataset."""
hparams = (large_imagenet_config() if config is None hparams = (large_imagenet_config() if config is None
else copy.deepcopy(config)) else copy.deepcopy(config))
...@@ -428,7 +434,8 @@ def build_nasnet_large(images, num_classes, ...@@ -428,7 +434,8 @@ def build_nasnet_large(images, num_classes,
hparams=hparams, hparams=hparams,
is_training=is_training, is_training=is_training,
stem_type='imagenet', stem_type='imagenet',
final_endpoint=final_endpoint) final_endpoint=final_endpoint,
current_step=current_step)
build_nasnet_large.default_image_size = 331 build_nasnet_large.default_image_size = 331
...@@ -439,7 +446,8 @@ def _build_nasnet_base(images, ...@@ -439,7 +446,8 @@ def _build_nasnet_base(images,
hparams, hparams,
is_training, is_training,
stem_type, stem_type,
final_endpoint=None): final_endpoint=None,
current_step=None):
"""Constructs a NASNet image model.""" """Constructs a NASNet image model."""
end_points = {} end_points = {}
...@@ -482,7 +490,8 @@ def _build_nasnet_base(images, ...@@ -482,7 +490,8 @@ def _build_nasnet_base(images,
filter_scaling=filter_scaling, filter_scaling=filter_scaling,
stride=2, stride=2,
prev_layer=cell_outputs[-2], prev_layer=cell_outputs[-2],
cell_num=true_cell_num) cell_num=true_cell_num,
current_step=current_step)
if add_and_check_endpoint( if add_and_check_endpoint(
'Reduction_Cell_{}'.format(reduction_indices.index(cell_num)), net): 'Reduction_Cell_{}'.format(reduction_indices.index(cell_num)), net):
return net, end_points return net, end_points
...@@ -496,7 +505,8 @@ def _build_nasnet_base(images, ...@@ -496,7 +505,8 @@ def _build_nasnet_base(images,
filter_scaling=filter_scaling, filter_scaling=filter_scaling,
stride=stride, stride=stride,
prev_layer=prev_layer, prev_layer=prev_layer,
cell_num=true_cell_num) cell_num=true_cell_num,
current_step=current_step)
if add_and_check_endpoint('Cell_{}'.format(cell_num), net): if add_and_check_endpoint('Cell_{}'.format(cell_num), net):
return net, end_points return net, end_points
......
...@@ -371,6 +371,24 @@ class NASNetTest(tf.test.TestCase): ...@@ -371,6 +371,24 @@ class NASNetTest(tf.test.TestCase):
self.assertListEqual( self.assertListEqual(
end_points['Stem'].shape.as_list(), [batch_size, 336, 42, 42]) end_points['Stem'].shape.as_list(), [batch_size, 336, 42, 42])
def testCurrentStepCifarModel(self):
batch_size = 5
height, width = 32, 32
num_classes = 10
inputs = tf.random_uniform((batch_size, height, width, 3))
global_step = tf.train.create_global_step()
with slim.arg_scope(nasnet.nasnet_cifar_arg_scope()):
logits, end_points = nasnet.build_nasnet_cifar(inputs,
num_classes,
current_step=global_step)
auxlogits = end_points['AuxLogits']
predictions = end_points['Predictions']
self.assertListEqual(auxlogits.get_shape().as_list(),
[batch_size, num_classes])
self.assertListEqual(logits.get_shape().as_list(),
[batch_size, num_classes])
self.assertListEqual(predictions.get_shape().as_list(),
[batch_size, num_classes])
if __name__ == '__main__': if __name__ == '__main__':
tf.test.main() tf.test.main()
...@@ -300,7 +300,7 @@ class NasNetABaseCell(object): ...@@ -300,7 +300,7 @@ class NasNetABaseCell(object):
return net return net
def __call__(self, net, scope=None, filter_scaling=1, stride=1, def __call__(self, net, scope=None, filter_scaling=1, stride=1,
prev_layer=None, cell_num=-1): prev_layer=None, cell_num=-1, current_step=None):
"""Runs the conv cell.""" """Runs the conv cell."""
self._cell_num = cell_num self._cell_num = cell_num
self._filter_scaling = filter_scaling self._filter_scaling = filter_scaling
...@@ -325,10 +325,12 @@ class NasNetABaseCell(object): ...@@ -325,10 +325,12 @@ class NasNetABaseCell(object):
# Apply conv operations # Apply conv operations
with tf.variable_scope('left'): with tf.variable_scope('left'):
h1 = self._apply_conv_operation(h1, operation_left, h1 = self._apply_conv_operation(h1, operation_left,
stride, original_input_left) stride, original_input_left,
current_step)
with tf.variable_scope('right'): with tf.variable_scope('right'):
h2 = self._apply_conv_operation(h2, operation_right, h2 = self._apply_conv_operation(h2, operation_right,
stride, original_input_right) stride, original_input_right,
current_step)
# Combine hidden states using 'add'. # Combine hidden states using 'add'.
with tf.variable_scope('combine'): with tf.variable_scope('combine'):
...@@ -343,7 +345,7 @@ class NasNetABaseCell(object): ...@@ -343,7 +345,7 @@ class NasNetABaseCell(object):
return net return net
def _apply_conv_operation(self, net, operation, def _apply_conv_operation(self, net, operation,
stride, is_from_original_input): stride, is_from_original_input, current_step):
"""Applies the predicted conv operation to net.""" """Applies the predicted conv operation to net."""
# Dont stride if this is not one of the original hiddenstates # Dont stride if this is not one of the original hiddenstates
if stride > 1 and not is_from_original_input: if stride > 1 and not is_from_original_input:
...@@ -367,7 +369,7 @@ class NasNetABaseCell(object): ...@@ -367,7 +369,7 @@ class NasNetABaseCell(object):
raise ValueError('Unimplemented operation', operation) raise ValueError('Unimplemented operation', operation)
if operation != 'none': if operation != 'none':
net = self._apply_drop_path(net) net = self._apply_drop_path(net, current_step=current_step)
return net return net
def _combine_unused_states(self, net): def _combine_unused_states(self, net):
...@@ -433,9 +435,9 @@ class NasNetABaseCell(object): ...@@ -433,9 +435,9 @@ class NasNetABaseCell(object):
drop_path_keep_prob = 1 - layer_ratio * (1 - drop_path_keep_prob) drop_path_keep_prob = 1 - layer_ratio * (1 - drop_path_keep_prob)
if drop_connect_version in ['v1', 'v3']: if drop_connect_version in ['v1', 'v3']:
# Decrease the keep probability over time # Decrease the keep probability over time
if not current_step: if current_step is None:
current_step = tf.cast(tf.train.get_or_create_global_step(), current_step = tf.train.get_or_create_global_step()
tf.float32) current_step = tf.cast(current_step, tf.float32)
drop_path_burn_in_steps = self._total_training_steps drop_path_burn_in_steps = self._total_training_steps
current_ratio = current_step / drop_path_burn_in_steps current_ratio = current_step / drop_path_burn_in_steps
current_ratio = tf.minimum(1.0, current_ratio) current_ratio = tf.minimum(1.0, current_ratio)
......
...@@ -124,6 +124,11 @@ tf.app.flags.DEFINE_float('rmsprop_momentum', 0.9, 'Momentum.') ...@@ -124,6 +124,11 @@ tf.app.flags.DEFINE_float('rmsprop_momentum', 0.9, 'Momentum.')
tf.app.flags.DEFINE_float('rmsprop_decay', 0.9, 'Decay term for RMSProp.') tf.app.flags.DEFINE_float('rmsprop_decay', 0.9, 'Decay term for RMSProp.')
tf.app.flags.DEFINE_integer(
'quantize_delay', -1,
'Number of steps to start quantized training. Set to -1 would disable '
'quantized training.')
####################### #######################
# Learning Rate Flags # # Learning Rate Flags #
####################### #######################
...@@ -511,6 +516,10 @@ def main(_): ...@@ -511,6 +516,10 @@ def main(_):
else: else:
moving_average_variables, variable_averages = None, None moving_average_variables, variable_averages = None, None
if FLAGS.quantize_delay >= 0:
tf.contrib.quantize.create_training_graph(
quant_delay=FLAGS.quantize_delay)
######################################### #########################################
# Configure the optimization procedure. # # Configure the optimization procedure. #
######################################### #########################################
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment