变分自动编码器:Keras 中的实现预热

Posted

技术标签:

【中文标题】变分自动编码器:Keras 中的实现预热【英文标题】:Variationnal auto-encoder: implementing warm-up in Keras 【发布时间】:2017-08-04 20:37:11 【问题描述】:

我最近阅读了this paper,其中介绍了一个称为“预热”(WU)的过程,该过程包括将 KL 散度中的损失乘以一个变量,该变量的值取决于 epoch 的数量(它从0到1)

我想知道这是不是这样做的好方法:

beta = K.variable(value=0.0)

def vae_loss(x, x_decoded_mean):
    # cross entropy
    xent_loss = K.mean(objectives.categorical_crossentropy(x, x_decoded_mean))

    # kl divergence
    for k in range(n_sample):
        epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.,
                              std=1.0)  # used for every z_i sampling
        # Sample several layers of latent variables
        for mean, var in zip(means, variances):
            z_ = mean + K.exp(K.log(var) / 2) * epsilon

            # build z
            try:
                z = tf.concat([z, z_], -1)
            except NameError:
                z = z_
            except TypeError:
                z = z_

            # sum loss (using a MC approximation)
            try:
                loss += K.sum(log_normal2(z_, mean, K.log(var)), -1)
            except NameError:
                loss = K.sum(log_normal2(z_, mean, K.log(var)), -1)
        print("z", z)
        loss -= K.sum(log_stdnormal(z) , -1)
        z = None
    kl_loss = loss / n_sample
    print('kl loss:', kl_loss)

    # result
    result = beta*kl_loss + xent_loss
    return result

# define callback to change the value of beta at each epoch
def warmup(epoch):
    value = (epoch/10.0) * (epoch <= 10.0) + 1.0 * (epoch > 10.0)
    print("beta:", value)
    beta = K.variable(value=value)

from keras.callbacks import LambdaCallback
wu_cb = LambdaCallback(on_epoch_end=lambda epoch, log: warmup(epoch))


# train model
vae.fit(
    padded_X_train[:last_train,:,:],
    padded_X_train[:last_train,:,:],
    batch_size=batch_size,
    nb_epoch=nb_epoch,
    verbose=0,
    callbacks=[tb, wu_cb],
    validation_data=(padded_X_test[:last_test,:,:], padded_X_test[:last_test,:,:])
)

【问题讨论】:

看起来可以。虽然我认为here 的答案可能更简洁一些:发送你的回调 beta 参数,这样你就不必像上面那样将它保持为全局。 谢谢你我没看到那个帖子 【参考方案1】:

这行不通。我对其进行了测试以弄清楚它为什么不起作用。要记住的关键是 Keras 在训练开始时会创建一个静态图。

因此,vae_loss 函数只被调用一次来创建损失张量,这意味着每次计算损失时对beta 变量的引用都将保持不变。但是,您的 warmup 函数将 beta 重新分配给新的 K.variable。因此,用于计算损失的beta 与更新后的beta 不同,其值始终为0。

这是一个简单的修复。只需在 warmup 回调中更改此行:

beta = K.variable(value=value)

到:

K.set_value(beta, value)

这样beta 中的实际值会“就地”更新,而不是创建新变量,并且会正确重新计算损失。

【讨论】:

别忘了设置beta._trainable = False!否则,学习算法。操纵变量,学习变得不稳定。目前,只有“脏”的私有变量 manip。可用。参考:github.com/tensorflow/tensorflow/issues/31089 @Tik0 我认为没有必要。我尝试为当前的 Keras VAE 示例 (gist.github.com/pnb/0b66a49e40f18b9c77f2ade7cc5b039c) 添加预热,似乎beta 的值在训练期间没有改变。不过,设置_trainable = False 也无妨! @Nigel 我将其用作tensorflow_probability.layers.KLDivergenceRegularizer(prior, weight=beta)。除非我设置beta._trainable=False,否则它会包含在“可训练参数”计数中。我没有测试,但我猜如果没有_trainable=False,它会更新每个批次,然后在每个时期结束时重置为确定性值。

以上是关于变分自动编码器:Keras 中的实现预热的主要内容,如果未能解决你的问题,请参考以下文章

变分自动编码器损失函数(keras)

基于变分自动编码器(Variational Autoencoders)疾病预测系统实战:(Keras实现并可视化训练和验证误差最后给出topK准确率和召回率)

用于时间序列异常检测的 Keras LSTM-VAE(变分自动编码器)

用于可变长度序列的 LSTM 变分自动编码器

PyTorch实现简单的变分自动编码器VAE

python 一个简单的变分自动编码器实现