【问题标题】:Combining add_loss with keras.losses in multioutput models using intermediate outputs在使用中间输出的多输出模型中结合 add_loss 和 keras.losses
【发布时间】:2021-07-31 16:08:04
【问题描述】:

之前在另一篇文章 (Keras multioutput custom loss with intermediate layers output) 中,我讨论了我遇到的问题。最后,这个问题是这样解决的:

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 loss

input1 = Input(shape=input1_shape)
input2 = Input(shape=input2_shape)

# do not take into account the notation, only the idea
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 损失结合起来。也就是说,现在我有了这个方案:

为了添加这两个损失,即 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: using a `tf.Tensor` as a Python `bool` is not allowed in Graph execution. Use Eager execution or decorate this function with @tf.function.

我尝试使用@tf.function 装饰函数,但出现此错误:

_SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<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 结合起来,也许这是问题所在,但我不知道如何解决。

【问题讨论】:

  • 您能否就给定的答案提供一些反馈?
  • 嗨@M.Innat,是的,对不起。这些天我有点忙,我无法检查您的解决方案。我现在已经开始了,它似乎正在工作,尽管我遇到了与此无关的其他错误。非常感谢!

标签: python tensorflow machine-learning keras deep-learning


【解决方案1】:

我能够在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 中,我不需要禁用急切模式。该模型编译良好并按预期进行训练。但是当我尝试绘制模型时,唯一的问题出现了,它给出了以下错误

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

这个问题是由SSIMLoss方法中的1-..表达式引起的;某事similar。 但同样,通过禁用急切模式,它仍然可以解决。不过总的来说还是升级到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.1
True

自定义损失函数。

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) # disable eager mode 
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>

【讨论】:

  • 嗨@M.Innat。我一直在使用您在 TF 2.3 上禁用 Eager 和 TF 2.4 的解决方案而不禁用它。两者似乎都有效,但在 TF 2.4 中,一个 epoch 需要 5 小时才能执行,而在 TF 2.3 中需要 5 分钟(这对我来说太多了)。但是,在 TF 2.4 中,GPU volatile 实用程序为 0%,所以我想我没有使用 GPU。
  • 这是一个已知问题,与图形模式相比,Eager 模式速度较慢。检查此question-answer 关于此问题。此外,如果可能,请尝试使用最新的 tf 2.5 以及 nightly 包运行您的代码,看看它是如何运行的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 2021-12-22
  • 1970-01-01
  • 2017-08-30
  • 2022-01-23
相关资源
最近更新 更多