title: 'serving_default' : Classification input must be a single string Tensor
body: <p>I'm building a very simple Classifier. The input data has the following features</p>
  
  <pre><code>job           object
  marital       object
  education     object
  default        int64
  housing        int64
  loan           int64
  contact       object
  dayofmonth    object
  month         object
  duration       int64
  campaign       int64
  pdays          int64
  previous       int64
  poutcome      object
  </code></pre>
  
  <ol>
  <li>First version of the serving function</li>
  </ol>
  
  <pre><code>def serving_input_receiver_fn():
      feature_spec = {
          'job' : tf.placeholder(dtype = tf.string, shape = [None]),
          'marital' : tf.placeholder(dtype = tf.string, shape = [None]),
          'education' : tf.placeholder(dtype = tf.string, shape = [None]),
          'default' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'housing' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'loan' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'contact' : tf.placeholder(dtype = tf.string, shape = [None]),
          'dayofmonth' : tf.placeholder(dtype = tf.string, shape = [None]),
          'month' : tf.placeholder(dtype = tf.string, shape = [None]),
          'duration' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'campaign' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'pdays' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'previous' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'poutcome' : tf.placeholder(dtype = tf.string, shape = [None])
      }
  
      return tf.estimator.export.ServingInputReceiver(features = feature_spec, receiver_tensors = feature_spec)
  </code></pre>
  
  <p>The error is:</p>
  
  <pre><code>INFO:tensorflow:'serving_default' : Classification input must be a single string Tensor; got {'poutcome': &lt;tf.Tensor 'Placeholder_13:0' shape=(?,) dtype=string&gt;, 'campaign': &lt;tf.Tensor 'Placeholder_10:0' shape=(?,) dtype=int64&gt;, 'loan': &lt;tf.Tensor 'Placeholder_5:0' shape=(?,) dtype=int64&gt;, 'month': &lt;tf.Tensor 'Placeholder_8:0' shape=(?,) dtype=string&gt;, 'job': &lt;tf.Tensor 'Placeholder:0' shape=(?,) dtype=string&gt;, 'duration': &lt;tf.Tensor 'Placeholder_9:0' shape=(?,) dtype=int64&gt;, 'education': &lt;tf.Tensor 'Placeholder_2:0' shape=(?,) dtype=string&gt;, 'marital': &lt;tf.Tensor 'Placeholder_1:0' shape=(?,) dtype=string&gt;, 'dayofmonth': &lt;tf.Tensor 'Placeholder_7:0' shape=(?,) dtype=string&gt;, 'default': &lt;tf.Tensor 'Placeholder_3:0' shape=(?,) dtype=int64&gt;, 'pdays': &lt;tf.Tensor 'Placeholder_11:0' shape=(?,) dtype=int64&gt;, 'housing': &lt;tf.Tensor 'Placeholder_4:0' shape=(?,) dtype=int64&gt;, 'contact': &lt;tf.Tensor 'Placeholder_6:0' shape=(?,) dtype=string&gt;, 'previous': &lt;tf.Tensor 'Placeholder_12:0' shape=(?,) dtype=int64&gt;}
  </code></pre>
  
  <p>Then, I changed the serving function to this:</p>
  
  <pre><code>def serving_input_receiver_fn():
      feature_spec = {
          'job': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'marital': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'education': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'default': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'housing': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'loan': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'contact': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'dayofmonth': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'month': tf.FixedLenFeature(shape=[None], dtype=tf.string),
          'duration': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'campaign': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'pdays': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'previous': tf.FixedLenFeature(shape=[None], dtype=tf.int64),
          'poutcome': tf.FixedLenFeature(shape=[None], dtype=tf.string)
      }
  
      serialized_tf_example = tf.compat.v1.placeholder(tf.string, name='input_example_tensor')
      tf_example = tf.io.parse_example(serialized=serialized_tf_example, features=tf.feature_column.make_parse_example_spec(feature_spec))
      receiver_tensors = {'examples': serialized_tf_example}
  
      return tf.estimator.export.ServingInputReceiver(features = tf_example, receiver_tensors = receiver_tensors)
  </code></pre>
  
  <p>The error becomes:</p>
  
  <pre><code>File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 473, in train_and_evaluate
      return executor.run()
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 613, in run
      return self.run_local()
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 714, in run_local
      saving_listeners=saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 370, in train
      loss = self._train_model(input_fn, hooks, saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1161, in _train_model
      return self._train_model_default(input_fn, hooks, saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1195, in _train_model_default
      saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1495, in _train_with_estimator_spec
      any_step_done = True
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/monitored_session.py", line 861, in __exit__
      self._close_internal(exception_type)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/monitored_session.py", line 894, in _close_internal
      h.end(self._coordinated_creator.tf_sess)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/basic_session_run_hooks.py", line 600, in end
      self._save(session, last_step)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/basic_session_run_hooks.py", line 619, in _save
      if l.after_save(session, step):
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 519, in after_save
      self._evaluate(global_step_value)  # updates self.eval_result
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 539, in _evaluate
      self._evaluator.evaluate_and_export())
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 932, in evaluate_and_export
      is_the_final_export)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 965, in _export_eval_result
      is_the_final_export=is_the_final_export))
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/exporter.py", line 414, in export
      is_the_final_export)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/exporter.py", line 120, in export
      checkpoint_path=checkpoint_path)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 735, in export_saved_model
      strip_default_attrs=True)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 859, in _export_all_saved_models
      strip_default_attrs=strip_default_attrs)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 925, in _add_meta_graph_for_mode
      input_receiver = input_receiver_fn()
    File "deploy_model/model.py", line 85, in serving_input_receiver_fn
      tf_example = tf.io.parse_example(serialized=serialized_tf_example, features=tf.feature_column.make_parse_example_spec(feature_spec))
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/feature_column/feature_column.py", line 806, in make_parse_example_spec
      'Given: {}'.format(column))
  ValueError: All feature_columns must be _FeatureColumn instances. Given: poutcome
  </code></pre>
  
  <p>I modified the serving function again like this:</p>
  
  <pre><code>def serving_input_receiver_fn():
      inputs = {
          'job' : tf.placeholder(dtype = tf.string, shape = [None]),
          'marital' : tf.placeholder(dtype = tf.string, shape = [None]),
          'education' : tf.placeholder(dtype = tf.string, shape = [None]),
          'default' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'housing' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'loan' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'contact' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'dayofmonth' : tf.placeholder(dtype = tf.string, shape = [None]),
          'month' : tf.placeholder(dtype = tf.string, shape = [None]),
          'duration' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'campaign' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'pdays' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'previous' : tf.placeholder(dtype = tf.int64, shape = [None]),
          'poutcome' : tf.placeholder(dtype = tf.string, shape = [None])
      }
  
      inputs = {}
  
      for feat in enumerate(inputs):
          inputs[feat.name] = tf.compat.v1.placeholder(shape=[None], dtype=feat.dtype)
  
      return tf.estimator.export.ServingInputReceiver(inputs, inputs)
  </code></pre>
  
  <p>Then the error changed to:</p>
  
  <pre><code>Traceback (most recent call last):
    File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
      "__main__", fname, loader, pkg_name)
    File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
      exec code in run_globals
    File "/home/jupyter/marketing/deploy_model/task.py", line 43, in &lt;module&gt;
      model.train_and_evaluate(args)
    File "deploy_model/model.py", line 136, in train_and_evaluate
      tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 473, in train_and_evaluate
      return executor.run()
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 613, in run
      return self.run_local()
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 714, in run_local
      saving_listeners=saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 370, in train
      loss = self._train_model(input_fn, hooks, saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1161, in _train_model
      return self._train_model_default(input_fn, hooks, saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1195, in _train_model_default
      saving_listeners)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1495, in _train_with_estimator_spec
      any_step_done = True
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/monitored_session.py", line 861, in __exit__
      self._close_internal(exception_type)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/monitored_session.py", line 894, in _close_internal
      h.end(self._coordinated_creator.tf_sess)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/basic_session_run_hooks.py", line 600, in end
      self._save(session, last_step)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/training/basic_session_run_hooks.py", line 619, in _save
      if l.after_save(session, step):
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 519, in after_save
      self._evaluate(global_step_value)  # updates self.eval_result
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 539, in _evaluate
      self._evaluator.evaluate_and_export())
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 932, in evaluate_and_export
      is_the_final_export)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/training.py", line 965, in _export_eval_result
      is_the_final_export=is_the_final_export))
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/exporter.py", line 414, in export
      is_the_final_export)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/exporter.py", line 120, in export
      checkpoint_path=checkpoint_path)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 735, in export_saved_model
      strip_default_attrs=True)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 859, in _export_all_saved_models
      strip_default_attrs=strip_default_attrs)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 932, in _add_meta_graph_for_mode
      config=self.config)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1149, in _call_model_fn
      model_fn_results = self._model_fn(features=features, **kwargs)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/contrib/estimator/python/estimator/extenders.py", line 89, in new_model_fn
      spec = estimator.model_fn(features, labels, mode, config)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 250, in public_model_fn
      return self._call_model_fn(features, labels, mode, config)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/estimator.py", line 1149, in _call_model_fn
      model_fn_results = self._model_fn(features=features, **kwargs)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/canned/dnn.py", line 811, in _model_fn
      batch_norm=batch_norm)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/canned/dnn.py", line 463, in _dnn_model_fn
      logits = logit_fn(features=features, mode=mode)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_estimator/python/estimator/canned/dnn.py", line 109, in dnn_logit_fn
      return dnn_model(features, mode)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/keras/engine/base_layer.py", line 854, in __call__
      outputs = call_fn(cast_inputs, *args, **kwargs)
    File "/usr/local/lib/python2.7/dist-packages/tensorflow_core/python/autograph/impl/api.py", line 237, in wrapper
      raise e.ag_error_metadata.to_exception(e)
  ValueError: in converted code:
      relative to /usr/local/lib/python2.7/dist-packages:
  
      tensorflow_estimator/python/estimator/canned/dnn.py:252 call  *
          net = self._input_layer(features)
      tensorflow_core/python/keras/engine/base_layer.py:854 __call__
          outputs = call_fn(cast_inputs, *args, **kwargs)
      tensorflow_core/python/feature_column/dense_features.py:133 call
          self._state_manager)
      tensorflow_core/python/feature_column/feature_column_v2.py:2835 get_dense_tensor
          return transformation_cache.get(self, state_manager)
      tensorflow_core/python/feature_column/feature_column_v2.py:2598 get
          transformed = column.transform_feature(self, state_manager)
      tensorflow_core/python/feature_column/feature_column_v2.py:2807 transform_feature
          input_tensor = transformation_cache.get(self.key, state_manager)
      tensorflow_core/python/feature_column/feature_column_v2.py:2590 get
          raise ValueError('Feature {} is not in features dictionary.'.format(key))
  
      ValueError: Feature campaign is not in features dictionary.
  </code></pre>
  
  <p>Finally, I solved it as follows:</p>
  
  <pre><code>def serving_input_receiver_fn():
  
      # set() change the iterable into a list of items, sorted
      feature_spec = [
          tf.feature_column.categorical_column_with_vocabulary_list('job', ['blue-collar', 'management', 'technician','admin.','services','retired', 'self-employed', \
                                                                            'entrepreneur','unemployed', 'housemaid', 'student', 'unknown']),
          tf.feature_column.categorical_column_with_vocabulary_list('marital', ['married', 'single', 'divorced']),
          tf.feature_column.categorical_column_with_vocabulary_list('education', ['secondary', 'primary', 'tertiary', 'unknown']),
          tf.feature_column.numeric_column("default"),
          tf.feature_column.numeric_column("housing"),
          tf.feature_column.numeric_column("loan"),
          tf.feature_column.categorical_column_with_vocabulary_list('contact', ['cellular', 'telephone', 'unknown']),
          tf.feature_column.categorical_column_with_vocabulary_list('dayofmonth', ['1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31']),
          tf.feature_column.categorical_column_with_vocabulary_list('month', ['jan', 'feb', 'mar','apr','may','jun','jul', 'aug', 'sep','oct','nov','dec']),
          tf.feature_column.numeric_column("duration"),
          tf.feature_column.numeric_column("campaign"),
          tf.feature_column.numeric_column("pdays"),
          tf.feature_column.numeric_column("previous"),
          tf.feature_column.categorical_column_with_vocabulary_list('poutcome', ['failure', 'success', 'other', 'unknown'])
      ]
  
      serialized_tf_example = tf.compat.v1.placeholder(dtype=tf.string, shape=[None], name='input_example_tensor')
      tf_example = tf.io.parse_example(serialized=serialized_tf_example, features=tf.feature_column.make_parse_example_spec(feature_spec))
  
      receiver_tensors = {'examples': serialized_tf_example}
  
      return tf.estimator.export.ServingInputReceiver(features = tf_example, receiver_tensors = receiver_tensors)
  </code></pre>
  
  <p>However, I faced another problem in prediction. I cannot provide a data format that the serving function can read.</p>
  
  <p>This is the Signature_Def</p>
  
  <pre><code>The given SavedModel SignatureDef contains the following input(s):
    inputs['inputs'] tensor_info:
        dtype: DT_STRING
        shape: (-1)
        name: input_example_tensor:0
  The given SavedModel SignatureDef contains the following output(s):
    outputs['classes'] tensor_info:
        dtype: DT_STRING
        shape: (-1, 2)
        name: dnn/head/Tile:0
    outputs['scores'] tensor_info:
        dtype: DT_FLOAT
        shape: (-1, 2)
        name: dnn/head/predictions/probabilities:0
  Method name is: tensorflow/serving/classify
  </code></pre>
  
  <p>This is my code of prediction</p>
  
  <pre><code>%%writefile ./test.json
  {"inputs": {"job":"entrepreneur","marital":"married","education":"secondary","default":"1","housing":"1","loan":"1","contact":"unknown","dayofmonth":"5","month":"may","duration":"127","campaign":"1","pdays":"-1","previous":"0","poutcome":"unknown"}}
  
  !gcloud ai-platform predict --model=campaign_deploy --json-instances=./test.json
  </code></pre>
  
  <p>The error message is:</p>
  
  <pre><code>{
    "error": "Prediction failed: Error processing input: Failed to convert object of type &lt;class 'list'&gt; to Tensor. Contents: [{'campaign': '1', 'contact': 'unknown', 'dayofmonth': '5', 'default': '1', 'duration': '127', 'education': 'secondary', 'housing': '1', 'job': 'entrepreneur', 'loan': '1', 'marital': 'married', 'month': 'may', 'pdays': '-1', 'poutcome': 'unknown', 'previous': '0'}]. Consider casting elements to a supported type."
  }
  </code></pre>
  
  <p>Can anyone tell me where the problem is? Is it the input input (test.json) or the serving function? What is your suggestion to fix it?</p>