我正在Keras中制作一个普通的变分自动编码器。以下是我的尝试:
import numpy as np
from keras import backend as K
import matplotlib.pyplot as plt
from keras.models import Model
from keras.layers import Input,Dense,Lambda
from keras.datasets import mnist
from keras.objectives import binary_crossentropy
(xTrain,yTrain),(xTest,yTest)=mnist.load_data()
xTrain=xTrain.astype('float32')/255.
xTest=xTest.astype('float32')/255.
xTrain=xTrain.reshape(xTrain.shape[0],-1)
xTest=xTest.reshape(xTest.shape[0],-1)
xTrain.shape,yTrain.shape,xTest.shape,yTest.shape
hidden_dim1=256
hidden_dim2=128
z_dim=2
n_epoch=100
n_batch=512
xTrain.shape[1:]
def sampleZ(args):
mu,log_var=args
eps=K.random_normal(shape=(z_dim,),mean=0.0,stddev=1.0)
return mu+K.exp(log_var/2)*eps
def vae_loss(yPred,yTrue):
recon_loss=K.sum(K.binary_crossentropy(yPred,yTrue),axis=1)
kl_loss=0.5*K.sum(K.square(mu)+K.exp(log_var)-1-log_var,axis=1)
return recon_loss+kl_loss
encoderInput=Input(shape=(xTrain.shape[1:]))
encoder=Dense(hidden_dim1,activation='relu')(encoderInput)
encoder=Dense(hidden_dim2,activation='relu')(encoder)
mu=Dense(z_dim,activation='linear')(encoder)
log_var=Dense(z_dim,activation='linear')(encoder)
encoderModel=Model(encoderInput,encoder)
zLayer=Lambda(sampleZ,output_shape=(z_dim,)([mu,log_var])
decoder=Dense(hidden_dim2,activation='relu')(zLayer)
decoder=Dense(hidden_dim1,activation='relu')(decoder)
decoder=Dense(xTrain.shape[1],activation='sigmoid')(decoder)
vaeModel=Model(encoderInput,decoder)
vaeModel.compile(optimizer='adam',loss=vae_loss)
vaeModel.summary()
vaeModel.fit(xTrain,xTrain,epochs=n_epoch,batch_size=n_batch)
以下是型号摘要:
Model: "functional_58"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_12 (InputLayer) [(None, 784)] 0
__________________________________________________________________________________________________
dense_90 (Dense) (None, 256) 200960 input_12[0][0]
__________________________________________________________________________________________________
dense_91 (Dense) (None, 128) 32896 dense_90[0][0]
__________________________________________________________________________________________________
dense_92 (Dense) (None, 2) 258 dense_91[0][0]
__________________________________________________________________________________________________
dense_93 (Dense) (None, 2) 258 dense_91[0][0]
__________________________________________________________________________________________________
lambda_20 (Lambda) (None, 2) 0 dense_92[0][0]
dense_93[0][0]
__________________________________________________________________________________________________
dense_103 (Dense) (None, 128) 384 lambda_20[0][0]
__________________________________________________________________________________________________
dense_104 (Dense) (None, 256) 33024 dense_103[0][0]
__________________________________________________________________________________________________
dense_105 (Dense) (None, 784) 201488 dense_104[0][0]
==================================================================================================
Total params: 469,268
Trainable params: 469,268
Non-trainable params: 0
这是我在训练开始时遇到的错误:
Epoch 1/100
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
59 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
---> 60 inputs, attrs, num_outputs)
61 except core._NotOkStatusException as e:
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: dense_92/BiasAdd:0
During handling of the above exception, another exception occurred:
_SymbolicException Traceback (most recent call last)
9 frames
/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
72 raise core._SymbolicException(
73 "Inputs to eager execution function cannot be Keras symbolic "
---> 74 "tensors, but found {}".format(keras_symbolic_tensors))
75 raise e
76 # pylint: enable=protected-access
_SymbolicException: Inputs to eager execution function cannot be Keras symbolic tensors, but found [<tf.Tensor 'dense_92/BiasAdd:0' shape=(None, 2) dtype=float32>, <tf.Tensor 'dense_93/BiasAdd:0' shape=(None, 2) dtype=float32>]
有人能指导我如何解决这个问题吗?
错误是由于损失函数访问模型生成的张量,即mu
和log_var
。相反,您需要创建一个自定义训练循环(例如使用tf.GradientTape
(,或者使用模型的add_loss
方法,如下所示:
vaeModel=Model(encoderInput,decoder)
vaeModel.add_loss(vae_loss(encoderInput, decoder))
vaeModel.compile(optimizer='adam') # No need to pass any loss function to compile method