Beispiel #1
0
 def evaluate(post,
              output_dir,
              evaluation_fn=gin.REQUIRED,
              random_seed=gin.REQUIRED,
              name=""):
     experiment_timer = time.time()
     assert post == 'mean' or post == 'sampled'
     results_dict = evaluation_fn(
         dataset,
         mean_rep if post == 'mean' else sample_rep,
         random_state=np.random.RandomState(random_seed))
     results_dict["elapsed_time"] = time.time() - experiment_timer
     results.update_result_directory(output_dir, "evaluation", results_dict)
def train(model_dir,
          overwrite=False,
          model=gin.REQUIRED,
          training_steps=gin.REQUIRED,
          random_seed=gin.REQUIRED,
          batch_size=gin.REQUIRED,
          eval_steps=1000,
          name="",
          model_num=None):
  """Trains the estimator and exports the snapshot and the gin config.

  The use of this function requires the gin binding 'dataset.name' to be
  specified as that determines the data set used for training.

  Args:
    model_dir: String with path to directory where model output should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    model: GaussianEncoderModel that should be trained and exported.
    training_steps: Integer with number of training steps.
    random_seed: Integer with random seed used for training.
    batch_size: Integer with the batch size.
    eval_steps: Optional integer with number of steps used for evaluation.
    name: Optional string with name of the model (can be used to name models).
    model_num: Optional integer with model number (can be used to identify
      models).
  """
  # We do not use the variables 'name' and 'model_num'. Instead, they can be
  # used to name results as they will be part of the saved gin config.
  del name, model_num

  # Delete the output directory if it already exists.
  if tf.gfile.IsDirectory(model_dir):
    if overwrite:
      tf.gfile.DeleteRecursively(model_dir)
    else:
      raise ValueError("Directory already exists and overwrite is False.")

  # Create a numpy random state. We will sample the random seeds for training
  # and evaluation from this.
  random_state = np.random.RandomState(random_seed)

  # Obtain the dataset.
  dataset = named_data.get_named_ground_truth_data()

  # We create a TPUEstimator based on the provided model. This is primarily so
  # that we could switch to TPU training in the future. For now, we train
  # locally on GPUs.
  run_config = tf.contrib.tpu.RunConfig(
      tf_random_seed=random_seed,
      keep_checkpoint_max=1,
      tpu_config=tf.contrib.tpu.TPUConfig(iterations_per_loop=500))
  tpu_estimator = tf.contrib.tpu.TPUEstimator(
      use_tpu=False,
      model_fn=model.model_fn,
      model_dir=os.path.join(model_dir, "tf_checkpoint"),
      train_batch_size=batch_size,
      eval_batch_size=batch_size,
      config=run_config)

  # Set up time to keep track of elapsed time in results.
  experiment_timer = time.time()

  # Do the actual training.
  tpu_estimator.train(
      input_fn=_make_input_fn(dataset, random_state.randint(2**16)),
      steps=training_steps)

  # Save model as a TFHub module.
  output_shape = named_data.get_named_ground_truth_data().observation_shape
  module_export_path = os.path.join(model_dir, "tfhub")
  gaussian_encoder_model.export_as_tf_hub(model, output_shape,
                                          tpu_estimator.latest_checkpoint(),
                                          module_export_path)

  # Save the results. The result dir will contain all the results and config
  # files that we copied along, as we progress in the pipeline. The idea is that
  # these files will be available for analysis at the end.
  results_dict = tpu_estimator.evaluate(
      input_fn=_make_input_fn(
          dataset, random_state.randint(2**16), num_batches=eval_steps))
  results_dir = os.path.join(model_dir, "results")
  results_dict["elapsed_time"] = time.time() - experiment_timer
  results.update_result_directory(results_dir, "train", results_dict)
Beispiel #3
0
def evaluate(model_dir,
             output_dir,
             overwrite=False,
             evaluation_fn=gin.REQUIRED,
             random_seed=gin.REQUIRED,
             name="",
             eval_pytorch=False):
    """Loads a representation TFHub module and computes disentanglement metrics.

    Args:
      model_dir: String with path to directory where the representation function
        is saved.
      output_dir: String with the path where the results should be saved.
      overwrite: Boolean indicating whether to overwrite output directory.
      evaluation_fn: Function used to evaluate the representation (see metrics/
        for examples).
      random_seed: Integer with random seed used for training.
      name: Optional string with name of the metric (can be used to name metrics).
    """
    # We do not use the variable 'name'. Instead, it can be used to name scores
    # as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Set up time to keep track of elapsed time in results.
    experiment_timer = time.time()

    try:
        # Automatically set the proper data set if necessary. We replace the active
        # gin config as this will lead to a valid gin config file where the data set
        # is present.
        if gin.query_parameter("dataset.name") == "auto":
            # Obtain the dataset name from the gin config of the previous step.
            gin_config_file = os.path.join(model_dir, "results", "gin",
                                           "postprocess.gin")
            gin_dict = results.gin_dict(gin_config_file)
            with gin.unlock_config():
                gin.bind_parameter("dataset.name",
                                   gin_dict["dataset.name"].replace("'", ""))
        dataset = named_data.get_named_ground_truth_data()
    except NotFoundError:
        # If we did not train with disentanglement_lib, there is no "previous step",
        # so we'll have to rely on the environment variable.
        if gin.query_parameter("dataset.name") == "auto":
            with gin.unlock_config():
                gin.bind_parameter("dataset.name", get_dataset_name())
        dataset = named_data.get_named_ground_truth_data()

    eval_tf = True
    if eval_pytorch and os.path.exists(
            os.path.join(model_dir, 'pytorch_model.pt')):
        eval_tf = False

    if os.path.exists(os.path.join(model_dir, 'tfhub')) and eval_tf:
        # Path to TFHub module of previously trained representation.
        module_path = os.path.join(model_dir, "tfhub")
        # Evaluate results with tensorflow
        results_dict = _evaluate_with_tensorflow(module_path, evaluation_fn,
                                                 dataset, random_seed)
    elif os.path.exists(os.path.join(model_dir, 'pytorch_model.pt')):
        # Path to Pytorch JIT Module of previously trained representation.
        module_path = os.path.join(model_dir, 'pytorch_model.pt')
        # Evaluate results with pytorch
        results_dict = _evaluate_with_pytorch(module_path, evaluation_fn,
                                              dataset, random_seed)
    elif os.path.exists(os.path.join(model_dir, 'python_model.dill')):
        # Path to the dilled function
        module_path = os.path.join(model_dir, 'python_model.dill')
        # Evaluate results with numpy
        results_dict = _evaluate_with_numpy(module_path, evaluation_fn,
                                            dataset, random_seed)
    else:
        raise RuntimeError(
            "`model_dir` must contain either a pytorch or a TFHub model.")

    # Save the results (and all previous results in the pipeline) on disk.
    original_results_dir = os.path.join(model_dir, "results")
    results_dir = os.path.join(output_dir, "results")
    results_dict["elapsed_time"] = time.time() - experiment_timer
    results.update_result_directory(results_dir, "evaluation", results_dict,
                                    original_results_dir)
Beispiel #4
0
def evaluate(model_dir,
             output_dir,
             overwrite=False,
             postprocess_fn=gin.REQUIRED,
             evaluation_fn=gin.REQUIRED,
             random_seed=gin.REQUIRED,
             pca_components=gin.REQUIRED,
             name=""):
    """Loads a trained Gaussian encoder and decoder.

  Args:
    model_dir: String with path to directory where the model is saved.
    output_dir: String with the path where the representation should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    postprocess_fn: Function used to extract the representation (see methods.py
      for examples).
    random_seed: Integer with random seed used for postprocessing (may be
      unused).
    name: Optional string with name of the representation (can be used to name
      representations).
  """
    # We do not use the variable 'name'. Instead, it can be used to name
    # representations as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Set up timer to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Automatically set the proper data set if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the data set
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(model_dir, "results", "gin",
                                       "train.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))
    dataset = named_data.get_named_ground_truth_data()

    # Path to TFHub module of previously trained model.
    module_path = os.path.join(model_dir, "tfhub")
    with hub.eval_function_for_module(module_path) as f:

        def _gaussian_encoder(x):
            """Encodes images using trained model."""
            # Push images through the TFHub module.
            output = f(dict(images=x),
                       signature="gaussian_encoder",
                       as_dict=True)
            # Convert to numpy arrays and return.
            return np.array(output["mean"]), np.array(output["logvar"])

        def _decoder(z):
            """Encodes images using trained model."""
            # Push images through the TFHub module.
            output = f(dict(latent_vectors=z),
                       signature="decoder",
                       as_dict=True)
            # Convert to numpy arrays and return.
            return np.array(output['images'])

        # Run the postprocessing function which returns a transformation function
        # that can be used to create the representation from the mean and log
        # variance of the Gaussian distribution given by the encoder. Also returns
        # path to a checkpoint if the transformation requires variables.
        transform_fn, transform_checkpoint_path = postprocess_fn(
            dataset, _gaussian_encoder, np.random.RandomState(random_seed),
            output_dir)

        print('\n\n\n Calculating recall')
        # Computes scores of the representation based on the evaluation_fn.
        if _has_kwarg_or_kwargs(evaluation_fn, "artifact_dir"):
            artifact_dir = os.path.join(model_dir, "artifacts")
            results_dict_list = evaluation_fn(
                dataset,
                _gaussian_encoder,
                transform_fn,
                _decoder,
                random_state=np.random.RandomState(random_seed),
                artifact_dir=artifact_dir)
        else:
            # Legacy code path to allow for old evaluation metrics.
            warnings.warn(
                "Evaluation function does not appear to accept an"
                " `artifact_dir` argument. This may not be compatible with "
                "future versions.", DeprecationWarning)
            results_dict_list = evaluation_fn(
                dataset,
                _gaussian_encoder,
                transform_fn,
                _decoder,
                random_state=np.random.RandomState(random_seed))

    # Save the results (and all previous results in the pipeline) on disk.
    for results_dict, pca_comp in list(zip(results_dict_list, pca_components)):
        results_dir = os.path.join(output_dir, "results")
        results_dict["elapsed_time"] = time.time() - experiment_timer
        filename = "evaluation_pca_{}comp".format(pca_comp)
        results.update_result_directory(results_dir, filename, results_dict)
Beispiel #5
0
def evaluate(model_dirs,
             output_dir,
             evaluation_fn=gin.REQUIRED,
             random_seed=gin.REQUIRED,
             name=""):
    """Loads a trained estimator and evaluates it according to beta-VAE metric."""
    # The name will be part of the gin config and can be used to tag results.
    del name

    # Set up time to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Automatically set the proper dataset if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the dataset
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(model_dirs[0], "results", "gin",
                                       "train.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            print(gin_dict["dataset.name"])
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))

    output_dir = os.path.join(output_dir)
    if tf.io.gfile.isdir(output_dir):
        tf.io.gfile.rmtree(output_dir)

    dataset = named_data.get_named_ground_truth_data()

    with contextlib.ExitStack() as stack:
        representation_functions = []
        eval_functions = [
            stack.enter_context(
                hub.eval_function_for_module(os.path.join(model_dir, "tfhub")))
            for model_dir in model_dirs
        ]
        for f in eval_functions:

            def _representation_function(x, f=f):
                def compute_gaussian_kl(z_mean, z_logvar):
                    return np.mean(
                        0.5 *
                        (np.square(z_mean) + np.exp(z_logvar) - z_logvar - 1),
                        axis=0)

                encoding = f(dict(images=x),
                             signature="gaussian_encoder",
                             as_dict=True)

                return np.array(encoding["mean"]), compute_gaussian_kl(
                    np.array(encoding["mean"]), np.array(encoding["logvar"]))

            representation_functions.append(_representation_function)

        results_dict = evaluation_fn(
            dataset,
            representation_functions,
            random_state=np.random.RandomState(random_seed))

    original_results_dir = os.path.join(model_dirs[0], "results")
    results_dir = os.path.join(output_dir, "results")
    results_dict["elapsed_time"] = time.time() - experiment_timer
    results.update_result_directory(results_dir, "evaluation", results_dict,
                                    original_results_dir)
Beispiel #6
0
def reason(
    input_dir,
    output_dir,
    overwrite=False,
    model=gin.REQUIRED,
    num_iterations=gin.REQUIRED,
    training_steps_per_iteration=gin.REQUIRED,
    eval_steps_per_iteration=gin.REQUIRED,
    random_seed=gin.REQUIRED,
    batch_size=gin.REQUIRED,
    name="",
):
    """Trains the estimator and exports the snapshot and the gin config.

  The use of this function requires the gin binding 'dataset.name' to be
  specified if a model is trained from scratch as that determines the data set
  used for training.

  Args:
    input_dir: String with path to directory where the representation function
      is saved.
    output_dir: String with the path where the results should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    model: GaussianEncoderModel that should be trained and exported.
    num_iterations: Integer with number of training steps.
    training_steps_per_iteration: Integer with number of training steps per
      iteration.
    eval_steps_per_iteration: Integer with number of validationand test steps
      per iteration.
    random_seed: Integer with random seed used for training.
    batch_size: Integer with the batch size.
    name: Optional string with name of the model (can be used to name models).
  """
    # We do not use the variable 'name'. Instead, it can be used to name results
    # as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Create a numpy random state. We will sample the random seeds for training
    # and evaluation from this.
    random_state = np.random.RandomState(random_seed)

    # Automatically set the proper data set if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the data set
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        if input_dir is None:
            raise ValueError(
                "Cannot automatically infer data set for methods with"
                " no prior model directory.")
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(input_dir, "results", "gin",
                                       "postprocess.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))
    dataset = pgm_data.get_pgm_dataset()

    # Set the path to the TFHub embedding if we are training based on a
    # pre-trained embedding..
    if input_dir is not None:
        tfhub_dir = os.path.join(input_dir, "tfhub")
        with gin.unlock_config():
            gin.bind_parameter("HubEmbedding.hub_path", tfhub_dir)

    # We create a TPUEstimator based on the provided model. This is primarily so
    # that we could switch to TPU training in the future. For now, we train
    # locally on GPUs.
    run_config = contrib_tpu.RunConfig(
        tf_random_seed=random_seed,
        keep_checkpoint_max=1,
        tpu_config=contrib_tpu.TPUConfig(iterations_per_loop=500))
    tpu_estimator = contrib_tpu.TPUEstimator(use_tpu=False,
                                             model_fn=model.model_fn,
                                             model_dir=os.path.join(
                                                 output_dir, "tf_checkpoint"),
                                             train_batch_size=batch_size,
                                             eval_batch_size=batch_size,
                                             config=run_config)

    # Set up time to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Create a dictionary to keep track of all relevant information.
    results_dict_of_dicts = {}
    validation_scores = []
    all_dicts = []

    for i in range(num_iterations):
        steps_so_far = i * training_steps_per_iteration
        tf.logging.info("Training to %d steps.", steps_so_far)
        # Train the model for the specified steps.
        tpu_estimator.train(input_fn=dataset.make_input_fn(
            random_state.randint(2**32)),
                            steps=training_steps_per_iteration)
        # Compute validation scores used for model selection.
        validation_results = tpu_estimator.evaluate(
            input_fn=dataset.make_input_fn(
                random_state.randint(2**32),
                num_batches=eval_steps_per_iteration))
        validation_scores.append(validation_results["accuracy"])
        tf.logging.info("Validation results %s", validation_results)
        # Compute test scores for final results.
        test_results = tpu_estimator.evaluate(input_fn=dataset.make_input_fn(
            random_state.randint(2**32), num_batches=eval_steps_per_iteration),
                                              name="test")
        dict_at_iteration = results.namespaced_dict(val=validation_results,
                                                    test=test_results)
        results_dict_of_dicts["step{}".format(
            steps_so_far)] = dict_at_iteration
        all_dicts.append(dict_at_iteration)

    # Select the best number of steps based on the validation scores and add it as
    # as a special key to the dictionary.
    best_index = np.argmax(validation_scores)
    results_dict_of_dicts["best"] = all_dicts[best_index]

    # Save the results. The result dir will contain all the results and config
    # files that we copied along, as we progress in the pipeline. The idea is that
    # these files will be available for analysis at the end.
    if input_dir is not None:
        original_results_dir = os.path.join(input_dir, "results")
    else:
        original_results_dir = None
    results_dict = results.namespaced_dict(**results_dict_of_dicts)
    results_dir = os.path.join(output_dir, "results")
    results_dict["elapsed_time"] = time.time() - experiment_timer
    results.update_result_directory(results_dir, "abstract_reasoning",
                                    results_dict, original_results_dir)
Beispiel #7
0
def evaluate(model_dir,
             output_dir,
             overwrite=False,
             evaluation_fn=gin.REQUIRED,
             random_seed=gin.REQUIRED,
             name=""):
    """Loads a representation TFHub module and computes disentanglement metrics.

  Args:
    model_dir: String with path to directory where the representation function
      is saved.
    output_dir: String with the path where the results should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    evaluation_fn: Function used to evaluate the representation (see metrics/
      for examples).
    random_seed: Integer with random seed used for training.
    name: Optional string with name of the metric (can be used to name metrics).
  """
    # We do not use the variable 'name'. Instead, it can be used to name scores
    # as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Set up time to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Automatically set the proper data set if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the data set
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(model_dir, "results", "gin",
                                       "postprocess.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))
    dataset = named_data.get_named_ground_truth_data()

    # Path to TFHub module of previously trained representation.
    module_path = os.path.join(model_dir, "tfhub")
    with hub.eval_function_for_module(module_path) as f:

        def _representation_function(x):
            """Computes representation vector for input images."""
            output = f(dict(images=x),
                       signature="representation",
                       as_dict=True)
            return np.array(output["default"])

        # Computes scores of the representation based on the evaluation_fn.
        if _has_kwarg_or_kwargs(evaluation_fn, "artifact_dir"):
            artifact_dir = os.path.join(model_dir, "artifacts")
            results_dict = evaluation_fn(
                dataset,
                _representation_function,
                random_state=np.random.RandomState(random_seed),
                artifact_dir=artifact_dir)
        else:
            # Legacy code path to allow for old evaluation metrics.
            warnings.warn(
                "Evaluation function does not appear to accept an"
                " `artifact_dir` argument. This may not be compatible with "
                "future versions.", DeprecationWarning)
            results_dict = evaluation_fn(
                dataset,
                _representation_function,
                random_state=np.random.RandomState(random_seed))

    # Save the results (and all previous results in the pipeline) on disk.
    original_results_dir = os.path.join(model_dir, "results")
    results_dir = os.path.join(output_dir, "results")
    results_dict["elapsed_time"] = time.time() - experiment_timer
    results.update_result_directory(results_dir, "evaluation", results_dict,
                                    original_results_dir)
def validate(model_dir,
             output_dir,
             overwrite=False,
             validation_fn=gin.REQUIRED,
             random_seed=gin.REQUIRED,
             num_labelled_samples=gin.REQUIRED,
             name=""):
    """Loads a representation TFHub module and computes disentanglement metrics.

  Args:
    model_dir: String with path to directory where the representation function
      is saved.
    output_dir: String with the path where the results should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    validation_fn: Function used to validate the representation (see metrics/
      for examples).
    random_seed: Integer with random seed used for training.
    num_labelled_samples: How many labelled samples are available.
    name: Optional string with name of the metric (can be used to name metrics).
  """
    # We do not use the variable 'name'. Instead, it can be used to name scores
    # as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Set up time to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Automatically set the proper data set if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the data set
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(model_dir, "results", "gin",
                                       "postprocess.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))
    dataset = named_data.get_named_ground_truth_data()
    observations, labels, _ = semi_supervised_utils.sample_supervised_data(
        random_seed, dataset, num_labelled_samples)
    # Path to TFHub module of previously trained representation.
    module_path = os.path.join(model_dir, "tfhub")
    with hub.eval_function_for_module(module_path) as f:

        def _representation_function(x):
            """Computes representation vector for input images."""
            output = f(dict(images=x),
                       signature="representation",
                       as_dict=True)
            return np.array(output["default"])

        # Computes scores of the representation based on the evaluation_fn.
        results_dict = validation_fn(observations, np.transpose(labels),
                                     _representation_function)

    # Save the results (and all previous results in the pipeline) on disk.
    original_results_dir = os.path.join(model_dir, "results")
    results_dir = os.path.join(output_dir, "results")
    results_dict["elapsed_time"] = time.time() - experiment_timer
    results.update_result_directory(results_dir, "validation", results_dict,
                                    original_results_dir)
Beispiel #9
0
def postprocess(model_dir,
                output_dir,
                overwrite=False,
                postprocess_fn=gin.REQUIRED,
                random_seed=gin.REQUIRED,
                name=""):
    """Loads a trained Gaussian encoder and extracts representation.

  Args:
    model_dir: String with path to directory where the model is saved.
    output_dir: String with the path where the representation should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    postprocess_fn: Function used to extract the representation (see methods.py
      for examples).
    random_seed: Integer with random seed used for postprocessing (may be
      unused).
    name: Optional string with name of the representation (can be used to name
      representations).
  """
    # We do not use the variable 'name'. Instead, it can be used to name
    # representations as it will be part of the saved gin config.
    del name

    # Delete the output directory if it already exists.
    if tf.gfile.IsDirectory(output_dir):
        if overwrite:
            tf.gfile.DeleteRecursively(output_dir)
        else:
            raise ValueError(
                "Directory already exists and overwrite is False.")

    # Set up timer to keep track of elapsed time in results.
    experiment_timer = time.time()

    # Automatically set the proper data set if necessary. We replace the active
    # gin config as this will lead to a valid gin config file where the data set
    # is present.
    if gin.query_parameter("dataset.name") == "auto":
        # Obtain the dataset name from the gin config of the previous step.
        gin_config_file = os.path.join(model_dir, "results", "gin",
                                       "train.gin")
        gin_dict = results.gin_dict(gin_config_file)
        with gin.unlock_config():
            gin.bind_parameter("dataset.name",
                               gin_dict["dataset.name"].replace("'", ""))
    dataset = named_data.get_named_ground_truth_data()

    # Path to TFHub module of previously trained model.
    module_path = os.path.join(model_dir, "tfhub")
    with hub.eval_function_for_module(module_path) as f:

        def _gaussian_encoder(x):
            """Encodes images using trained model."""
            # Push images through the TFHub module.
            output = f(dict(images=x),
                       signature="gaussian_encoder",
                       as_dict=True)
            # Convert to numpy arrays and return.
            return {key: np.array(values) for key, values in output.items()}

        # Run the postprocessing function which returns a transformation function
        # that can be used to create the representation from the mean and log
        # variance of the Gaussian distribution given by the encoder. Also returns
        # path to a checkpoint if the transformation requires variables.
        transform_fn, transform_checkpoint_path = postprocess_fn(
            dataset, _gaussian_encoder, np.random.RandomState(random_seed),
            output_dir)

        # Takes the "gaussian_encoder" signature, extracts the representation and
        # then saves under the signature "representation".
        tfhub_module_dir = os.path.join(output_dir, "tfhub")
        convolute_hub.convolute_and_save(module_path, "gaussian_encoder",
                                         tfhub_module_dir, transform_fn,
                                         transform_checkpoint_path,
                                         "representation")

    # We first copy over all the prior results and configs.
    original_results_dir = os.path.join(model_dir, "results")
    results_dir = os.path.join(output_dir, "results")
    results_dict = dict(elapsed_time=time.time() - experiment_timer)
    results.update_result_directory(results_dir, "postprocess", results_dict,
                                    original_results_dir)
Beispiel #10
0
def train(model_dir,
          overwrite=False,
          model=gin.REQUIRED,
          training_steps=gin.REQUIRED,
          unsupervised_data_seed=gin.REQUIRED,
          supervised_data_seed=gin.REQUIRED,
          model_seed=gin.REQUIRED,
          batch_size=gin.REQUIRED,
          num_labelled_samples=gin.REQUIRED,
          train_percentage=gin.REQUIRED,
          name=""):
  """Trains the estimator and exports the snapshot and the gin config.

  The use of this function requires the gin binding 'dataset.name' to be
  specified as that determines the data set used for training.

  Args:
    model_dir: String with path to directory where model output should be saved.
    overwrite: Boolean indicating whether to overwrite output directory.
    model: GaussianEncoderModel that should be trained and exported.
    training_steps: Integer with number of training steps.
    unsupervised_data_seed: Integer with random seed used for the unsupervised
      data.
    supervised_data_seed: Integer with random seed for supervised data.
    model_seed: Integer with random seed used for the model.
      batch_size: Integer with the batch size.
    num_labelled_samples: Integer with number of labelled observations for
      training.
    train_percentage: Fraction of the labelled data to use for training (0,1)
    name: Optional string with name of the model (can be used to name models).
  """
  # We do not use the variable 'name'. Instead, it can be used to name results
  # as it will be part of the saved gin config.
  del name

  # Delete the output directory if necessary.
  if tf.gfile.IsDirectory(model_dir):
    if overwrite:
      tf.gfile.DeleteRecursively(model_dir)
    else:
      raise ValueError("Directory already exists and overwrite is False.")

  # Obtain the dataset.
  dataset = named_data.get_named_ground_truth_data()
  (sampled_observations,
   sampled_factors,
   factor_sizes) = semi_supervised_utils.sample_supervised_data(
       supervised_data_seed, dataset, num_labelled_samples)
  # We instantiate the model class.
  if  issubclass(model, semi_supervised_vae.BaseS2VAE):
    model = model(factor_sizes)
  else:
    model = model()

  # We create a TPUEstimator based on the provided model. This is primarily so
  # that we could switch to TPU training in the future. For now, we train
  # locally on GPUs.
  run_config = tpu_config.RunConfig(
      tf_random_seed=model_seed,
      keep_checkpoint_max=1,
      tpu_config=tpu_config.TPUConfig(iterations_per_loop=500))
  tpu_estimator = TPUEstimator(
      use_tpu=False,
      model_fn=model.model_fn,
      model_dir=model_dir,
      train_batch_size=batch_size,
      eval_batch_size=batch_size,
      config=run_config)

  # Set up time to keep track of elapsed time in results.
  experiment_timer = time.time()
  # Do the actual training.
  tpu_estimator.train(
      input_fn=_make_input_fn(dataset, num_labelled_samples,
                              unsupervised_data_seed, sampled_observations,
                              sampled_factors, train_percentage),
      steps=training_steps)
  # Save model as a TFHub module.
  output_shape = named_data.get_named_ground_truth_data().observation_shape
  module_export_path = os.path.join(model_dir, "tfhub")
  gaussian_encoder_model.export_as_tf_hub(model, output_shape,
                                          tpu_estimator.latest_checkpoint(),
                                          module_export_path)

  # Save the results. The result dir will contain all the results and config
  # files that we copied along, as we progress in the pipeline. The idea is that
  # these files will be available for analysis at the end.
  results_dict = tpu_estimator.evaluate(
      input_fn=_make_input_fn(
          dataset,
          num_labelled_samples,
          unsupervised_data_seed,
          sampled_observations,
          sampled_factors,
          train_percentage,
          num_batches=num_labelled_samples,
          validation=True))
  results_dir = os.path.join(model_dir, "results")
  results_dict["elapsed_time"] = time.time() - experiment_timer
  results.update_result_directory(results_dir, "train", results_dict)