【问题标题】:tensorflow/keras "An op outside of the function building code is being passed a 'Graph' Tensor"tensorflow/keras“函数构建代码之外的操作正在传递一个‘图形’张量”
【发布时间】:2020-12-24 05:17:11
【问题描述】:

我是 Tensorflow/Keras 的新手,我一直在关注《使用 Scikit-Learn 和 Tensorflow 进行机器学习实践》一书。第 12 章涉及自定义 Tensorflow,以及相关的笔记本 (here) 我已经找到了以下自定义模型:

class ReconstructingRegressor(keras.models.Model):
    def __init__(self, output_dim, **kwargs):
        super().__init__(**kwargs)
        self.hidden = [keras.layers.Dense(30, activation="selu",
                                          kernel_initializer="lecun_normal")
                       for _ in range(5)]
        self.out = keras.layers.Dense(output_dim)

    def build(self, batch_input_shape):
        n_inputs = batch_input_shape[-1]
        self.reconstruct = keras.layers.Dense(n_inputs)
        super().build(batch_input_shape)
        
    def call(self, inputs, training=None):
        Z = inputs
        for layer in self.hidden:
            Z = layer(Z)
        reconstruction = self.reconstruct(Z)

        recon_loss = tf.reduce_mean(tf.square(reconstruction - inputs))        
        self.add_loss(0.05 * recon_loss)

        return self.out(Z)

当我使用此模型进行训练时,我收到以下错误:

TypeError: An op outside of the function building code is being passed
a "Graph" tensor. It is possible to have Graph tensors
leak out of the function building context by including a
tf.init_scope in your function building code.
For example, the following function will fail:
  @tf.function
  def has_init_scope():
    my_constant = tf.constant(1.)
    with tf.init_scope():
      added = my_constant * 2
The graph tensor has name: mul:0

问题是self.add_loss(0.05 * recon_loss);在评论说一切运行良好之后。大概recon_loss"Graph" tensorself.add_loss()op outside of the function building code,但是——如果这适用于add_loss()——我不知道我将如何从call() 中增加损失。

完全披露:当我在编写本书时考虑到 2.1 时,我使用的是 Tensorflow 2.3,所以我并没有真正遵循说明。也就是说,我真的很好奇如何解决这个问题,以我目前的知识水平,我觉得基本上无能为力。它似乎应该可以工作——否则如何添加到损失函数中?任何帮助将不胜感激。

完整示例:

import tensorflow as tf
from tensorflow import keras

from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

housing = fetch_california_housing()
X_train_full, X_test, y_train_full, y_test = train_test_split(
    housing.data, housing.target.reshape(-1, 1), random_state=42)
X_train, X_valid, y_train, y_valid = train_test_split(
    X_train_full, y_train_full, random_state=42)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_valid_scaled = scaler.transform(X_valid)
X_test_scaled = scaler.transform(X_test)

class ReconstructingRegressor(keras.models.Model):
    def __init__(self, output_dim, **kwargs):
        super().__init__(**kwargs)
        self.hidden = [keras.layers.Dense(30, activation="selu",
                                          kernel_initializer="lecun_normal")
                       for _ in range(5)]
        self.out = keras.layers.Dense(output_dim)

    def build(self, batch_input_shape):
        n_inputs = batch_input_shape[-1]
        self.reconstruct = keras.layers.Dense(n_inputs)
        super().build(batch_input_shape)
        
    def call(self, inputs, training=None):
        Z = inputs
        for layer in self.hidden:
            Z = layer(Z)
        reconstruction = self.reconstruct(Z)
        recon_loss = tf.reduce_mean(tf.square(reconstruction - inputs))
        
        self.add_loss(0.05 * recon_loss)

        return self.out(Z)

model = ReconstructingRegressor(1, dynamic=True)
model.compile(loss="mse", optimizer="nadam")
history = model.fit(X_train_scaled, y_train, epochs=2)

【问题讨论】:

    标签: python tensorflow keras


    【解决方案1】:

    虽然我认为现在回答这个问题为时已晚...让我向您展示我的尝试。

    首先,我删除了自定义模型的构建功能。

        def build(self, batch_input_shape):
            n_inputs = batch_input_shape[-1]
            self.reconstruct = keras.layers.Dense(n_inputs)
            super().build(batch_input_shape)
    

    编译时run_eagerly = True 使用自定义层计算自定义损失有效。 例如,编写自定义层代码:

    class ReconLoss(keras.layers.Layer):
      def __init__(self, **kwargs):
        super().__init__(**kwargs)
    
      def call(self, inputs):
        x, reconstruction = inputs
        recon_loss = tf.reduce_mean(tf.square(reconstruction - x))
    
        self.add_loss(0.05 * recon_loss)
    
        return
    

    然后在自定义模型的__init__中为其赋值一个实例,将self.ReconLoss([x, reconstruction])插入自定义模型的调用方法中。

    编辑 colab 代码:https://colab.research.google.com/drive/1Hwi6auz2meKvD0ogdDSywb2E4_J1F9S_?usp=sharing

    我仍然不明白为什么会出现错误,但这对我有用。


    参考 :

    【讨论】:

      猜你喜欢
      • 2020-06-18
      • 2021-09-27
      • 2020-09-30
      • 2020-02-22
      • 1970-01-01
      • 2019-12-08
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      相关资源
      最近更新 更多