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

TensorFlow/Keras多输出CNN无法运行问题求助

问题分析与解决方案

核心问题根源

  1. 模型输出与损失函数不兼容:你给position输出添加了Reshape((1,1,2)),导致输出形状为[batch_size,1,1,2],但TensorFlow的mean_squared_error损失默认会尝试挤压最后一维(期望该维度为1),维度为2时直接触发挤压错误。
  2. 数据集输出结构不匹配Keras要求:Keras的model.fit期望输入数据是(x, y)格式,其中y要和模型多输出的结构一致(元组或字典);你修改数据集后返回了4个独立张量,不符合要求,同时tf.data.Dataset.from_generator的output_types和output_shapes必须严格匹配生成器的返回结构。

具体修正步骤

1. 修正模型定义(移除不必要的Reshape层)

模型的position输出无需额外Reshape,直接输出(batch_size, 2)即可,对应每个样本的(x,y)坐标:

model = ResNet18(input_shape=(224, 224, 3), weights="imagenet", include_top=False)
inputLayer = model.input
innerLayer = tf.keras.layers.Flatten()(model.output)

# 分类分支保持不变
is_visible = tf.keras.layers.Dense(1, activation="sigmoid", name="is_visible")(innerLayer)

# 回归分支:直接输出2维,无需Reshape
position = tf.keras.layers.Dense(2, name="position")(innerLayer)

model = tf.keras.Model(inputs=[inputLayer], outputs=[is_visible, position])
adam = tf.keras.optimizers.Adam(1e-4)
model.compile(
    optimizer=adam,
    loss={
        "is_visible": "binary_crossentropy",
        "position": "mean_squared_error",
    },
    loss_weights={
        "is_visible": 1.0,
        "position": 1.0
    },
    metrics={
        "is_visible": "accuracy",
        "position": "mean_squared_error"
    },
)

2. 修正数据集生成器与tf.data配置

生成器需要返回(image_batch, (is_visible_batch, position_batch))的结构,其中position_batch的形状为(batch_size, 2);同时调整output_types和output_shapes匹配该结构:

生成器返回格式(关键)

确保生成器的yield语句为:

# 假设is_visible_batch形状是(batch_size,1),position_batch形状是(batch_size,2)
yield image_batch, (is_visible_batch, position_batch)

tf.data参数配置

# output_types对应返回的结构:(图像类型, (分类标签类型, 回归标签类型))
output_types = (tf.float32, (tf.uint8, tf.float32))
output_shapes = (
    tf.TensorShape((None, image_height, image_width, number_of_channels)),  # 图像
    (
        tf.TensorShape((None, 1)),  # is_visible
        tf.TensorShape((None, 2))   # position (x,y)
    )
)

train_dataset = tf.data.Dataset.from_generator(
    generator, output_types=output_types, output_shapes=output_shapes,
)

为什么之前的尝试无效?

  • 给position加Reshape((1,1,2))完全没必要,回归任务的输出只需要和标签形状一致即可,标签是每个样本2个数值,所以输出(batch_size,2)就足够。
  • 调整数据集时,你把position拆成x和y两个独立张量,导致返回结构变成4个元素,而Keras只接受(x,y)的二元组,其中y是对应多输出的嵌套结构(元组或字典)。
  • 若尝试用字典返回y,需确保tf.data的output_types和output_shapes也对应字典结构,示例如下:
    # 字典格式的tf.data配置
    output_types = (tf.float32, {"is_visible": tf.uint8, "position": tf.float32})
    output_shapes = (
        tf.TensorShape((None, 224,224,3)),
        {
            "is_visible": tf.TensorShape((None,1)),
            "position": tf.TensorShape((None,2))
        }
    )
    # 生成器yield语句
    yield image_batch, {"is_visible": is_visible_batch, "position": position_batch}
    
    这种方式也可行,但元组结构更简洁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:25:16