Tensorflow 急切执行函数的输入不能作为带有变分自动编码器的符号张量

Tensorflow 急切执行函数的输入不能作为带有变分自动编码器的符号张量,tensorflow,keras,Tensorflow,Keras,我正在尝试实现一个定制的可变自动编码器。代码如下所示 image = Input(shape = (X_train.shape[1])) label = Input(shape = (Y_train.shape[1])) inputs = Concatenate()([image, label]) x = Dense(625, activation = 'relu')(inputs) x = Reshape((25,25,1))(x) x = LocallyConnected2D(8, (

我正在尝试实现一个定制的可变自动编码器。代码如下所示

image = Input(shape = (X_train.shape[1]))
label = Input(shape = (Y_train.shape[1]))

inputs = Concatenate()([image, label])

x = Dense(625, activation = 'relu')(inputs)
x = Reshape((25,25,1))(x)

x = LocallyConnected2D(8, (5,5), padding = 'valid')(x)
x = LeakyReLU()(x)

x = LocallyConnected2D(8, (5,5), padding = 'valid')(x)
x = LeakyReLU()(x)

x = LocallyConnected2D(8, (3,3), padding = 'valid')(x)
x = LeakyReLU()(x)

x = LocallyConnected2D(8, (3,3), padding = 'valid')(x)
x = LeakyReLU()(x)

x = AveragePooling2D((2, 2))(x)

encoder_out = Flatten()(x)

mu = Dense(latent_size, activation ='linear')(encoder_out)
sigma = Dense(latent_size, activation = 'linear')(encoder_out)

def sampling(args):
    mu, sigma = args
    eps = K.random_normal(shape=(batch_size, latent_size), mean=0., stddev=1.)
    return mu + K.exp(sigma / 2) * eps

latent_space = Lambda(sampling, output_shape = (latent_size, ))([mu, sigma])

decoder_latent = Input(shape = (latent_size, ))
decoder_c = Input(shape = (c_space, ))

x = Concatenate()([decoder_latent, decoder_c])

x = Dense(288)(x)
x = Reshape((6,6,8))(x)
x = ZeroPadding2D((2,2))(x)
x = LocallyConnected2D(8, (3,3), padding = 'valid')(x)
x = LeakyReLU()(x)

x = ZeroPadding2D((2,2))(x)
x = LocallyConnected2D(8, (3,3), padding = 'valid')(x)
x = LeakyReLU()(x)

x = UpSampling2D(size = (2,2))(x)
x = LocallyConnected2D(8, (5,5), padding = 'valid')(x)
x = LeakyReLU()(x)

x = UpSampling2D(size = (2,2))(x)
x = LocallyConnected2D(8,(5,5), padding = 'valid')(x)
x = LeakyReLU()(x)

x = LocallyConnected2D(1,(4,4), padding = 'valid')(x)
decoder_out = Activation('relu')(x)
我定义的损失函数是

def DFC_loss(x_in, x_out):
    kl_loss = 0.5 * K.sum(K.exp(sigma) + K.square(mu) - 1. - sigma, axis=1)
    return K.mean(perceptual_loss(x_in, x_out) + kl_loss)

def perceptual_loss(x_in, x_out):
    
    x_in = K.reshape(x_in, shape=(batch_size, 25,25,1))
    x_out = K.reshape(x_out, shape=(batch_size, 25,25,1))
    
    conv_outputs = [classifier.get_layer(l).output for l in selected_layers]
    
    activation = Model(classifier.input, conv_outputs)

    h1_list = activation(x_in)
    h2_list = activation(x_out)
    
    rc_loss = 0.0
    
    for h1, h2, weight in zip(h1_list, h2_list, [1.0, 1.0]):
        h1 = K.batch_flatten(h1)
        h2 = K.batch_flatten(h2)
        rc_loss = rc_loss + weight * K.sum(K.square(h1 - h2), axis=-1)
    
    return rc_loss

CVAE.compile(optimizer = "adam", loss = DFC_loss, metrics = [perceptual_loss])
每当我运行下面的代码时

CVAE_hist = CVAE.fit([X_train,Y_train], X_train, verbose = 1, batch_size=batch_size, epochs=n_epochs, validation_data = ([X_test, Y_test], X_test))
我有两个错误

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: dense_2_1/Identity:0

到急切执行函数的
输入不能作为符号张量,但可以找到[,]

有趣的是,每当我将损失函数单独设置为知觉损失,而没有Kl散度损失时,我的代码没有收到错误。对于变分自动编码器,有许多KL发散损失的实现,但我不知道为什么它不能与这个特定的实现一起工作。

我已经有了很长时间的相同问题,但我设法解决了它。 问题是TF只接受损失函数,这些函数接受
(输入、输出)
参数,然后进行比较。然而,您也在使用基本上是密集层的
mu
sigma
计算(kl_)损失。在tensorflow v2.1之前,它神奇地知道这些参数是什么,知道如何包含/操作它们,但从那时起,您必须更加小心。阅读后(编辑:也可以滚动到页面底部查看完整的VAE示例),我建议对代码进行以下更改:

1。编译模型时,仅将感知损失定义为损失:

CVAE.compile(optimizer=“adam”,loss=perceptive\u loss,metrics=[perceptive\u loss])

2。将
sampling
函数更改为一个类,然后在
call
方法下添加
kl\u loss
,类似于

class Sampling(keras.layers.Layer):
    def __init__(self):
        super(Sampling, self).__init__()

    def build(self, input_shape):
        _, sigma_shape = input_shape
        self.sigma_shape = (sigma_shape[-1], )

    def call(self, inputs):
        mu, sigma = inputs

        # Add loss
        kl_loss = 0.5 * K.sum(K.exp(sigma) + K.square(mu) - 1. - sigma, axis=1)
        self.add_loss(K.mean(kl_loss))
        
        # Return sampling as before
        eps = K.random_normal(self.sigma_shape, mean=0., stddev=1.)
        return mu + K.exp(sigma / 2) * eps
确保只添加
kl_损失
而不是
DFC_损失
,这样就不会计算
感知损失
两次

3。使用
采样
类作为潜在层

潜在_空间=采样()([mu,sigma])

这是我的第一个答案,希望有帮助


另外,您也可以尝试通过
add\u loss
命令在采样类中移动这两个损失,然后在不使用任何
loss
参数的情况下进行编译。

我已经有很长一段时间遇到相同的问题,但还是设法解决了。 问题是TF只接受损失函数,这些函数接受
(输入、输出)
参数,然后进行比较。然而,您也在使用基本上是密集层的
mu
sigma
计算(kl_)损失。在tensorflow v2.1之前,它神奇地知道这些参数是什么,知道如何包含/操作它们,但从那时起,您必须更加小心。阅读后(编辑:也可以滚动到页面底部查看完整的VAE示例),我建议对代码进行以下更改:

1。编译模型时,仅将感知损失定义为损失:

CVAE.compile(optimizer=“adam”,loss=perceptive\u loss,metrics=[perceptive\u loss])

2。将
sampling
函数更改为一个类,然后在
call
方法下添加
kl\u loss
,类似于

class Sampling(keras.layers.Layer):
    def __init__(self):
        super(Sampling, self).__init__()

    def build(self, input_shape):
        _, sigma_shape = input_shape
        self.sigma_shape = (sigma_shape[-1], )

    def call(self, inputs):
        mu, sigma = inputs

        # Add loss
        kl_loss = 0.5 * K.sum(K.exp(sigma) + K.square(mu) - 1. - sigma, axis=1)
        self.add_loss(K.mean(kl_loss))
        
        # Return sampling as before
        eps = K.random_normal(self.sigma_shape, mean=0., stddev=1.)
        return mu + K.exp(sigma / 2) * eps
确保只添加
kl_损失
而不是
DFC_损失
,这样就不会计算
感知损失
两次

3。使用
采样
类作为潜在层

潜在_空间=采样()([mu,sigma])

这是我的第一个答案,希望有帮助

另外,您也可以尝试通过
add_loss
命令在采样类中移动这两个损失,然后在不使用任何
loss
参数的情况下进行编译