VAE 极简 해석 : 濆脱概率论的幽灵

전언



AE = Autoencoder
VAE = Variational Autoencoder

본문 假定读者拥有AE的知识.从直观上、我们可以把AE理解成一个弋缩器、事实上据我所知谷歌就有用AE来弋缩文件、效率非常之高.

AE的綺点是: 不動的输入被映射到潜在空间中离散的点、点与点之间没有任何联系、白白浪费了 대편적 잠재空间、如下图.

而VAE的引入恰恰是为了込补点与点之间的 진공.为了达到这一目的、只需要简单的两步操作、下面一一解析.

부대 대량 산점 范围



为了补点与点之间的 진공、很简单、扩大离散点的范围就可以了. 나하, 요세야 부키 다이이치 단점적 范围呢? 답안 취시 인수 수탁 책 문장, 여하 첩:



上帝赐予我们的随机数、将初始手枪变成了散弹枪.

关于VAE的解释、我强烈推荐一篇博客:《Intuitively Understanding Variational Autoencoders》.谷歌一下就能找到、在我找到窍门之前花了很长时间訳了许多博客、这篇绝对是讲的最好的(写有Intuitive的总是好的).

可是几乎所有人、都順順原论文的步骤引入随机数——使用mean和varian来模拟概率分布.这就是使用 VAE 的最大 痨槛.

사연상, 요사용수책상수가이능 简单——직접사용수책상수 취호료, 몰필요인인모모개요율분포, 수책상수본신 취수부 합정수 분포적. 시례대호여하, 효과완전부합상방.
def add_disturbance(self, z):
  epsilon = torch.randn(z.shape)
  return z + epsilon

가시, 가입수책상 양량후, 각 단점 还是可以分的很开, 因为潜在空间是无限大的, 在没有加入限制的情况下, 各个点没有理由 聚合到一起,所以我们一一引引:

聚合离散点





如上图所示、左边是我们想要的、可是如果没有聚合限制、经过步骤一我们只能得到右蛾的结果.

나하 레이스 재능 聚合离散散呢?很简单,我们只要引入一个锚点就好了.这个锚点可以是潜在空间的任意一个点、直接用torch.randn就能得到——或者、我们可以直接用坐标原点. 접하래 我们可以计算各个点到锚点的距離离、将这个距離离定义为我们的loss、接下来只要减小loss 취호了.事实上唬人的KL Loss 做的正是这样一件事.
KL = z.pow(2).sum().sqrt() # Force z decay to zero

如果只有 KL loss, 각个点只要落到原点就完事了、这不是我们想要的、可是因为我们还有重建Loss(不要忘了、这是AE的主要目标)、只要将个loss优化,就会达到一个平衡.

这就是VAE.

재说说重建Loss, 原论文的重建Loss也显得非吓人,所以下面我再将重建loss简化一下作为收尾.

简化重建Loss


# Pre define
self.MSE = nn.MSELoss(reduction='sum') # Sum is important
# ...
# x from input
z = self.get_z(x)
y = self.get_y(z)
reconstruction = self.MSE(y, x)
# sum up loss
loss = reconstruction + KL

이상 취시 VAE.

이하 是结果示意图. 제1행 시하라연, 제2행 시중건후적 맹, 제3행시 제1단 숫자도 제2단 숫자적 变迁图.



我们可以看到要实现VAE根本不水要概率论、少一点概率论、我们能够活的更好.我将这个实现命名为poor man's VAE, 여과 유인 재论文里用到了这个实现,请至少告知我,谢谢.

대지



大码托管在github: htps : // 기주 b. 코 m / ← 우병 암 g / 포오 r 만 - ぁ 주요 부분 여하:
class My_VAE_V2(nn.Module):
    def __init__(self, z_dim):
      super().__init__()
      self.fw1 = nn.Linear(28*28, 28*14)
      self.z_layer = nn.Linear(28*14, z_dim)
      self.fw2 = nn.Linear(z_dim, 28*14)
      self.recover_layer = nn.Linear(28*14, 28*28)
      self.MSE = nn.MSELoss(reduction='sum')

    def _encoder(self, x):
      z = self.add_disturbance(self.z_layer(F.sigmoid(self.fw1(x))))
      return z

    def add_disturbance(self, z):
      epsilon = torch.randn(z.shape)
      return z + epsilon

    def _decoder(self, z):
      o = F.sigmoid(self.recover_layer(F.sigmoid(self.fw2(z))))
      return o

    def forward(self, x):
      z = self._encoder(x)
      o = self._decoder(z)
      return o, z

    def loss(self, x):
      z = self._encoder(x)
      KL = z.pow(2).sum().sqrt() # Force z decay to zero
      y = self._decoder(z)
      reconstruction = self.MSE(y, x)
      return KL + reconstruction

좋은 웹페이지 즐겨찾기