代码是理解 Vae 与标准自动编码器的正确方法吗?
Is the code proper way of understanding Vae vs. Standard 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')
既然你的动机是"understanding",我应该说你的方向是正确的,致力于这种实现肯定有助于你的理解。但我坚信 "understanding" 必须首先在 books/papers 中实现,然后才能通过 implementation/code 实现。
快速浏览一下,您的标准自动编码器看起来不错。您正在通过您的实施假设您的 潜在代码 将在使用 relu(x)
.
的 (0,infinity) 范围内
然而,在实现 VAE 时,您无法使用 relu(x)
功能实现 潜在代码 。这是您 "theoretical" 理解缺失的地方。在标准 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
希望对您有所帮助!
我已经为标准自动编码器和 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')
既然你的动机是"understanding",我应该说你的方向是正确的,致力于这种实现肯定有助于你的理解。但我坚信 "understanding" 必须首先在 books/papers 中实现,然后才能通过 implementation/code 实现。
快速浏览一下,您的标准自动编码器看起来不错。您正在通过您的实施假设您的 潜在代码 将在使用 relu(x)
.
然而,在实现 VAE 时,您无法使用 relu(x)
功能实现 潜在代码 。这是您 "theoretical" 理解缺失的地方。在标准 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
希望对您有所帮助!