我构建了以下函数,它将一些数据作为输入,并在这些数据上运行VAE:
def VAE(data, original_dim, latent_dim, test_size, epochs):
x_train, x_test = train_test_split(data, test_size=test_size, random_state=42)
# Define the VAE architecture
#Encoder
encoder_inputs = tf.keras.Input(shape=(original_dim,))
x = layers.Dense(64, activation='relu')(encoder_inputs)
x = layers.Dense(32, activation='relu')(x)
x = layers.Dense(8, activation='relu')(x)
#--- Custom Latent Space Layer
z_mean = layers.Dense(units=latent_dim, name='Z-Mean', activation='linear')(x)
z_log_sigma = layers.Dense(units=latent_dim, name='Z-Log-Sigma', activation='linear')(x)
z = layers.Lambda(sampling, name='Z-Sampling-Layer')([z_mean, z_log_sigma, latent_dim]) # Z sampling layer
# Instantiate the encoder
encoder = tf.keras.Model(encoder_inputs, [z_mean, z_log_sigma, z], name='encoder')
#Decoder
latent_inputs = tf.keras.Input(shape=(latent_dim,))
x = layers.Dense(8, activation='relu')(latent_inputs)
x = layers.Dense(32, activation='relu')(x)
x = layers.Dense(64, activation='relu')(x)
decoder_outputs = layers.Dense(1, activation='relu')(x)
# Instantiate the decoder
decoder = tf.keras.Model(latent_inputs, decoder_outputs, name='decoder')
# Define outputs from a VAE model by specifying how the encoder-decoder models are linked
# Instantiate a VAE model
vae = tf.keras.Model(inputs=encoder_inputs, outputs=decoder(encoder(encoder_inputs)[2]), name='vae')
# Reconstruction loss compares inputs and outputs and tries to minimise the difference
r_loss = original_dim * tf.keras.losses.mse(encoder_inputs, decoder(encoder(encoder_inputs)[2])) # use MSE
# KL divergence loss compares the encoded latent distribution Z with standard Normal distribution and penalizes if it's too different
kl_loss = -0.5 * K.mean(1 + z_log_sigma - K.square(z_mean) - K.exp(z_log_sigma), axis=-1)
#VAE total loss
vae_loss = K.mean(r_loss + kl_loss)
# Add loss to the model and compile it
vae.add_loss(vae_loss)
vae.compile(optimizer='adam')
# train the model
vae.fit(x_train, x_train, epochs=epochs, validation_data=(x_test, x_test))
其中
def sampling(args):
z_mean, z_log_sigma, latent_dim = args
epsilon = K.random_normal(shape=(K.shape(z_mean)[0], latent_dim), mean=0., stddev=1., seed=42)
return z_mean + K.exp(z_log_sigma) * epsilon
我的问题是,如果我想通过使用上面的VAE生成新数据,我该如何实现呢?
如果我想对100个新数据进行采样,是否应该使用此函数
latent_mean = tf.math.reduce_mean(encoder(x_train)[2], axis=0)
latent_std = tf.math.reduce_std(encoder(x_train)[2], axis=0)
tf.random.normal(shape=(100, latent_dim), mean=latent_mean, stddev=latent_std)
或
latent_mean = tf.math.reduce_mean(encoder(x_train)[0], axis=0)
latent_std = tf.math.exp(tf.math.reduce_mean(encoder(x_train)[1], axis=0))
tf.random.normal(shape=(100, latent_dim), mean=latent_mean, stddev=latent_std)
?
基本上,我应该直接使用z_mean和z_log_sigma吗?还是应该从z推断它们?
1条答案
按热度按时间4smxwvx51#
我认为您可能希望直接使用z_mean和z_log_sigma,网络的输出不需要进一步通过均值来减少,您可能希望从以下方面进行采样:
normal(encoder(x)[0], encoder(x)[1])
,而不是取平均值和标准差的平均值。我想您已经在使用this example,但您会注意到采样层直接连接到网络的平均值和标准输出。
https://keras.io/examples/generative/vae/