Потеря кросс-энтропии вариационного автоэнкодера (xent_loss) с трехмерными сверточными слоями

Я адаптирую эту реализацию VAE https://github.com/keras-team/keras/blob/master/examples/variational_autoencoder.py, который я нашел здесь https://blog.keras.io/building-autoencoders-in-keras.html

Эта реализация не использует сверточные слои, так что все происходит, так сказать, в 1D. Моя цель - реализовать трехмерные сверточные слои в этой модели.

Однако я сталкиваюсь с несоответствием формы в функции потерь при запуске партий (которые состоят из 128 образцов):

def vae_loss(self, x, x_decoded_mean):
    xent_loss = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)
    #xent_loss.shape >> [128, 40, 20, 40, 1]
    kl_loss = - 0.5 * K.sum(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
    #kl_loss.shape >> [128]
    return K.mean(xent_loss + kl_loss) # >> error shape mismatch

Здесь уже дан ответ почти на тот же вопрос Keras - несовместимая форма вариационного автоэнкодера для модель с одномерными сверточными слоями, но я не могу понять, как экстраполировать ответ на мой случай с более сложной формой ввода.

Я пробовал это решение:

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

Но я не знаю, верное ли это решение с математической точки зрения, хотя сейчас модель работает.


person fartagaintuxedo    schedule 14.01.2018    source источник


Ответы (1)


Ваш подход правильный, но он сильно зависит от K.binary_crossentropy реализации. tensorflow и theano должны работать на вас (насколько я знаю). Чтобы сделать его более чистым и не зависящим от реализации, я предлагаю вам следующий способ:

xent_loss_vec = original_dim * metrics.binary_crossentropy(x, x_decoded_mean)
xent_loss = K.mean(xent_loss_vec, axis=[1, 2, 3, 4])
# xent_loss.shape = (128,)

Теперь вы оцениваете потери для каждого вокселя, и благодаря этому каждая допустимая реализация binary_crossentropy должна работать для вас нормально.

person Marcin Możejko    schedule 14.01.2018
comment
Это имело большой смысл, когда я читал ваш ответ, но на самом деле теперь он выдает мне эту ошибку в этой строке: xent_loss = K.mean(xent_loss_vec, axis=[1, 2, 3, 4]) error ›› ValueError: Invalid reduction dimension 4 for input with 4 dimensions. for 'custom_variational_layer_7/Mean_1' (op: 'Mean') with input shapes: [?,40,20,40], [4] and with computed input tensors: input[1] = <1 2 3 4> Хотя это работает примерно так: xent_loss = K.mean(xent_loss_vec, axis=-1) но опять же, правильно ли это математически? - person fartagaintuxedo; 15.01.2018
comment
Странный. Попробуйте установить axis=[1, 2, 3]. - person Marcin Możejko; 15.01.2018