TensorFlow导出自定义Estimator报错:serving_input_fn与PredictOutput使用困惑
嘿,我前阵子刚折腾完自定义TF Estimator导出SavedModel的事儿,太懂你现在的困惑了!这俩玩意儿(serving_input_fn和PredictOutput)确实文档讲得太绕,我给你用MNIST的场景拆解明白:
先搞懂核心逻辑
训练时你的模型是从训练数据管道拿输入,但预测服务时,模型得知道怎么接收外部传来的数据——这就是serving_input_fn的作用;而PredictOutput是帮你明确告诉TF,哪些预测结果要暴露给外部调用者,避免导出的模型输出乱套。
第一步:写对serving_input_fn
针对MNIST的28x28灰度图,你得定义预测时模型接收的输入格式,还要和你训练时的输入特征对应上。比如如果训练时你给模型的是[None,28,28,1]的图片张量,那serving_input_fn得这么写:
def serving_input_fn(): # 定义占位符:支持批量输入,shape的第一个维度是None(表示任意批量大小) input_placeholder = tf.compat.v1.placeholder( dtype=tf.float32, shape=[None, 28, 28, 1], name="mnist_input_image" ) # 如果你训练时是把图片扁平化成784维向量,就把shape改成[None,784] # 注意:这里的features字典的key,必须和你model_fn里接收的features的key完全一致! features = {"image": input_placeholder} # receiver_tensors是外部调用时要传的参数名,和features对应就行 receiver_tensors = {"image": input_placeholder} # 返回ServingInputReceiver,告诉TF预测时的输入管道 return tf.estimator.export.ServingInputReceiver(features, receiver_tensors)
第二步:在model_fn里正确用PredictOutput
你的自定义model_fn在PREDICT模式下,得用PredictOutput包装你的预测结果,而不是直接返回字典。比如:
def model_fn(features, labels, mode, params): # 这里是你的卷积、BN、Dropout等网络结构代码 # 假设最后得到logits张量:shape=[batch_size, 10] if mode == tf.estimator.ModeKeys.PREDICT: # 定义你要输出的预测结果 predictions = { "class_id": tf.argmax(logits, axis=1, output_type=tf.int32), "probabilities": tf.nn.softmax(logits, name="softmax_output"), "logits": logits } # 用PredictOutput包装后返回EstimatorSpec return tf.estimator.EstimatorSpec( mode=mode, predictions=tf.estimator.PredictOutput(predictions) ) # 下面是训练和评估模式的代码(你已经写好的部分) # ...
第三步:执行导出
这一步就简单了,调用export_saved_model就行:
# 初始化你的自定义Estimator mnist_estimator = tf.estimator.Estimator( model_fn=model_fn, model_dir="./mnist_model_checkpoints" # 你的模型 checkpoint 目录 ) # 导出SavedModel到指定目录 export_dir = mnist_estimator.export_saved_model( export_dir_base="./mnist_saved_model", serving_input_receiver_fn=serving_input_fn ) print(f"模型已导出到:{export_dir}")
常见ValueError排查
你提到的ValueError大概率是这几个原因:
- 特征key不匹配:serving_input_fn里的features的key,和model_fn里接收的features的key不一样,比如model_fn里用的是
input_x,但serving_input_fn里写的是image - 输入shape不匹配:训练时用的是扁平化的784维,但serving_input_fn里给的是28x28x1的张量,没做扁平化(如果是这种情况,要在serving_input_fn里加
tf.reshape(input_placeholder, [-1, 784])) - PredictOutput的键和predictions字典不对应:比如PredictOutput里漏写了某个键,或者键名拼写错了
验证导出的模型
导出后可以快速验证一下:
import tensorflow as tf # 加载SavedModel loaded_model = tf.saved_model.load("./mnist_saved_model/1234567890") # 替换成你的导出子目录 infer = loaded_model.signatures["serving_default"] # 生成测试输入(比如随机一张28x28的灰度图) test_img = tf.random.normal([1, 28, 28, 1]) # 调用预测 result = infer(image=test_img) print(f"预测类别:{result['class_id'].numpy()[0]}") print(f"类别概率:{result['probabilities'].numpy()[0]}")
内容的提问来源于stack exchange,提问作者匿名用户
相关产品推荐
相关产品推荐

