Debugging 如何在TensorFlow和Keras中打印损失函数中的中间变量?

Debugging 如何在TensorFlow和Keras中打印损失函数中的中间变量?,debugging,tensorflow,keras,Debugging,Tensorflow,Keras,我正在编写一个自定义目标来训练Keras(带有TensorFlow后端)模型,但我需要调试一些中间计算。为简单起见,假设我有: def custom_loss(y_pred, y_true): diff = y_pred - y_true return K.square(diff) 我找不到一个简单的方法来访问,例如,中间变量diff或它在训练期间的形状。在这个简单的例子中,我知道我可以返回diff来打印它的值,但是我的实际损失更为复杂,我不能返回中间值而不出现编译错误 有没有

我正在编写一个自定义目标来训练Keras(带有TensorFlow后端)模型,但我需要调试一些中间计算。为简单起见,假设我有:

def custom_loss(y_pred, y_true):
    diff = y_pred - y_true
    return K.square(diff)
我找不到一个简单的方法来访问,例如,中间变量diff或它在训练期间的形状。在这个简单的例子中,我知道我可以返回diff来打印它的值,但是我的实际损失更为复杂,我不能返回中间值而不出现编译错误


有没有一种简单的方法来调试Keras中的中间变量?

据我所知,Keras中并没有解决这个问题,所以您必须求助于后端特定的功能。和都有
Print
节点,这些节点是标识节点(即,它们返回输入节点),并且具有打印输入(或输入的某些张量)的副作用

Theano的示例:

diff = y_pred - y_true
diff = theano.printing.Print('shape of diff', attrs=['shape'])(diff)
return K.square(diff)
TensorFlow示例:

diff = y_pred - y_true
diff = tf.Print(diff, [tf.shape(diff)])
return K.square(diff)

请注意,这仅适用于中间值。Keras期望传递到其他层的张量具有特定属性,例如
\u Keras\u shape
。由后端处理的值,即通过
打印
,通常不具有该属性。为了解决这个问题,您可以将调试语句包装在一个层中,例如。

在TensorFlow 2中,您现在可以在TensorFlow Keras模型/层/损失中添加IDE断点,包括在使用拟合、评估和预测方法时。但是,您必须在调用
model.compile()
之后添加
model.run\u急切地=True
,以便调试器在断点处提供张量值。比如说,

import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam

def custom_loss(y_pred, y_true):
    diff = y_pred - y_true
    return tf.keras.backend.square(diff)  # Breakpoint in IDE here. =====

class SimpleModel(Model):

    def __init__(self):
        super().__init__()
        self.dense0 = Dense(2)
        self.dense1 = Dense(1)

    def call(self, inputs):
        z = self.dense0(inputs)
        z = self.dense1(z)
        return z

x = tf.convert_to_tensor([[1, 2, 3], [4, 5, 6]], dtype=tf.float32)
y = tf.convert_to_tensor([0, 1], dtype=tf.float32)

model0 = SimpleModel()
model0.run_eagerly = True
model0.compile(optimizer=Adam(), loss=custom_loss)
y0 = model0.fit(x, y, epochs=1)  # Values of diff *not* shown at breakpoint. =====

model1 = SimpleModel()
model1.compile(optimizer=Adam(), loss=custom_loss)
model1.run_eagerly = True
y1 = model1.fit(x, y, epochs=1)  # Values of diff shown at breakpoint. =====
这也适用于调试中间网络层的输出(例如,在SimpleModel的
调用中添加断点)


注意:这是在TensorFlow
2.0.0-rc0中测试的。在TensorFlow 2.0中,您可以使用和打印损失函数定义内的任何内容。您还可以执行类似于
tf.print(“my_intermediate\u tensor=,my_intermediate\u tensor)
的操作,即使用消息,类似于Python的
print
。但是,您可能需要使用来装饰损失函数,以实际查看tf.print的结果。要添加到@nemo,Keras通过
K.print_tensor()
&,将这些后端打印函数扩展到Keras中。我没有尝试使用
print\u tensor()
函数,但正如@nemo所指出的,您必须将它与
Lambda
layerOh一起使用。是的,忘记了它的存在。但是如果你想要一些不同于张量的完整字符串表示的东西,例如形状,这对你没有帮助。谢谢,但是tf.Print和K.Print\u张量似乎都不会自己打印任何东西,如果我用标准python打印包住它们,例如Print(tf.Print(diff,[tf.shape(diff)])它只在模型编译阶段执行一次,而不是在运行阶段(在培训期间)执行一次好的,我的错误,我没有将打印输出分配给另一个操作,以防止在图形评估期间对其进行评估。谢谢!也可以做类似的事情来显示网络各层的激活情况(不仅仅是损失值或任何损失中间值)?@nbro,是的。但是,您需要编写带有显式调用函数的模型。在这里可以看到我的相关答案:但我不想将
模型子类化。我想将调试器与内置层一起使用。@nbro,
Dense
层是内置层。您当前是否正在使用
顺序
类?
Sequential
Model
之间唯一(主要)的区别在于
Sequential
为您设置了
调用
方法。如果您正在谈论其他内容,我可能需要更多的细节。我目前正在使用函数式API(但稍后可能会切换回顺序API)。无论如何,我只想在每个历元的开始(或结束)打印中间层(或任何其他内容,如模型的
loss
属性)的输出值。但是,我不能使用
tf.print
。看见如果我使用Python的
print
,它不会打印张量的实际值,而只打印符号表示。请注意,我使用的是TF2.0。你能提供一个详细的代码段吗?大多数都是新手,在这里提问是因为互联网上的示例很差