多输出Keras模型损失计算的y_pred、y_true及自定义损失实现问题
Let's break down your questions one by one, since multi-output models in Keras can be a bit tricky when it comes to loss handling:
问题1:多输出Keras模型中,损失计算时的y_pred和y_true分别指代什么?
在Keras的多输出模型里,每个输出分支都会对应一对独立的y_true和y_pred,它们的顺序和你定义模型outputs=参数时的列表顺序完全一致。举个例子,如果你的模型输出是[y1, y2],那么第一个损失函数会拿到对应y1的真实标签(y1_true)和y1的预测值(y1_pred),第二个损失函数则处理y2的真实标签(y2_true)和y2的预测值(y2_pred)。每个损失函数只负责自己对应的输出分支,互相独立。
问题2:你的MSE损失对应的y_pred和y_true是什么?MSE的y_true包含y1吗?
先明确:损失列表的顺序和模型输出列表的顺序是一一绑定的。你的模型输出是[y1, y2],compile时的loss列表是[custom_loss, 'mse'],所以:
custom_loss对应第一个输出y1,它的y_true是y1的真实标签,y_pred是模型输出的y1预测值;'mse'对应第二个输出y2,它的y_true仅仅是y2的真实标签,y_pred是模型输出的y2预测值,和y1完全没关系。
简单说,MSE只关心自己对应的那个输出分支,不会碰另一个分支的真实值或预测值。
问题3:如何实现接收两个输出的真实值和预测值的自定义损失函数?
你现在写的custom_loss(y1_true, y1_pred,y2_true, y2_pred)这种形式,不能直接作为列表里的单个损失函数用(因为单个损失函数只能接收对应分支的一对y_true和y_pred)。要实现同时处理两个分支的损失,你需要定义一个全局损失函数,把所有输出的真实值和预测值作为整体传入,步骤如下:
- 调整自定义损失函数的参数结构:Keras会把所有真实标签打包成一个列表(或张量)传给
y_true,把所有预测值打包成一个列表传给y_pred,所以你的函数要先拆分这两个参数:
import tensorflow as tf def custom_total_loss(y_true, y_pred): # 拆分真实标签和预测值 y1_true, y2_true = y_true y1_pred, y2_pred = y_pred # 在这里实现你的自定义逻辑,比如计算两个分支的损失然后组合 loss1 = tf.reduce_mean(tf.abs(y1_true - y1_pred)) # 替换成你自己的损失逻辑 loss2 = tf.keras.losses.mean_squared_error(y2_true, y2_pred) # 总损失可以是两者的加权和或者直接相加,根据需求调整权重 return loss1 + 0.5 * loss2
- 修改模型的compile方式:不再用损失列表,而是直接传入这个全局损失函数:
model = Model(inputs=x1, outputs=[y1,y2]) model.compile(optimizer='sgd', loss=custom_total_loss)
- 训练时的输入注意:喂数据的时候,真实标签也要以列表形式传入,比如:
model.fit(x_train, [y1_train, y2_train], epochs=10, batch_size=32)
这样你的自定义损失函数就能同时拿到两个分支的真实值和预测值,自由组合计算总损失了。
内容的提问来源于stack exchange,提问作者Eka

