You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Keras Functional API模型的输出指定自定义名称?

问题描述

使用Keras Functional API开发多输出模型后,用saved_model_cli查看SavedModel的签名定义,发现输出属性被默认命名为output_0、output_1、output_2,但预期是t1、t2、t3(与代码中输出层的名称一致)。

saved_model_cli输出结果

$ saved_model_cli show --dir /serving_model_folder/1673549934 --tag_set serve --signature_def serving_default

2023-01-12 10:59:50.836255: I tensorflow/core/util/util.cc:169] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
The given SavedModel SignatureDef contains the following input(s):
  inputs['f1'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: serving_default_f1:0
  inputs['f2'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: serving_default_f2:0
  inputs['f3'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: serving_default_f3:0
  inputs['f4'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1, 1)
      name: serving_default_f4:0
The given SavedModel SignatureDef contains the following output(s):
  outputs['output_0'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1)
      name: StatefulPartitionedCall_1:0
  outputs['output_1'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1)
      name: StatefulPartitionedCall_1:1
  outputs['output_2'] tensor_info:
      dtype: DT_FLOAT
      shape: (-1)
      name: StatefulPartitionedCall_1:2
Method name is: tensorflow/serving/predict

模型代码

input_layers = {
    'f1': Input(shape=(1,), name='f1'),
    'f2': Input(shape=(1,), name='f2'),
    'f3': Input(shape=(1,), name='f3'),
    'f4': Input(shape=(1,), name='f4'),
}

x = layers.concatenate(input_layers.values())
x = layers.Dense(32, activation='relu', name="dense")(x)

output_layers = {
    't1': layers.Dense(1, activation='sigmoid', name='t1')(x),
    't2': layers.Dense(1, activation='sigmoid', name='t2')(x),
    't3': layers.Dense(1, activation='sigmoid', name='t3')(x),
}

model = models.Model(input_layers, output_layers)

希望继续使用Functional API,而非继承tf.Model类,如何指定输出属性的名称?


解决方案

有两种可靠的方法可以在Functional API中保留输出名称:

方法1:自定义导出签名

在保存模型时,用tf.function包装推理逻辑并显式指定输入输出签名,确保输出字典的键被正确映射到SavedModel的输出名称:

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, models

# (模型定义代码不变)

# 定义带输入签名的推理函数
@tf.function(input_signature=[
    {
        'f1': tf.TensorSpec(shape=(None, 1), dtype=tf.float32),
        'f2': tf.TensorSpec(shape=(None, 1), dtype=tf.float32),
        'f3': tf.TensorSpec(shape=(None, 1), dtype=tf.float32),
        'f4': tf.TensorSpec(shape=(None, 1), dtype=tf.float32)
    }
])
def serving_fn(inputs):
    return model(inputs)

# 保存模型时指定自定义签名
tf.saved_model.save(
    model,
    export_dir="/serving_model_folder/new_version",
    signatures={'serving_default': serving_fn}
)

方法2:为输出张量显式命名

通过tf.identity为每个输出张量赋予明确名称,确保SavedModel导出时保留该名称:

# 修改输出层定义部分
output_layers = {
    't1': tf.identity(layers.Dense(1, activation='sigmoid', name='t1')(x), name='t1'),
    't2': tf.identity(layers.Dense(1, activation='sigmoid', name='t2')(x), name='t2'),
    't3': tf.identity(layers.Dense(1, activation='sigmoid', name='t3')(x), name='t3'),
}

model = models.Model(input_layers, output_layers)

# 正常保存模型即可
model.save("/serving_model_folder/new_version")

两种方法都能让saved_model_cli输出中显示t1、t2、t3作为输出属性名,无需切换到继承tf.Model的方式。


内容的提问来源于stack exchange,提问作者Mehran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:30:42