Python “急切执行”函数的输入不能作为符号张量

Python “急切执行”函数的输入不能作为符号张量,python,tensorflow,keras,deep-learning,eager-execution,Python,Tensorflow,Keras,Deep Learning,Eager Execution,我正试图在tf.Keras(TensorFlow 2.0.0rc0)中为具有稀疏注释数据的三维U型网络实施与样本和像素相关的损失加权(Cicek 2016,arxiv:1606.06650) 这是我的代码: 将numpy导入为np 导入tensorflow作为tf 从tensorflow.keras导入图层、损耗、模型 #禁用“急切执行”可使此示例正常工作: #tf.python.framework_ops.disable_eager_execution() def get_loss_fcn(w

我正试图在
tf.Keras
(TensorFlow 2.0.0rc0)中为具有稀疏注释数据的三维U型网络实施与样本和像素相关的损失加权(Cicek 2016,arxiv:1606.06650)

这是我的代码:

将numpy导入为np
导入tensorflow作为tf
从tensorflow.keras导入图层、损耗、模型
#禁用“急切执行”可使此示例正常工作:
#tf.python.framework_ops.disable_eager_execution()
def get_loss_fcn(w):
def丢失fcn(y_真,y_pred):
损耗=w*损耗.mse(y_真,y_pred)
回波损耗
退货损失
数据x=np.random.rand(5,4,1)
数据w=np.random.rand(5,4)
数据y=np.random.rand(5,4,1)
x=层。输入([4,1])
w=层。输入([4])
y=层。激活('tanh')(x)
模型=模型。模型(输入=[x,w],输出=y)
损耗=获取损耗fcn(模型输入[1])
#使用另一个损耗也能使其起作用:
#损失='mse'
model.compile(损失=损失)
模型拟合((数据x,数据w),数据y)
打印('完成')
这在禁用急切执行时运行良好,但TensorFlow 2的一个要点是默认情况下具有急切执行。我和该目标之间的障碍是自定义丢失函数,正如您所看到的(使用
'mse'
作为丢失也会删除该错误):


还有其他想法吗?

另一种解决方案是将权重作为额外的输出特性而不是输入特性传递

这使模型完全没有任何与权重相关的内容,权重仅出现在损失函数和
.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)
一个缺点仍然是,当在
numpy.stack()
中合并
y
w
时,您需要操作(可能)大型数组,因此,我们将更喜欢TensorFlow。

另一种方法:

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))

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

如果将fit行替换为

model.fit((data_x, data_y, data_w))
因此:


此外,我发现在loss Function中实现的tf.reduce_mean、K.mean、tf.square、tf.exp等也会导致相同的错误。

您是否尝试过不使用.fit()直接进行训练,例如:@vgoklani,还没有。谢谢你的提示!问题是你失去了很多keras的便利性(即回调)。我为此提出了一个问题:你能解释一下为什么这样做吗?我有一个想法,但我不确定我是否理解它背后的概念。你是说
y\u true
是我的MWE遇到问题的张量,而不是
w
?因为我在
w
@bers中没有看到任何变化,所以我认为问题在于函数使用符号张量返回内部函数。使用返回符号张量的函数,而不是函数,因为返回的符号张量是惰性计算的。@feature\u engineer这是有道理的,但如果我这样做,我得到的是
ValueError:没有为任何变量提供梯度:[……]
-知道为什么会发生这种情况吗?
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.')