docs: def get_experiment_fn(args):
    """Builds the experiment function for learn_runner.run.
  
    Args:
      args: the command line args
  
    Returns:
      A function that returns a tf.learn experiment object.
    """
  
    def get_experiment(output_dir):
      # Read schema, input features, and transforms.
      schema_path_with_target = os.path.join(args.analysis,
                                             feature_transforms.SCHEMA_FILE)
      features_path = os.path.join(args.analysis,
                                   feature_transforms.FEATURES_FILE)
      stats_path = os.path.join(args.analysis,
                                feature_transforms.STATS_FILE)
  
      schema = read_json_file(schema_path_with_target)
      features = read_json_file(features_path)
      stats = read_json_file(stats_path)
  
      target_column_name = feature_transforms.get_target_name(features)
      if not target_column_name:
        raise ValueError('target missing from features file.')
  
      # Make a copy of the schema file without the target column.
      schema_without_target = [col for col in schema if col['name'] != target_column_name]
      schema_path_without_target = os.path.join(args.job_dir, 'schema_without_target.json')
      file_io.recursive_create_dir(args.job_dir)
      file_io.write_string_to_file(schema_path_without_target,
                                   json.dumps(schema_without_target, indent=2))
  
      # Make list of files to save with the trained model.
      additional_assets_with_target = {
          feature_transforms.FEATURES_FILE: features_path,
          feature_transforms.SCHEMA_FILE: schema_path_with_target}
      additional_assets_without_target = {
          feature_transforms.FEATURES_FILE: features_path,
          feature_transforms.SCHEMA_FILE: schema_path_without_target}
  
      # Get the model to train.
      target_vocab = read_vocab(args, target_column_name)
      estimator = get_estimator(args, output_dir, features, stats, len(target_vocab))
  
      export_strategy_csv_notarget = make_export_strategy(
          args=args,
          keep_target=False,
          assets_extra=additional_assets_without_target,
          features=features,
          schema=schema,
          stats=stats)
      export_strategy_csv_target = make_export_strategy(
          args=args,
          keep_target=True,
          assets_extra=additional_assets_with_target,
          features=features,
          schema=schema,
          stats=stats)
  
      # Build readers for training.
      if args.transform:
        if any(v['transform'] == feature_transforms.IMAGE_TRANSFORM
               for k, v in six.iteritems(features)):
          raise ValueError('"image_to_vec" transform requires transformation step. ' +
                           'Cannot train from raw data.')
  
        input_reader_for_train = feature_transforms.build_csv_transforming_training_input_fn(
            schema=schema,
            features=features,
            stats=stats,
            analysis_output_dir=args.analysis,
            raw_data_file_pattern=args.train,
            training_batch_size=args.train_batch_size,
            num_epochs=args.max_epochs,
            randomize_input=True,
            min_after_dequeue=10,
            reader_num_threads=multiprocessing.cpu_count())
        input_reader_for_eval = feature_transforms.build_csv_transforming_training_input_fn(
            schema=schema,
            features=features,
            stats=stats,
            analysis_output_dir=args.analysis,
            raw_data_file_pattern=args.eval,
            training_batch_size=args.eval_batch_size,
            num_epochs=1,
            randomize_input=False,
            reader_num_threads=multiprocessing.cpu_count())
      else:
        input_reader_for_train = feature_transforms.build_tfexample_transfored_training_input_fn(
            schema=schema,
            features=features,
            analysis_output_dir=args.analysis,
            raw_data_file_pattern=args.train,
            training_batch_size=args.train_batch_size,
            num_epochs=args.max_epochs,
            randomize_input=True,
            min_after_dequeue=10,
            reader_num_threads=multiprocessing.cpu_count())
        input_reader_for_eval = feature_transforms.build_tfexample_transfored_training_input_fn(
            schema=schema,
            features=features,
            analysis_output_dir=args.analysis,
            raw_data_file_pattern=args.eval,
            training_batch_size=args.eval_batch_size,
            num_epochs=1,
            randomize_input=False,
            reader_num_threads=multiprocessing.cpu_count())
  
      if args.early_stopping_num_evals == 0:
        train_monitors = None
      else:
        if is_classification_model(args.model):
          early_stop_monitor = tf.contrib.learn.monitors.ValidationMonitor(
              input_fn=input_reader_for_eval,
              every_n_steps=args.min_eval_frequency,
              early_stopping_rounds=(args.early_stopping_num_evals * args.min_eval_frequency),
              early_stopping_metric='accuracy',
              early_stopping_metric_minimize=False)
        else:
          early_stop_monitor = tf.contrib.learn.monitors.ValidationMonitor(
              input_fn=input_reader_for_eval,
              every_n_steps=args.min_eval_frequency,
              early_stopping_rounds=(args.early_stopping_num_evals * args.min_eval_frequency))
        train_monitors = [early_stop_monitor]
  
      return tf.contrib.learn.Experiment(
          estimator=estimator,
          train_input_fn=input_reader_for_train,
          eval_input_fn=input_reader_for_eval,
          train_steps=args.max_steps,
          train_monitors=train_monitors,
          export_strategies=[export_strategy_csv_notarget, export_strategy_csv_target],
          min_eval_frequency=args.min_eval_frequency,
          eval_steps=None)
  
    # Return a function to create an Experiment.
    return get_experiment