在多输出模型中使用中间输出结合add_loss和keras.losses

在之前的另一篇文章中(Keras多输出自定义损失函数与中间层输出),我讨论了我遇到的问题。最终,这个问题通过以下方式解决了:

def MyLoss(true1, true2, out1, out2, out3):    loss1 = tf.keras.losses.someloss1(out1, true1)    loss2 = tf.keras.losses.someloss2(out2, true2)    loss3 = tf.keras.losses.someloss3(out2, out3)    loss = loss1 + loss2 + loss3    return lossinput1 = Input(shape=input1_shape)input2 = Input(shape=input2_shape)# 不考虑符号表示,仅关注思想output1 = Submodel1()([input1,input2]) output2 = Submodel2()(output1)output3 = Sumbodel3()(output1)true1 = Input(shape=true1shape)true2 = Input(shape=true2shape)model = Model([input1,input2,true1,true2], [output1,output2,output3])model.add_loss(MyLoss(true1, true2, output1, output2, output3))model.compile(optimizer='adam', loss=None)model.fit(x=[input1 ,input2 ,true1,true2], y=None, epochs=n_epochs)

在那个问题中,我使用的所有损失函数都是keras的损失函数(即tf.keras.losss.someloss),但现在我想添加更多的损失函数,并且我想将自定义损失函数与keras的损失函数结合使用。也就是说,现在我有这样的方案:

enter image description here

为了添加这两个损失函数,这些是SSIM损失函数,我尝试了以下方法:

def SSIMLoss(y_true, y_pred):    return 1-tf.reduce_mean(tf.image.ssim(y_true, y_pred, 1.0))def MyLoss(true1, true2, out1, out2, out3):    loss1 = tf.keras.losses.someloss1(out1, true1)    customloss1 = SSIMLoss(out1,true1)    loss2 = tf.keras.losses.someloss2(out2, true2)    loss3 = tf.keras.losses.someloss3(out2, out3)    customloss2 = SSIMLoss(out2,out3)    loss = loss1 + loss2 + loss3 + customloss1 + customloss2    return loss

但我遇到了以下错误:

OperatorNotAllowedInGraphError: 在图执行中不允许将`tf.Tensor`用作Python的`bool`。请使用Eager执行模式或使用@tf.function装饰此函数。

我尝试使用@tf.function装饰该函数,但得到了以下错误:

_SymbolicException: Eager执行函数的输入不能是Keras符号张量,但发现了[<tf.Tensor 'input_43:0' shape=(None, 128, 128, 1) dtype=float32>, <tf.Tensor 'conv2d_109/Sigmoid:0' shape=(None, 128, 128, 1) dtype=float32>]

我找到了这个(https://github.com/tensorflow/tensorflow/issues/32127)关于将keras损失函数与add_loss结合的讨论,可能这就是问题所在,但我不知道如何解决它。


回答:

我在TF 2.3中能够重现您上述的错误。但在TF 2.4和夜间版本的TF 2.6中,没有这样的问题,但当我尝试绘制模型时,我得到了另一个错误,尽管使用model.summary().fit进行训练时没有问题。然而,如果禁用eager模式,那么在TF 2.3 / 2.4中就不会有问题。


详细信息

TF 2.3中,我可以重现您的问题,如下所示。要解决这个问题,只需禁用eager模式即可。

TF 2.4 / TF Nightly 2.6中,我不需要禁用eager模式。模型编译得很好,并且按预期进行训练。但唯一的问题是当我尝试绘制模型时,它给出了以下错误

tf.keras.utils.plot_model(model)....AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute '_keras_history'

这个问题是由SSIMLoss方法中的1-..表达式引起的;这与类似的情况。但同样,通过禁用eager模式,问题可以解决。然而,总的来说,最好升级到TF 2.4


代码示例

在这里,我将向您展示一个类似于您的训练管道的示例。在这个示例中,我们有一个输入(28, 28, 3)和三个输出(28, 28, 3)。

from tensorflow.keras.layers import *from tensorflow.keras import Model import tensorflow as tf import numpy as np# tf.compat.v1.disable_eager_execution()print(tf.__version__)print(tf.executing_eagerly())2.4.1True

自定义损失函数。

def SSIMLoss(y_true, y_pred):    return 1 - tf.reduce_mean(tf.image.ssim(y_true, y_pred, 1.0))def MyLoss(true1, true2, out1, out2, out3):    loss1 = tf.keras.losses.cosine_similarity(out1, true1)    loss2 = tf.keras.losses.cosine_similarity(out2, true2)    loss3 = tf.keras.losses.cosine_similarity(out2, out3)    customloss1 = SSIMLoss(true1, out1)    customloss2 = SSIMLoss(out2, out3)    loss = loss1 + loss2 + loss3 + customloss1 + customloss2    return loss

数据

imgA = tf.random.uniform([10, 28, 28, 3], minval=0, maxval=256)tarA = np.random.randn(10, 28, 28, 3)tarB = np.random.randn(10, 28, 28, 3)

模型

一个具有一个输入和三个输出的模型。

input  = Input(shape=(28, 28, 3))middle = Conv2D(16, kernel_size=(3,3), padding='same')(input)outputA = Dense(3, activation='relu')(middle)outputB = Dense(3, activation='selu')(middle)outputC = Dense(3, activation='elu')(middle)target_inputA = Input(shape=(28, 28, 3))target_inputB = Input(shape=(28, 28, 3))model = Model([input, target_inputA, target_inputB],               [outputA, outputB, outputC])model.add_loss(MyLoss(target_inputA, target_inputB,                       outputA, outputB, outputC))# tf.keras.utils.plot_model(model) # 禁用eager模式 model.summary()

编译和运行

model.compile(optimizer='adam', loss=None)model.fit([imgA, tarA, tarB], steps_per_epoch=5)5/5 [==============================] - 2s 20ms/step - loss: 1.4338<tensorflow.python.keras.callbacks.History at 0x7efde188d450>

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注