def expand(fn_name):
      if fn_name == "plain_preprocess":
        yield lambda x: x
      elif fn_name == "0_to_1":
        yield get_value_range_preprocess(0, 1)
      elif fn_name == "-1_to_1":
        yield get_value_range_preprocess(-1, 1)
      elif fn_name == "resize":
        yield get_resize_preprocess(
            utils.str2intlist(FLAGS.resize_size, 2),
            is_training and FLAGS.get_flag_value("randomize_resize_method",
                                                 False))
      elif fn_name == "resize_small":
        yield get_resize_small(FLAGS.smaller_size)
      elif fn_name == "crop":
        yield get_crop(is_training,
                       utils.str2intlist(FLAGS.crop_size, 2))
      elif fn_name == "central_crop":
        yield get_crop(False, utils.str2intlist(FLAGS.crop_size, 2))
      elif fn_name == "inception_crop":
        yield get_inception_crop(is_training)
      elif fn_name == "flip_lr":
        yield get_random_flip_lr(is_training)
      elif fn_name == "crop_inception_preprocess_patches":
        yield get_inception_preprocess_patches(
            is_training, utils.str2intlist(FLAGS.resize_size, 2),
            FLAGS.num_of_inception_patches)
      elif fn_name == "to_gray":
        yield get_to_gray_preprocess(
            FLAGS.get_flag_value("grayscale_probability", 1.0))
      elif fn_name == "crop_patches":
        yield pp_lib.get_crop_patches_fn(
            is_training,
            split_per_side=FLAGS.splits_per_side,
            patch_jitter=FLAGS.get_flag_value("patch_jitter", 0))
      elif fn_name == "standardization":
        yield get_standardization_preprocess()
      elif fn_name == "rotate":
        yield get_rotate_preprocess()

      # Below this line specific combos decomposed.
      # It would be nice to move them to the configs at some point.

      elif fn_name == "inception_preprocess":
        yield get_inception_preprocess(
            is_training, utils.str2intlist(FLAGS.resize_size, 2))
      else:
        raise ValueError("Not supported preprocessing %s" % fn_name)
Exemple #2
0
    def __init__(self, update_batchnorm_params=True):
        self.update_batchnorm_params = update_batchnorm_params

        split = FLAGS.get_flag_value('train_split', 'train')
        num_samples = datasets.get_count(split)
        steps_per_epoch = num_samples // FLAGS.batch_size

        global_step = tf.train.get_or_create_global_step()
        self.global_step_inc = tf.assign_add(global_step, 1)

        # lr_scale_batch_size defines a canonical batch size that is coupled with
        # the initial learning rate. If actual batch size is not the same as
        # canonical than learning rate is linearly scaled. This is very convinient
        # as this allows to vary batch size without recomputing learning rate.
        lr_factor = 1.0
        if FLAGS.get_flag_value('lr_scale_batch_size', 0):
            lr_factor = FLAGS.batch_size / float(FLAGS.lr_scale_batch_size)

        deps = FLAGS.get_flag_value('decay_epochs', None)
        decay_epochs = utils.str2intlist(deps) if deps else [FLAGS.epochs]

        self.lr = get_lr(
            global_step,
            base_lr=FLAGS.lr * lr_factor,
            steps_per_epoch=steps_per_epoch,
            decay_epochs=decay_epochs,
            lr_decay_factor=FLAGS.get_flag_value('lr_decay_factor', 0.1),
            warmup_epochs=FLAGS.get_flag_value('warmup_epochs', 0))
def serving_input_fn():  # pylint: disable=missing-docstring
  """A serving input fn."""
  input_shape = utils.str2intlist(FLAGS.serving_input_shape)
  image_features = {
      FLAGS.serving_input_key:
          tf.placeholder(dtype=tf.float32, shape=input_shape)}
  return tf.estimator.export.ServingInputReceiver(
      features=image_features, receiver_tensors=image_features)
def serving_input_fn():
    """A serving input fn."""
    input_shape = utils.str2intlist(
        FLAGS.get_flag_value('serving_input_shape', 'None,None,None,3'))
    image_features = {
        FLAGS.get_flag_value('serving_input_key', 'image'):
        tf.placeholder(dtype=tf.float32, shape=input_shape)
    }
    return tf.estimator.export.ServingInputReceiver(
        features=image_features, receiver_tensors=image_features)
Exemple #5
0
    def create_model_fn(is_training):  # pylint: disable=missing-docstring
        input_shape = utils.str2intlist(FLAGS.serving_input_shape)
        img = tf.placeholder(shape=input_shape, dtype=tf.float32)

        # This is an example of calling `apply_model_semi` with only one of the
        # inputs provided. The outputs will simply use the given names:
        end_points, predictions = model_fn(img, is_training)

        # Register both the class output and all endpoints to the hub module.
        hub.add_signature(inputs={'image': img}, outputs=predictions)
        hub.add_signature(inputs={'image': img},
                          outputs=end_points,
                          name='representation')
Exemple #6
0
def get_resize_preprocess(fn_args, is_training):
  # This checks if the string "randomize_method" is present anywhere in the
  # args. If it is, during training, enable randomization, but not during test.
  # That's so that a call can look like `resize(256, randomize_method)` or
  # `resize(randomize_method, 256, 128)` and they all work as expected.
  try:
    fn_args.remove("randomize_method")
    randomize_resize_method = is_training
  except ValueError:
    randomize_resize_method = False
  im_size = utils.str2intlist(fn_args, 2)

  def _resize(image, method, align_corners):

    def _process():
      # The resized_images are of type float32 and might fall outside of range
      # [0, 255].
      resized = tf.cast(
          tf.image.resize_images(
              image, im_size, method, align_corners=align_corners),
          dtype=tf.float32)
      return resized

    return _process

  def _resize_pp(data):
    im = data["image"]

    if randomize_resize_method:
      # pick random resizing method
      r = tf.random_uniform([], 0, 3, dtype=tf.int32)
      im = tf.case({
          tf.equal(r, tf.cast(0, r.dtype)):
              _resize(im, tf.image.ResizeMethod.BILINEAR, True),
          tf.equal(r, tf.cast(1, r.dtype)):
              _resize(im, tf.image.ResizeMethod.NEAREST_NEIGHBOR, True),
          tf.equal(r, tf.cast(2, r.dtype)):
              _resize(im, tf.image.ResizeMethod.BICUBIC, True),
          # NOTE: use align_corners=False for AREA resize, but True for the
          # others. See https://github.com/tensorflow/tensorflow/issues/6720
          tf.equal(r, tf.cast(3, r.dtype)):
              _resize(im, tf.image.ResizeMethod.AREA, False),
      })
    else:
      im = tf.image.resize_images(im, im_size)
    data["image"] = im
    return data

  return _resize_pp
Exemple #7
0
    def expand(fn_name, args):
      if fn_name == "plain_preprocess":
        yield lambda x: x
      elif fn_name == "0_to_1":
        yield get_value_range_preprocess(0, 1)
      elif fn_name == "-1_to_1":
        yield get_value_range_preprocess(-1, 1)
      elif fn_name == "value_range":
        yield get_value_range_preprocess(*map(float, args))
      elif fn_name == "resize":
        yield get_resize_preprocess(args, is_training)
      elif fn_name == "resize_small":
        yield get_resize_small(int(args[0]))
      elif fn_name == "crop":
        yield get_crop(is_training, utils.str2intlist(args, 2))
      elif fn_name == "central_crop":
        yield get_crop(False, utils.str2intlist(args, 2))
      elif fn_name == "multi_crop":
        yield get_multi_crop(utils.str2intlist(args, 2))
      elif fn_name == "inception_crop":
        yield get_inception_crop(is_training)
      elif fn_name == "flip_lr":
        yield get_random_flip_lr(is_training)
      elif fn_name == "hsvnoise":
        # TODO(lbeyer): expose the parameters? Or maybe just a scale parameter?
        yield get_hsvnoise_preprocess(*args)
      elif fn_name == "crop_inception_preprocess_patches":
        npatch = int(args[0])
        size = utils.str2intlist(args[1:], 2)
        yield get_inception_preprocess_patches(is_training, size, npatch)
      elif fn_name == "crop_inception_patches":
        npatch = int(args[0])
        size = utils.str2intlist(args[1:], 2)
        yield get_inception_crop_patches(size, npatch)
      elif fn_name == "to_gray":
        yield get_to_gray_preprocess(float(get(args, 0, 1.0)))
      elif fn_name == "standardize":
        yield get_standardize_preprocess()
      elif fn_name == "rotate":
        yield get_rotate_preprocess()
      elif fn_name == "copy_label":
        yield get_copy_label_preprocess(get(args, 0, "copy_label"))

      # Below this line specific combos decomposed.
      # It would be nice to move them to the configs at some point.

      elif fn_name == "inception_preprocess":
        yield get_inception_preprocess(is_training, utils.str2intlist(args, 2))
      else:
        raise ValueError("Not supported preprocessing %s" % fn_name)
def train_and_eval():
  """Trains a network on (self) supervised data."""
  checkpoint_dir = FLAGS.get_flag_value("checkpoint", FLAGS.workdir)
  tf.gfile.MakeDirs(checkpoint_dir)

  if FLAGS.tpu_name:
    cluster = TPUClusterResolver(tpu=[FLAGS.tpu_name])
  else:
    cluster = None

  # tf.logging.info("master: %s", master)
  config = RunConfig(
      model_dir=checkpoint_dir,
      tf_random_seed=FLAGS.random_seed,
      cluster=cluster,
      keep_checkpoint_max=None,
      save_checkpoints_steps=FLAGS.save_checkpoints_steps,
      tpu_config=TPUConfig(iterations_per_loop=TPU_ITERATIONS_PER_LOOP))

  # Optionally resume from a stored checkpoint.
  if FLAGS.path_to_initial_ckpt:
    warm_start_from = tf.estimator.WarmStartSettings(
        ckpt_to_initialize_from=FLAGS.path_to_initial_ckpt,
        # The square bracket is important for loading all the
        # variables from GLOBAL_VARIABLES collection.
        # See https://www.tensorflow.org/api_docs/python/tf/estimator/WarmStartSettings  # pylint: disable=line-too-long
        # section vars_to_warm_start for more details.
        vars_to_warm_start=[FLAGS.vars_to_restore]
    )
  else:
    warm_start_from = None

  # The global batch-sizes are passed to the TPU estimator, and it will pass
  # along the local batch size in the model_fn's `params` argument dict.
  estimator = TPUEstimator(
      model_fn=semi_supervised.get_model(FLAGS.task),
      model_dir=checkpoint_dir,
      config=config,
      use_tpu=FLAGS.tpu_name is not None,
      train_batch_size=FLAGS.batch_size,
      eval_batch_size=FLAGS.get_flag_value("eval_batch_size", FLAGS.batch_size),
      warm_start_from=warm_start_from
  )

  if FLAGS.run_eval:
    data_fn = functools.partial(
        datasets.get_data,
        split_name=FLAGS.val_split,
        preprocessing=FLAGS.get_flag_value("preprocessing_eval",
                                           FLAGS.preprocessing),
        is_training=False,
        shuffle=False,
        num_epochs=1,
        drop_remainder=True)

    # Contrary to what the documentation claims, the `train` and the
    # `evaluate` functions NEED to have `max_steps` and/or `steps` set and
    # cannot make use of the iterator's end-of-input exception, so we need
    # to do some math for that here.
    num_samples = datasets.get_count(FLAGS.val_split)
    num_steps = num_samples // FLAGS.get_flag_value("eval_batch_size",
                                                    FLAGS.batch_size)
    tf.logging.info("val_steps: %d", num_steps)

    for checkpoint in checkpoints_iterator(
        estimator.model_dir, timeout=FLAGS.eval_timeout_mins * 60):

      result_dict_val = estimator.evaluate(
          checkpoint_path=checkpoint, input_fn=data_fn, steps=num_steps)

      hub_exporter = hub.LatestModuleExporter("hub", serving_input_fn)
      hub_exporter.export(
          estimator,
          os.path.join(checkpoint_dir, "export/hub"),
          checkpoint)
      # This is here instead of using the above `checkpoints_iterator`'s
      # `timeout_fn` param, because that would wait forever on failed
      # trainers which will never create this file.
      if tf.gfile.Exists(os.path.join(FLAGS.workdir, "TRAINING_IS_DONE")):
        break

    # Evaluates the latest checkpoint on validation set.
    result_dict_val = estimator.evaluate(input_fn=data_fn, steps=num_steps)
    tf.logging.info(result_dict_val)

    # Optionally evaluates the latest checkpoint on test set.
    if FLAGS.test_split:
      data_fn = functools.partial(
          datasets.get_data,
          split_name=FLAGS.test_split,
          preprocessing=FLAGS.get_flag_value("preprocessing_eval",
                                             FLAGS.preprocessing),
          is_training=False,
          shuffle=False,
          num_epochs=1,
          drop_remainder=True)
      num_samples = datasets.get_count(FLAGS.test_split)
      num_steps = num_samples // FLAGS.get_flag_value("eval_batch_size",
                                                      FLAGS.batch_size)
      result_dict_test = estimator.evaluate(input_fn=data_fn, steps=num_steps)
      tf.logging.info(result_dict_test)
    return result_dict_val

  else:
    train_data_fn = functools.partial(
        datasets.get_data,
        split_name=FLAGS.train_split,
        preprocessing=FLAGS.preprocessing,
        is_training=True,
        num_epochs=None,  # read data indefenitely for training
        drop_remainder=True)

    # We compute the number of steps and make use of Estimator's max_steps
    # arguments instead of relying on the Dataset's iterator to run out after
    # a number of epochs so that we can use "fractional" epochs, which are
    # used by regression tests. (And because TPUEstimator needs it anyways.)
    num_samples = datasets.get_count(FLAGS.train_split)
    if FLAGS.num_supervised_examples:
      num_samples = FLAGS.num_supervised_examples
    # Depending on whether we drop the last batch each epoch or only at the
    # ver end, this should be ordered differently for rounding.
    updates_per_epoch = num_samples // FLAGS.batch_size
    epochs = utils.str2intlist(FLAGS.schedule, strict_int=False)[-1]
    num_steps = int(math.ceil(epochs * updates_per_epoch))
    tf.logging.info("train_steps: %d", num_steps)

    return estimator.train(
        train_data_fn,
        max_steps=num_steps)
def creates_estimator_model(images, labels, perms, num_classes, mode):
    """Creates EstimatorSpec for the patch based self supervised models.

  Args:
    images: images
    labels: self supervised labels (class indices)
    perms: patch permutations
    num_classes: number of different permutations
    mode: model's mode: training, eval or prediction

  Returns:
    EstimatorSpec
  """
    print('   +++ Mode: %s, images: %s, labels: %s' % (mode, images, labels))

    images = tf.reshape(images, shape=[-1] + images.get_shape().as_list()[-3:])
    if mode in [tf.estimator.ModeKeys.TRAIN, tf.estimator.ModeKeys.EVAL]:
        with tf.variable_scope('module'):
            image_fn = lambda: images
            logits = apply_model(
                image_fn=image_fn,
                is_training=(mode == tf.estimator.ModeKeys.TRAIN),
                num_outputs=num_classes,
                perms=perms,
                make_signature=False)
    else:
        input_shape = utils.str2intlist(
            FLAGS.get_flag_value('serving_input_shape', 'None,None,None,3'))
        image_fn = lambda: tf.placeholder(  # pylint: disable=g-long-lambda
            shape=input_shape,
            dtype=tf.float32)

        apply_model_function = functools.partial(apply_model,
                                                 image_fn=image_fn,
                                                 num_outputs=num_classes,
                                                 perms=perms,
                                                 make_signature=True)

        tf_hub_module_spec = hub.create_module_spec(
            apply_model_function, [(utils.TAGS_IS_TRAINING, {
                'is_training': True
            }), (set(), {
                'is_training': False
            })],
            drop_collections=['summaries'])
        tf_hub_module = hub.Module(tf_hub_module_spec,
                                   trainable=False,
                                   tags=set())
        hub.register_module_for_export(tf_hub_module, export_name='module')
        logits = tf_hub_module(images)
        return make_estimator(mode, predictions=logits)

    # build loss and accuracy
    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels,
                                                          logits=logits)
    loss = tf.reduce_mean(loss)

    eval_metrics = (
        lambda labels, logits: {  # pylint: disable=g-long-lambda
            'accuracy':
            tf.metrics.accuracy(labels=labels,
                                predictions=tf.argmax(logits, axis=-1))
        },
        [labels, logits])
    return make_estimator(mode, loss, eval_metrics, logits)
Exemple #10
0
def model_fn(data, mode):
    """Produces a loss for the rotation task.

  Args:
    data: Dict of inputs containing, among others, "image" and "label."
    mode: model's mode: training, eval or prediction

  Returns:
    EstimatorSpec
  """
    num_angles = 4
    images = data['image']

    if mode in [tf.estimator.ModeKeys.TRAIN, tf.estimator.ModeKeys.EVAL]:
        images = tf.reshape(images, [-1] + images.get_shape().as_list()[-3:])
        with tf.variable_scope('module'):
            image_fn = lambda: images
            logits = apply_model(
                image_fn=image_fn,
                is_training=(mode == tf.estimator.ModeKeys.TRAIN),
                num_outputs=num_angles,
                make_signature=False)
    else:
        input_shape = utils.str2intlist(
            FLAGS.get_flag_value('serving_input_shape', 'None,None,None,3'))
        image_fn = lambda: tf.placeholder(
            shape=input_shape,  # pylint: disable=g-long-lambda
            dtype=tf.float32)
        apply_model_function = functools.partial(apply_model,
                                                 image_fn=image_fn,
                                                 num_outputs=num_angles,
                                                 make_signature=True)
        tf_hub_module_spec = hub.create_module_spec(apply_model_function,
                                                    [(utils.TAGS_IS_TRAINING, {
                                                        'is_training': True
                                                    }),
                                                     (set(), {
                                                         'is_training': False
                                                     })])
        tf_hub_module = hub.Module(tf_hub_module_spec,
                                   trainable=False,
                                   tags=set())
        hub.register_module_for_export(tf_hub_module, export_name='module')
        logits = tf_hub_module(images)

        return trainer.make_estimator(mode, predictions=logits)

    labels = tf.reshape(data['label'], [-1])

    # build loss and accuracy
    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=labels,
                                                          logits=logits)
    loss = tf.reduce_mean(loss)

    eval_metrics = (
        lambda labels, logits: {  # pylint: disable=g-long-lambda
            'accuracy':
            tf.metrics.accuracy(labels=labels,
                                predictions=tf.argmax(logits, axis=-1))
        },
        [labels, logits])
    return trainer.make_estimator(mode, loss, eval_metrics, logits)