Decodes once.

  Args:
    estimator: tf.estimator.Estimator instance. Used to generate encoded
      predictions.
    problem_name: str. Name of problem.
    hparams: HParams instance. HParams for model training.
    infer_input_fn: zero-arg function. Input function for estimator.
    decode_hp: HParams instance. See decode_hparams() above.
    decode_to_file: str. Prefix for filenames. Used to generated filenames to
      which decoded predictions are written.
    output_dir: str. Output directory. Only used for writing images.
    log_results: bool. If False, return encoded predictions without any
      further processing.
    checkpoint_path: str. Path to load model checkpoint from. If unspecified,
      Estimator's default is used.

  Returns:
    If decode_hp.decode_in_memory is True:
      List of dicts, one per example. Values are either numpy arrays or decoded
      strings.
    If decode_hp.decode_in_memory is False:
      An empty list.

def decode_once(estimator,
                problem_name,
                hparams,
                infer_input_fn,
                decode_hp,
                decode_to_file,
                output_dir,
                log_results=True,
                checkpoint_path=None):
  """Decodes once.

  Args:
    estimator: tf.estimator.Estimator instance. Used to generate encoded
      predictions.
    problem_name: str. Name of problem.
    hparams: HParams instance. HParams for model training.
    infer_input_fn: zero-arg function. Input function for estimator.
    decode_hp: HParams instance. See decode_hparams() above.
    decode_to_file: str. Prefix for filenames. Used to generated filenames to
      which decoded predictions are written.
    output_dir: str. Output directory. Only used for writing images.
    log_results: bool. If False, return encoded predictions without any
      further processing.
    checkpoint_path: str. Path to load model checkpoint from. If unspecified,
      Estimator's default is used.

  Returns:
    If decode_hp.decode_in_memory is True:
      List of dicts, one per example. Values are either numpy arrays or decoded
      strings.
    If decode_hp.decode_in_memory is False:
      An empty list.
  """

  # Get the predictions as an iterable
  predictions = estimator.predict(infer_input_fn,
                                  checkpoint_path=checkpoint_path)

  if not log_results:
    return list(predictions)

  # Prepare output file writers if decode_to_file passed
  decode_to_file = decode_to_file or decode_hp.decode_to_file
  if decode_to_file:
    output_filepath = _decode_filename(decode_to_file, problem_name, decode_hp)
    parts = output_filepath.split(".")
    parts[-1] = "targets"
    target_filepath = ".".join(parts)
    parts[-1] = "inputs"
    input_filepath = ".".join(parts)

    output_file = tf.gfile.Open(output_filepath, "w")
    target_file = tf.gfile.Open(target_filepath, "w")
    input_file = tf.gfile.Open(input_filepath, "w")

  problem_hparams = hparams.problem_hparams
  # Inputs vocabulary is set to targets if there are no inputs in the problem,
  # e.g., for language models where the inputs are just a prefix of targets.
  has_input = "inputs" in problem_hparams.vocabulary
  inputs_vocab_key = "inputs" if has_input else "targets"
  inputs_vocab = problem_hparams.vocabulary[inputs_vocab_key]
  targets_vocab = problem_hparams.vocabulary["targets"]

  num_eval_samples = 0

  # all_outputs[i][j] = (input: str, output: str, target: str). Input,
  # decoded output, and target strings for example i, beam rank j.
  all_outputs = []
  for num_predictions, prediction in enumerate(predictions):
    num_eval_samples += 1
    num_predictions += 1
    inputs = prediction.get("inputs")
    targets = prediction.get("targets")
    outputs = prediction.get("outputs")

    # Log predictions
    decoded_outputs = []  # [(str, str, str)]. See all_outputs above.
    if decode_hp.decode_in_memory:
      all_outputs.append(decoded_outputs)
    decoded_scores = []

    if decode_hp.return_beams:
      output_beams = np.split(outputs, decode_hp.beam_size, axis=0)
      scores = None
      if "scores" in prediction:
        scores = np.split(prediction["scores"], decode_hp.beam_size, axis=0)
      for i, beam in enumerate(output_beams):
        tf.logging.info("BEAM %d:" % i)
        score = scores and scores[i]
        decoded = log_decode_results(
            inputs,
            beam,
            problem_name,
            num_predictions,
            inputs_vocab,
            targets_vocab,
            save_images=decode_hp.save_images,
            output_dir=output_dir,
            identity_output=decode_hp.identity_output,
            targets=targets,
            log_results=log_results)
        decoded_outputs.append(decoded)
        if decode_hp.write_beam_scores:
          decoded_scores.append(score)
    else:
      decoded = log_decode_results(
          inputs,
          outputs,
          problem_name,
          num_predictions,
          inputs_vocab,
          targets_vocab,
          save_images=decode_hp.save_images,
          output_dir=output_dir,
          identity_output=decode_hp.identity_output,
          targets=targets,
          log_results=log_results,
          skip_eos_postprocess=decode_hp.skip_eos_postprocess)
      decoded_outputs.append(decoded)

    # Write out predictions if decode_to_file passed
    if decode_to_file:
      for i, (d_input, d_output, d_target) in enumerate(decoded_outputs):
        # Skip if all padding
        if d_input and re.match("^({})+$".format(text_encoder.PAD), d_input):
          continue
        beam_score_str = ""
        if decode_hp.write_beam_scores:
          beam_score_str = "\t%.2f" % decoded_scores[i]
        output_file.write(str(d_output) + beam_score_str + decode_hp.delimiter)
        target_file.write(str(d_target) + decode_hp.delimiter)
        input_file.write(str(d_input) + decode_hp.delimiter)

    if (decode_hp.num_samples >= 0 and
        num_predictions >= decode_hp.num_samples):
      break

  mlperf_log.transformer_print(key=mlperf_log.EVAL_SIZE,
                               value=num_eval_samples,
                               hparams=hparams)

  if decode_to_file:
    output_file.close()
    target_file.close()
    input_file.close()

  return all_outputs