目前,我偶然发现了变分自动编码器,并尝试使用 keras 让它们在 MNIST 上工作。我找到了一个教程github https://github.com/keras-team/keras/blob/master/examples/variational_autoencoder.py.
我的问题涉及以下代码行:
# Build model
vae = Model(x, x_decoded_mean)
# Calculate custom loss
xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
vae_loss = K.mean(xent_loss + kl_loss)
# Compile
vae.add_loss(vae_loss)
vae.compile(optimizer='rmsprop')
为什么使用 add_loss 而不是将其指定为编译选项?就像是vae.compile(optimizer='rmsprop', loss=vae_loss)
似乎不起作用并抛出以下错误:
ValueError: The model cannot be compiled because it has no loss to optimize.
这个函数和自定义损失函数有什么区别,我可以将其添加为 Model.fit() 的参数?
提前致谢!
P.S.:我知道 github 上有几个与此相关的问题,但其中大多数都是开放的且未评论。如果这个问题已经解决了,请分享链接!
Edit 1
我删除了向模型添加损失的行,并使用了编译函数的损失参数。现在看起来像这样:
# Build model
vae = Model(x, x_decoded_mean)
# Calculate custom loss
xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
vae_loss = K.mean(xent_loss + kl_loss)
# Compile
vae.compile(optimizer='rmsprop', loss=vae_loss)
这会引发类型错误:
TypeError: Using a 'tf.Tensor' as a Python 'bool' is not allowed. Use 'if t is not None:' instead of 'if t:' to test if a tensor is defined, and use TensorFlow ops such as tf.cond to execute subgraphs conditioned on the value of a tensor.
Edit 2
感谢@MarioZ 的努力,我找到了解决方法。
# Build model
vae = Model(x, x_decoded_mean)
# Calculate custom loss in separate function
def vae_loss(x, x_decoded_mean):
xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
vae_loss = K.mean(xent_loss + kl_loss)
return vae_loss
# Compile
vae.compile(optimizer='rmsprop', loss=vae_loss)
...
vae.fit(x_train,
x_train, # <-- did not need this previously
shuffle=True,
epochs=epochs,
batch_size=batch_size,
validation_data=(x_test, x_test)) # <-- worked with (x_test, None) before
由于某些奇怪的原因,我必须在拟合模型时显式指定 y 和 y_test 。本来,我不需要这样做。生产的样品对我来说似乎很合理。
虽然我可以解决这个问题,但我仍然不知道这两种方法的区别和缺点是什么(除了需要不同的语法之外)。有人可以给我更多的见解吗?