部署Keras模型至Google AI Platform:修复SavedModel导出的serving_input_fn问题
解决Keras转Estimator后导出SavedModel的Input Key不匹配问题
你的问题核心在于模型期望的输入结构和serving_input_receiver_fn提供的特征结构不匹配:你的Keras模型定义了一个名为input_49的三维输入张量(形状(None, 400, 254)),但当前代码却传入了254个独立的特征列,这就导致了KeyError。结合TensorFlow 2.0-beta1的特性,这里有两种针对性的解决方案:
方案1:直接匹配模型的三维输入结构
如果你的服务请求会直接传入形状为(batch_size, 400, 254)的张量,那么直接修改serving_input_receiver_fn,让它创建一个和模型输入完全匹配的占位符即可:
def serving_input_receiver_fn(): # 创建与模型输入层匹配的占位符:形状[None, 400, 254],None对应可变的batch size input_placeholder = tf.placeholder( dtype=tf.float64, shape=[None, 400, 254], name='input_49' ) # 特征字典直接使用模型期望的键名input_49 features = {'input_49': input_placeholder} return tf.estimator.export.ServingInputReceiver(features, features)
这个方案最直接,完全对齐模型的输入定义,避免了不必要的特征拼接操作。
方案2:从多列特征拼接成模型需要的三维张量
如果你的服务请求是按254个独立列传递数据(比如每列对应时序中的一个特征维度,每个列包含400个时序步),那么需要在serving_input_receiver_fn里把这些列拼接成模型需要的三维张量:
def serving_input_receiver_fn(): # 为每个输入列创建占位符,形状为[None, 400](None是batch size,400是时序步长) feature_placeholders = { column.name: tf.placeholder(tf.float64, [None, 400]) for column in INPUT_COLUMNS } # 将254个(None,400)的张量沿最后一维拼接,得到(None,400,254)的张量 combined_input = tf.stack(list(feature_placeholders.values()), axis=-1) # 映射到模型期望的input_49键 features = {'input_49': combined_input} return tf.estimator.export.ServingInputReceiver(features, feature_placeholders)
这个方案处理了“输入是多列但模型需要单张量”的场景,确保特征结构和模型输入层一致。
关键注意事项
- 数据类型对齐:确保占位符的
dtype和Keras模型输入层的数据类型一致(你代码里用了tf.float64,要确认模型输入确实是这个类型)。 - 输入名称严格匹配:特征字典的键必须和Keras模型输入层的名称完全一致(这里是
input_49),大小写、拼写都不能错。 - TF2.0-beta1兼容性:
tf.keras.estimator.model_to_estimator在2.0-beta版本中已经支持直接转换Keras模型,只要输入结构匹配,导出SavedModel就不会有问题。
内容的提问来源于stack exchange,提问作者AntsaR
相关产品推荐
相关产品推荐

