title: building a tf.estimator input_fn: feature is not in features dictionary
body: <p>I have a corpus of records that represent matchups in a video game. I want to feed this to a <code>tf.estimator.DNNClassifier</code>. </p>
  
  <p>The records contain text representations of the 5 heroes on team 0 and the 5 heroes on team 1, the map the game was played on, and the winner of the game. I want to represent these three features as three sparse vectors.</p>
  
  <p>I'm not using pandas or numpy right now. I would prefer to keep it as simple as possible for the time being, until I can elaborate my tf knowledge. (But no simpler!). </p>
  
  <p>Perhaps the best way to ask the question is to show what I have and ask for help filling in the blank, at <code>make_input_fn</code></p>
  
  <pre><code>import tensorflow as tf
  import packunpack as source
  import tempfile
  from collections import namedtuple
  
  GameRecord = namedtuple('GameRecord', 'team_0 team_1 game_map winner')
  def parse(line):
      parts = line.rstrip().split("\t")
      return GameRecord(
          game_map = parts[1], 
          team_0 = parts[2].split(","), 
          team_1 = parts[3].split(","), 
          winner = int(parts[4]))
  
  def conjugate(record):
      return GameRecord(
          team_0 = record.team_1, 
          team_1 = record.team_0, 
          game_map = record.game_map, 
          winner = 0 if record.winner == 1 else 1)
  
  def sparse_team(team):
      return tf.SparseTensor(indices=team, values = [1] * len(team), dense_shape=[len(source.heroes_array)])
  
  def sparse_map(i):
      return tf.SparseTensor(indices=[i], values = [1], dense_shape=[len(source.maps_array)])
  
  def make_input_fn(filename, shuffle = True, add_conjugate_games = True):
      def _fn():
          records = []
          with open(filename, "r") as raw:
              i = 0
              for line in raw:
                  record = parse(line)
                  records.append(record)
                  if add_conjugate_games:
                      # the team_0 and team_1 designations are arbitrary, and so the same inference should be drawn from a game and its "conjugate" game
                      records.append(conjugate(record))
  
          team_0s = map(lambda r: sparse_team(r.team_0), records)
          team_1s = map(lambda r: sparse_team(r.team_1), records)
          maps = map(lambda r: sparse_map(r.game_map), records)
          winners = map(lambda r: tf.constant([r.winner]), records)
  
          return ({
                      team_0: team_0s,
                      team_1: team_1s,
                      game_map: maps,
                  }, 
                  winners)
          #Please help me finish this function?
  
      return _fn
  
  team_0 = tf.feature_column.embedding_column(
      tf.feature_column.categorical_column_with_vocabulary_list("team_0", source.heroes_array), 1)
  team_1 = tf.feature_column.embedding_column(
      tf.feature_column.categorical_column_with_vocabulary_list("team_1", source.heroes_array), 1)
  game_map = tf.feature_column.embedding_column(
      tf.feature_column.categorical_column_with_vocabulary_list("game_map", source.maps_array), 1)
  
  model_dir = tempfile.mkdtemp()
  m = tf.estimator.DNNClassifier(
      model_dir=model_dir,
      hidden_units = [1024, 512, 256], 
      feature_columns=[team_0, team_1, game_map])
  
  def main():
      m.train(input_fn=make_input_fn("validation.txt"))
  
  if __name__ == "__main__":
      main()
  </code></pre>
  
  <p>I've been all over the docs today, but all of the code examples I can find show how to feed pandas and numpy data structures into input_fn, and obsure the underlying mechanics of the process by calling out to helper functions that don't work for me.</p>
  
  <p>(e.g.,   <a href="https://www.tensorflow.org/get_started/input_fn" rel="nofollow noreferrer">https://www.tensorflow.org/get_started/input_fn</a>
  and 
  <a href="https://www.tensorflow.org/tutorials/wide" rel="nofollow noreferrer">https://www.tensorflow.org/tutorials/wide</a>)</p>
  
  <p>tf version 1.4.0-dev20171008</p>
  
  <p>When I run I get this stack trace. I think it doesn't like the return value from <code>_fn</code>. But that dictionary does have the names of the features that I gave to the model AFAICT.</p>
  
  <pre><code> File "estimator.py", line 72, in &lt;module&gt;
      main()
    File "estimator.py", line 69, in main
      m.train(input_fn=make_input_fn("validation.txt"))
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/estimator.py", line 302, in train
      loss = self._train_model(input_fn, hooks, saving_listeners)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/estimator.py", line 711, in _train_model
      features, labels, model_fn_lib.ModeKeys.TRAIN, self.config)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/estimator.py", line 694, in _call_model_fn
      model_fn_results = self._model_fn(features=features, **kwargs)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/canned/dnn.py", line 334, in _model_fn
      config=config)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/canned/dnn.py", line 190, in _dnn_model_fn
      logits = logit_fn(features=features, mode=mode)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/estimator/canned/dnn.py", line 89, in dnn_logit_fn
      features=features, feature_columns=feature_columns)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 230, in input_lay
  er
      trainable=trainable)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 1834, in _get_den
  se_tensor
      inputs, weight_collections=weight_collections, trainable=trainable)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 2119, in _get_spa
  rse_tensors
      return _CategoricalColumn.IdWeightPair(inputs.get(self), None)
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 1533, in get
      transformed = column._transform_feature(self)  # pylint: disable=protected-access
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 2087, in _transfo
  rm_feature
      input_tensor = _to_sparse_input(inputs.get(self.key))
    File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/feature_column/feature_column.py", line 1529, in get
      raise ValueError('Feature {} is not in features dictionary.'.format(key))
  ValueError: Feature team_0 is not in features dictionary.
  </code></pre>