TensorFlow/Keras多输出CNN无法运行问题求助
问题分析与解决方案
核心问题根源
- 模型输出与损失函数不兼容:你给
position输出添加了Reshape((1,1,2)),导致输出形状为[batch_size,1,1,2],但TensorFlow的mean_squared_error损失默认会尝试挤压最后一维(期望该维度为1),维度为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
相关产品推荐
相关产品推荐

