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

TensorFlow多输出模型如何将两类损失合并为单个总损失?

3D图像分割分类模型合并总损失的正确实现

方法一:利用Keras内置的多输出损失加权机制

你的第二种尝试出现四个损失,核心原因是metrics参数同时指定了dice_loss和CCE,Keras会为每个输出头计算这两个指标,造成重复。只需移除多余的metrics(或仅保留所需评价指标),同时通过loss_weights实现加权求和,Keras会自动计算单个总损失。

修改后的编译代码:

# 修正CCE损失定义,避免每次创建新实例
cce_loss = tf.keras.losses.CategoricalCrossentropy()

model.compile(
    loss={'Seg_Final_Sigmoid': dice_loss, 'Class_Final_SoftMax': cce_loss},
    optimizer=Nadam(learning_rate=Config["learning_rate"], beta_1=0.9, beta_2=0.999, epsilon=1e-07, name="Nadam"),
    loss_weights=[0.8, 0.2]  # 对应分割损失、分类损失的权重
)

训练时Keras会自动生成:

  • 单个total_loss:0.8*分割损失 + 0.2*分类损失
  • 同时会显示两个单独的输出损失(可通过自定义回调隐藏,但总损失会正常返回)

方法二:自定义单一总损失函数

这种方法直接在损失函数内部处理两个输出的损失加权求和,需确保函数接收所有真实值和预测值的列表(而非单个输出的张量)。

修正后的损失函数和编译代码:

def total_loss(y_true, y_pred):
    # y_true是列表:[分割掩码真实值, 分类标签真实值]
    # y_pred是列表:[分割掩码预测值, 分类标签预测值]
    mask_weight = 0.8
    class_weight = 0.2
    
    # 计算分割损失
    mask_loss = dice_loss(y_true[0], y_pred[0])
    # 计算分类损失,直接使用内置交叉熵,避免重复创建实例
    class_loss = tf.keras.losses.CategoricalCrossentropy()(y_true[1], y_pred[1])
    
    return mask_weight * mask_loss + class_weight * class_loss

# 编译模型时直接使用总损失函数
model.compile(
    loss=total_loss,
    optimizer=Nadam(learning_rate=Config["learning_rate"], beta_1=0.9, beta_2=0.999, epsilon=1e-07, name="Nadam")
)

此时模型训练时只会返回单个总损失,完全符合需求。

关键错误说明

  1. 第一种尝试的问题:Keras会将单一损失函数分别应用到每个输出头,此时y_true和y_pred是单个输出的张量,而非所有输出的列表,导致你取y_true[0]的逻辑完全错误。
  2. 第二种尝试的问题:metrics参数同时指定两个损失函数,导致每个输出头都计算这两个指标,产生四个额外的损失条目,移除多余metrics即可解决。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 10:45:33