Keras VAE 示例损失函数

数据挖掘 喀拉斯 自动编码器
2022-03-16 07:25:00

这里的代码:

https://github.com/keras-team/keras/blob/master/examples/variational_autoencoder.py

特别是第 53 行:

xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)

为什么交叉熵乘以original_dim? 另外,这个函数是否只计算批处理维度的交叉熵(我注意到没有axis输入)?从文档中很难判断...

2个回答

Keras metrics.binary_crossentropy 计算所有输入的平均交叉熵(伪代码):

original_dim = 3 
x = [1,1,0]
x_decoded = [0.2393,0.7484,-1.1399]

average_BCE = binary_crossentropy(x, x_decoded)
print(average_BCE)
>>>0.1186

对于这部分自动编码器损失,我们需要总和,而不是输入和输出像素之间所有平方差的平均值,这相当于 average_crossentropy_of_pixels * num_pixels (original_dim)

print(original_dim * average_BCE)
>>>0.3559

编写这部分的另一种方式是(我认为这更能说明正在发生的事情,但在 Keras 领域可能表现不佳):

xent_loss = K.sum(K.square(x - sigmoid(x_decoded)))
print(xent_loss)
>>>0.3559

关于第二部分,由于您真正要做的第一个操作是减法,这意味着输入和输出的张量大小相同。如果您检查实现代码(在这种情况下比文档更好),可以找到这一点 - 转到第 3056 行: https://github.com/keras-team/keras/blob/master/keras/backend/tensorflow_backend。 py

# Do Keras' binary cross entropy
x = Input(shape=(3,))
x_decoded = Input(shape=(3,))  
bce = metrics.binary_crossentropy(x,x_decoded)
sess = K.get_session()
with sess.as_default():
    print(bce.eval(feed_dict={x: np.array([[1,1,0]]),
                              x_decoded: np.array([[0.2393,0.7484,-1.1399]])}))

# Do the same thing in numpy directly
epsilon = 1e-7
x = np.array([1,1,0]) 
x_decoded = np.array([0.2393,0.7484,-1.1399])

output = np.clip(x_decoded, epsilon, 1-epsilon)
output = -x * np.log(output) - (1 - x) * np.log(1 - output)
print(np.mean(output, axis=-1))

输出:

[0.57328504]
0.5732850228833389

所以问题是mean. 它应该是一个sum. 而且我猜他们会做一些事情epsilon来防止可能导致爆炸的奇怪边缘情况。