tensorflow - 从导出中排除,因为它们无法通过 TensorFlow Serving API 提供服务
问题描述
TensorFlow 1.10 版
使用:DNNClassifier
和tf.estimator.FinalExporter
我正在使用 TF博客中的 Iris 示例。我定义了以下代码:
# The CSV features in our training & test data.
COLUMN_NAMES = ['SepalLength',
'SepalWidth',
'PetalLength',
'PetalWidth',
'Species']
FEATURE_COLUMNS = COLUMN_NAMES[:4]
INPUT_COLUMNS = [
tf.feature_column.numeric_column(column) for column in COLUMN_NAMES
]
def serving_input_receiver_fn():
"""Build the serving inputs."""
inputs = {}
for feat in INPUT_COLUMNS:
inputs[feat.name] = tf.placeholder(shape=[None], dtype=feat.dtype)
return tf.estimator.export.ServingInputReceiver(inputs, inputs)
这就是我调用函数的方式:
train_spec = tf.estimator.TrainSpec(
train_input, max_steps=hparams.train_steps)
exporter = tf.estimator.FinalExporter(
'iris', serving_input_receiver_fn)
eval_spec = tf.estimator.EvalSpec(
eval_input,
steps=hparams.eval_steps,
exporters=[exporter],
name='iris-eval')
run_config = tf.estimator.RunConfig(
session_config=_get_session_config_from_env_var())
run_config = run_config.replace(model_dir=hparams.job_dir)
print('Model dir: %s', run_config.model_dir)
estimator = model.build_estimator(
# Construct layers sizes.
config=run_config,
hidden_units=[10, 20, 10],
n_classes=3)
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
我收到以下消息:
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Signatures INCLUDED in export for Eval: None
INFO:tensorflow:Signatures INCLUDED in export for Classify: None
INFO:tensorflow:Signatures INCLUDED in export for Regress: None
INFO:tensorflow:Signatures INCLUDED in export for Predict: ['predict']
INFO:tensorflow:Signatures INCLUDED in export for Train: None
INFO:tensorflow:Signatures EXCLUDED from export because they cannot be be served via TensorFlow Serving APIs:
INFO:tensorflow:'serving_default' : Classification input must be a single string Tensor; got {'SepalLength': <tf.Tensor 'Placeholder:0' shape=(?,) dtype=float32>, 'PetalLength': <tf.Tensor 'Placeholder_2:0' shape=(?,) dtype=float32>, 'PetalWidth': <tf.Tensor 'Placeholder_3:0' shape=(?,) dtype=float32>, 'SepalWidth': <tf.Tensor 'Placeholder_1:0' shape=(?,) dtype=float32>, 'Species': <tf.Tensor 'Placeholder_4:0' shape=(?,) dtype=float32>}
INFO:tensorflow:'classification' : Classification input must be a single string Tensor; got {'SepalLength': <tf.Tensor 'Placeholder:0' shape=(?,) dtype=float32>, 'PetalLength': <tf.Tensor 'Placeholder_2:0' shape=(?,) dtype=float32>, 'PetalWidth': <tf.Tensor 'Placeholder_3:0' shape=(?,) dtype=float32>, 'SepalWidth': <tf.Tensor 'Placeholder_1:0' shape=(?,) dtype=float32>, 'Species': <tf.Tensor 'Placeholder_4:0' shape=(?,) dtype=float32>}
WARNING:tensorflow:Export includes no default signature!
当我打印时,serving_input_receiver_fn
我得到:
ServingInputReceiver(features={'sepal_width': <tf.Tensor 'Placeholder_1:0' shape=(?, 1) dtype=float32>, 'petal_width': <tf.Tensor 'Placeholder_3:0' shape=(?, 1) dtype=float32>, 'sepal_length': <tf.Tensor 'Placeholder:0' shape=(?, 1) dtype=float32>, 'petal_length': <tf.Tensor 'Placeholder_2:0' shape=(?, 1) dtype=float32>}, receiver_tensors={'sepal_width': <tf.Tensor 'Placeholder_1:0' shape=(?, 1) dtype=float32>, 'petal_width': <tf.Tensor 'Placeholder_3:0' shape=(?, 1) dtype=float32>, 'sepal_length': <tf.Tensor 'Placeholder:0' shape=(?, 1) dtype=float32>, 'petal_length': <tf.Tensor 'Placeholder_2:0' shape=(?, 1) dtype=float32>}, receiver_tensors_alternatives=None)
在导出文件夹中没有任何内容(CSV、JSON 等):
gs://<my-bucket>/iris/iris_20181014_214916/export/:
gs://<my-bucket>/iris/iris_20181014_214916/export/
解决方案
我在这里找到了解决方案。
def _make_input_parser(with_target=True):
"""Returns a parser func according to file_type, task_type and target.
Need to set record_default for last column to integer instead of float in
case of classification tasks.
Args:
with_target (boolean): Pass label or not.
Returns:
It returns a parser.
"""
def _decode_csv(line):
"""Takes the string input tensor and parses it to feature dict and target.
All the columns except the first one are treated as feature column. The
first column is expected to be the target.
Only returns target for if with_target is True.
Args:
line: csv rows in tensor format.
Returns:
features: A dictionary of features with key as "column_names" from
self._column_header.
target: tensor of target values which is the first column of the file.
This will only be returned if with_target==True.
"""
column_header = column_names if with_target else column_names[:4]
record_defaults = [[0.] for _ in xrange(len(column_names) - 1)]
# Pass label as integer.
if with_target:
record_defaults.append([0])
columns = tf.decode_csv(line, record_defaults=record_defaults)
features = dict(zip(column_header, columns))
target = features.pop(column_names[4]) if with_target else None
return features, target
return _decode_csv
def serving_input_receiver_fn():
"""This is used to define inputs to serve the model.
Returns:
A ServingInputReciever object.
"""
csv_row = tf.placeholder(shape=[None], dtype=tf.string)
features, _ = _make_input_parser(with_target=False)(csv_row)
return tf.estimator.export.ServingInputReceiver(features,
{'csv_row': csv_row})
推荐阅读
- text - 如何仅将段落的一部分加粗?
- twitter-bootstrap - 如何使用自定义(布局和表单)组件制作引导模式
- sql - View using dynamic tables
- python - Pandas 多个过滤器 str.contains 或不包含
- python - 无法理解 Python Negative List Slice 的输出
- python-3.x - importing libraries on Python 3.7
- laravel - 如何使用相关表中的数据过滤查询结果?
- c# - How to switch views in a UWP application
- javascript - 搜索结果不会移动到网站的第一列 - HTML5 搜索
- java - Spring FeignClient:如何配置像 Ribbon 这样的负载均衡器