【问题标题】:Inputs to eager execution function cannot be Keras symbolic tensors急切执行函数的输入不能是 Keras 符号张量
【发布时间】:2019-08-29 07:05:42
【问题描述】:

我正在尝试在 tf.Keras (TensorFlow 2.0.0rc0) 中为具有稀疏注释数据的 3-D U-Net 实施依赖于样本和像素的损失加权 (Cicek 2016, arxiv:1606.06650)。

这是我的代码:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, losses, models

# disabling eager execution makes this example work:
# tf.python.framework_ops.disable_eager_execution()


def get_loss_fcn(w):
    def loss_fcn(y_true, y_pred):
        loss = w * losses.mse(y_true, y_pred)
        return loss
    return loss_fcn


data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4)
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
w = layers.Input([4])
y = layers.Activation('tanh')(x)
model = models.Model(inputs=[x, w], outputs=y)
loss = get_loss_fcn(model.input[1])

# using another loss makes it work, too:
# loss = 'mse'

model.compile(loss=loss)
model.fit((data_x, data_w), data_y)

print('Done.')

这在禁用 Eager Execution 时运行良好,但 TensorFlow 2 的要点之一是默认情况下具有 Eager Execution。如您所见,在我和该目标之间存在自定义损失函数(使用'mse' 作为损失也可以消除该错误):

  File "MWE.py", line 30, in <module>
    model.fit((data_x, data_w), data_y)
[...]
tensorflow.python.eager.core._SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'input_2:0' shape=(None, 4) dtype=float32>]

我可以做些什么来使这种结构与急切的执行一起工作?

我的一个想法是将w 连接到输出y 并将y_pred 分离为损失函数中的原始y_predw,但这是我想要的hack避免。不过,它的工作原理是 # HERE 标记的更改:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, losses, models


# HERE
def loss_fcn(y_true, y_pred):
    w = y_pred[:, :, -1]  # HERE
    y_pred = y_pred[:, :, :-1]  # HERE
    loss = w * losses.mse(y_true, y_pred)
    return loss


data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4, 1)  # HERE
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
w = layers.Input([4, 1])  # HERE
y = layers.Activation('tanh')(x)
output = layers.Concatenate()([y, w])  # HERE
model = models.Model(inputs=[x, w], outputs=output)  # HERE
loss = loss_fcn  # HERE

model.compile(loss=loss)
model.fit((data_x, data_w), data_y)

print('Done.')

还有其他想法吗?

【问题讨论】:

标签: python tensorflow keras deep-learning eager-execution


【解决方案1】:

另一种解决方案是将权重作为附加输出特征而不是输入特征传递。

这使模型完全没有任何相关的权重,权重仅出现在损失函数和.fit() 调用中:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, losses, models

data_x = 2 * np.ones((7, 11, 15, 3), dtype=float)
data_y = 5 * np.ones((7, 9, 13, 5), dtype=float)

x = layers.Input(data_x.shape[1:])
y = layers.Conv2D(5, kernel_size=3)(x)
model = models.Model(inputs=x, outputs=y)


def loss(y_true, y_pred):
    (y_true, w) = tf.split(y_true, num_or_size_splits=[-1, 1], axis=-1)
    loss = tf.squeeze(w, axis=-1) * losses.mse(y_true, y_pred)

    tf.print(tf.math.reduce_mean(y_true), "== 5")
    tf.print(tf.math.reduce_mean(w), "== 3")

    return loss


model.compile(loss=loss)

data_w = 3 * np.ones((7, 9, 13, 1), dtype=float)
data_yw = np.concatenate((data_y, data_w), axis=-1)
model.fit(data_x, data_yw)

一个缺点仍然是在将 yw 合并到 numpy.stack() 时,您需要(可能)操作大型数组,因此更多类似 TensorFlow 的内容将不胜感激。

【讨论】:

  • 您是否尝试过不使用 .fit() 直接进行训练,例如:tensorflow.org/beta/guide/keras/…
  • @vgoklani 不,还没有。感谢您的提示!
  • 这样的问题是你失去了 keras 的很多便利(即回调)。
【解决方案2】:

另一种方式:

from tensorflow.keras import layers, models, losses
import numpy as np

def loss_fcn(y_true, y_pred, w):
    loss = w * losses.mse(y_true, y_pred)
    return loss


data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4)
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
y_true = layers.Input([4, 1])
w = layers.Input([4])
y = layers.Activation('tanh')(x)


model = models.Model(inputs=[x, y_true, w], outputs=y)
model.add_loss(loss_fcn(y, y_true, w))


model.compile()
model.fit((data_x, data_y, data_w))

我认为这是最优雅的解决方案。

【讨论】:

  • 您能解释一下为什么会这样吗?我有一个想法,但我不确定我是否理解它背后的概念。你是在暗示 y_true 是我的 MWE 有问题的张量,而不是 w?因为我没有看到w 有任何变化。
  • @bers 我认为问题在于您的函数使用符号张量返回内部函数。使用返回符号张量的函数而不是函数有效,因为返回的符号张量是惰性求值的。
  • @feature_engineer 这是有道理的,但如果我这样做,我会得到ValueError: No gradients provided for any variable: [...] - 知道为什么会发生这种情况吗?
【解决方案3】:

如果您将 fit 行替换为

,您的代码在最新的 tensorflow (2.3) 上运行良好
model.fit((data_x, data_y, data_w))

所以:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, losses, models


# HERE
def loss_fcn(y_true, y_pred):
    w = y_pred[:, :, -1]  # HERE
    y_pred = y_pred[:, :, :-1]  # HERE
    loss = w * losses.mse(y_true, y_pred)
    return loss


data_x = np.random.rand(5, 4, 1)
data_w = np.random.rand(5, 4, 1)  # HERE
data_y = np.random.rand(5, 4, 1)

x = layers.Input([4, 1])
w = layers.Input([4, 1])  # HERE
y = layers.Activation('tanh')(x)
output = layers.Concatenate()([y, w])  # HERE
model = models.Model(inputs=[x, w], outputs=output)  # HERE
loss = loss_fcn  # HERE

model.compile(loss=loss)
model.fit((data_x, data_y, data_w))

print('Done.')

此外,我发现在损失函数中实现的 tf.reduce_mean、K.mean、tf.square、tf.exp 等会导致相同的错误。

【讨论】:

    猜你喜欢
    • 2020-07-30
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    • 2020-07-25
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多