【问题标题】:Keras, Tensorflow: How to set breakpoint (debug) in custom layer when evaluating?Keras,Tensorflow:评估时如何在自定义层中设置断点(调试)?
【发布时间】:2019-01-11 08:43:33
【问题描述】:

我只想在自定义层内做一些数值验证。

假设我们有一个非常简单的自定义层:

class test_layer(keras.layers.Layer):
    def __init__(self, **kwargs):
        super(test_layer, self).__init__(**kwargs)

    def build(self, input_shape):
        self.w = K.variable(1.)
        self._trainable_weights.append(self.w)
        super(test_layer, self).build(input_shape)

    def call(self, x, **kwargs):
        m = x * x            # Set break point here
        n = self.w * K.sqrt(x)
        return m + n

还有主程序:

import tensorflow as tf
import keras
import keras.backend as K

input = keras.layers.Input((100,1))
y = test_layer()(input)

model = keras.Model(input,y)
model.predict(np.ones((100,1)))

如果我在m = x * x这一行设置断点调试,程序在执行y = test_layer()(input)的时候会在这里暂停,这是因为图建好了,调用了call()方法。

但是当我使用model.predict() 赋予它真正的价值,并想看看它是否正常工作时,它不会在m = x * x 行暂停

我的问题是:

  1. call() 方法是否仅在构建计算图时调用? (喂真值时不会调用?)

  2. 如何在层内调试(或在何处插入断点)以在输入实值时查看变量的值?

【问题讨论】:

    标签: python tensorflow keras pycharm


    【解决方案1】:
    1. 是的。 call() 方法仅用于构建计算图。

    2. 关于调试。我更喜欢使用TFDBG,这是推荐的tensorflow调试工具,虽然它不提供断点功能。

    对于 Keras,您可以将这些行添加到您的脚本中以使用 TFDBG

    import tf.keras.backend as K
    from tensorflow.python import debug as tf_debug
    sess = K.get_session()
    sess = tf_debug.LocalCLIDebugWrapperSession(sess)
    K.set_session(sess)
    

    【讨论】:

    • 注意,Tensorflow 2.0 不再直接暴露 backend.get_session --> 即 K.get_session()。但是我们必须使用 --> import tensorflow.python.keras.backend as K --> sess = K.get_session() 来代替。
    • 请问,在执行完这些行之后,我们是否必须在需要进行调试的任何地方运行 sess 才能获得输出?
    【解决方案2】:

    在 TensorFlow 2 中,您现在可以向 TensorFlow Keras 模型/层添加断点,包括在使用拟合、评估和预测方法时。但是,您必须在调用model.compile() 之后添加model.run_eagerly = True 以使张量的值在断点处的调试器中可用。例如,

    import tensorflow as tf
    from tensorflow.keras.layers import Dense
    from tensorflow.keras.losses import BinaryCrossentropy
    from tensorflow.keras.models import Model
    from tensorflow.keras.optimizers import Adam
    
    
    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)  # Breakpoint in IDE here. =====
            return z
    
    x = tf.convert_to_tensor([[1, 2, 3], [4, 5, 6]], dtype=tf.float32)
    
    model0 = SimpleModel()
    y0 = model0.call(x)  # Values of z shown at breakpoint. =====
    
    model1 = SimpleModel()
    model1.run_eagerly = True
    model1.compile(optimizer=Adam(), loss=BinaryCrossentropy())
    y1 = model1.predict(x)  # Values of z *not* shown at breakpoint. =====
    
    model2 = SimpleModel()
    model2.compile(optimizer=Adam(), loss=BinaryCrossentropy())
    model2.run_eagerly = True
    y2 = model2.predict(x)  # Values of z shown at breakpoint. =====
    

    注意:这是在 TensorFlow 2.0.0-rc0 中测试的。

    【讨论】:

    • 训练时如何显示数值,即Model.fit_generator()
    • @abacusreader, fit_generator 的工作方式与我展示的代码中的第三个示例相同。请注意,您需要显式 call 函数中的断点(您不能使用类似 Sequential 的隐式 call 之类的东西,因为您无法添加断点)。
    猜你喜欢
    • 2019-04-13
    • 2019-07-29
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 2019-08-06
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    相关资源
    最近更新 更多