Understanding `TypeError: An op outside of the function building code is being passed a "Graph" tensor.` error

Understanding `TypeError: An op outside of the function building code is being passed a "Graph" tensor.` error

我在自定义实验框架中使用 TF2.4,并使用 mlworkflow.lazyproperty 装饰器在第一次访问时构造属性(如 tf.keras.Model())。

对于我的大部分深度学习实验,此框架运行良好,但我在实验中尝试另一个头时遇到 TypeError: An op outside of the function building code is being passed a "Graph" tensor. 错误。

我设法将问题简化为以下最小工作示例,其中在使用我的自定义对象 Head_1() 时出现错误,但在使用 Head_2(tf.keras.layers.Layer) 时它工作正常。

import numpy as np
from mlworkflow import lazyproperty

class Head_1():
    def __call__(self, inputs):
        return tf.ones((20,25))[tf.newaxis] + inputs[...,0]

class Head_2(tf.keras.layers.Layer):
    def call(self, inputs):
        return tf.ones((20,25))[tf.newaxis] + inputs[...,0]

class Experiment():
    @lazyproperty
    def model(self):
        inputs = tf.keras.Input(dtype=tf.float32, shape=(20, 25, 3))
        model = tf.keras.layers.Conv2D(5, 1)
        head = Head_1()
        logits = model(inputs)
        outputs = head(logits)
        return tf.keras.Model(inputs, outputs)

    @tf.function
    def run(self, data):
        return self.model(data, training=True)

exp = Experiment()
exp.run(np.ones((1, 20, 25, 3), dtype=np.float32))

有人可以解释为什么 Head_1 将 «_"Graph" 张量_» 传递给函数构建代码_» 之外的 «_op,而 Head_2 不这样做吗?

我不能使用 Head_2,因为我需要我的自定义对象来控制 __call__ 方法中发生的事情。

解决方案是在调用 run 之前创建模型。具体

exp = Experiment()
_ = exp.model    # creates model before first call of the tf.function
exp.run(np.ones((1, 20, 25, 3), dtype=np.float32))