代码是理解Vae与标准自动编码器的正确方法吗?

时间:2019-02-15 20:50:58

标签: python neural-network autoencoder

我为标准自动编码器和VAE创建了两个小型编码网络,并分别进行了绘制。只是想知道我的理解是否适用于这种小型案例。请注意,这只是一个时代,它以编码结尾。

import numpy as np
from matplotlib import pyplot as plt

np.random.seed(0)

fig, (ax,ax2) = plt.subplots(2,1)

def relu(x):
    c = np.where(x>0,x,0)
    return c


#Standard autoencoder
x = np.random.randint(0,2,[100,5])
w_autoencoder = np.random.normal(0,1,[5,2])


bottle_neck = relu(x.dot(w_autoencoder))

ax.scatter(bottle_neck[:,0],bottle_neck[:,1])

#VAE autoencoder

w_vae1 = np.random.normal(0,1,[5,2])
w_vae2 = np.random.normal(0,1,[5,2])

mu = relu(x.dot(w_vae1))
sigma = relu(x.dot(w_vae2))

epsilon_sample = np.random.normal(0,1,[100,2])

latent_space = mu+np.log2(sigma)*epsilon_sample

ax2.scatter(latent_space[:,0], latent_space[:,1],c='red')

w_vae1 = np.random.normal(0,1,[5,2])
w_vae2 = np.random.normal(0,1,[5,2])

mu = relu(x.dot(w_vae1))
sigma = relu(x.dot(w_vae2))

epsilon_sample = np.random.normal(0,1,[100,2])

latent_space = mu+np.log2(sigma)*epsilon_sample

ax2.scatter(latent_space[:,0], latent_space[:,1],c='red')

1 个答案:

答案 0 :(得分:1)

由于您的动机是“理解”,所以我应该说您处于正确的方向,并且从事此类实施工作肯定会帮助您理解。但是我坚信必须首先在书籍/论文中实现“理解”,然后才通过实现/代码来实现。

快速浏览一下,您的标准自动编码器看起来不错。您正在通过实现假设使用relu(x)潜在代码在(0,infinity)范围内。

但是,在执行VAE时,无法使用relu(x)函数获得潜在代码。这是您缺乏“理论”理解的地方。在标准VAE中,我们假定潜在代码是来自高斯分布的样本,因此我们近似估算了该高斯分布的参数,即均值和协方差。另外,我们还假设该高斯分布是阶乘的,这意味着协方差矩阵是对角线。在您的实现中,您将均值和对角协方差近似为:

mu = relu(x.dot(w_vae1))
sigma = relu(x.dot(w_vae2))

看起来不错,但是在获取示例(重新参数化技巧)时,不确定为什么要引入np.log2()。由于您使用的是ReLU()激活,因此您的sigma变量可能以0结尾,当您执行np.log2(0)时,将得到inf。我相信您会受到一些可用代码的激励:

mu = relu(x.dot(w_vae1)) #same as yours
logOfSigma = x.dot(w_vae2) #you are forcing your network to learn log(sigma)

现在,由于您逼近了sigma的对数,因此您可以允许输出为负,因为要获得sigma,您将执行类似np.exp(logOfSigma)的操作,这将确保您始终在对角协方差中获得正值矩阵。现在要进行采样,您只需执行以下操作即可:

latent_code = mu + np.exp(logOfSigma)*epsilon_sample

希望这会有所帮助!