栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

CVAE (条件 变分 自动编码器)

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CVAE (条件 变分 自动编码器)

notations

  • x x x image
  • z z z latent
  • y y y label (omitted to lighten notation)
  • p ( x ∣ z ) p(x|z) p(x∣z) decoder Encoder
  • q ( z ∣ x ) q(z|x) q(z∣x) encoder Decoder
  • p ^ ( h ) hat{p}(h) p^​(h) prior encoder (by variational inference) PriorEncoder

model structure

class CVAE(nn.Module):
    def __init__(self, config):
        super(CVAE, self).__init__()
        self.encoder = Encoder(...)
        self.decoder = Decoder(...)
        self.priorEncoder = PriorEncoder(...)
    def forward(self, x, y):
        x = x.reshape((-1, 784)) # MNIST
        mu, sigma = self.encoder(x, y)
        prior_mu, prior_sigma = self.priorEncoder(y)
        z = torch.randn_like(mu)
        z = z * sigma + mu
        reconstructed_x = self.decoder(z, y)
        reconstructed_x = reconstructed_x.reshape((-1, 28, 28))
        return reconstructed_x, mu, sigma, prior_mu, prior_sigma
    def infer(self, y):
        prior_mu, prior_sigma = self.priorEncoder(y)
        z = torch.randn_like(prior_mu)
        z = z * prior_sigma + prior_mu
        reconstructed_x = self.decoder(z, y)
        return reconstructed_x
#
class Loss(nn.Module):
    def __init__(self):
        super(Loss,self).__init__()
        self.loss_fn = nn.MSELoss(reduction='mean')
        self.kld_loss_weight = 1e-5
    def forward(self, x, reconstructed_x, mu, sigma, prior_mu, prior_sigma):
        mse_loss = self.loss_fn(x, reconstructed_x)
        kld_loss = torch.log(prior_sigma / sigma) + (sigma**2 + (mu - prior_mu)**2) / (2 * prior_sigma**2) - 0.5
        kld_loss = torch.sum(kld_loss) / x.shape[0]
        loss = mse_loss + self.kld_loss_weight * kld_loss
        return loss
#
def train(model, criterion, optimizer, data_loader, config):
    train_task_time_str = time_str()
    for epoch in range(config.num_epoch):
        loss_seq = []
        for step, (x,y) in tqdm(enumerate(data_loader)):
            # --------------------   data   --------------------
            x = x.to(device)
            y = y.to(device)
            # -------------------- forward  --------------------
            reconstructed_x, mu, sigma, prior_mu, prior_sigma = model(x, y)
            loss = criterion(x, reconstructed_x, mu, sigma, prior_mu, prior_sigma)
            # --------------------   log    --------------------
            loss_seq.append(loss.item())
            # -------------------- backward --------------------
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            # --------------------   end    --------------------
        logging.info(f'epoch {epoch:^5d} loss {sum(loss_seq[-config.batch_size:]) / config.batch_size:.5f}')
        with torch.no_grad():
            # --------------------   file   --------------------
            path = f'{config.save_fig_path}/{train_task_time_str}' # type(model).__name__
            if not os.path.exists(path):
                os.makedirs(path)
            path += f'/epoch{epoch:04d}.png'
            # --------------------  figure  --------------------
            plt.close()
            fig, axs = plt.subplots(nrows=1, ncols=10, figsize=(10, 2), dpi=512)
            fig.suptitle(f'epoch {epoch} loss {sum(loss_seq[-config.batch_size:]) / config.batch_size:.5f}')
            # --------------------  infer   --------------------
            y = torch.Tensor(list(range(config.num_class)))
            y = y.to(dtype=torch.int64)
            y = nn.functional.one_hot(y, num_classes=config.num_class)
            y = y.to(dtype=torch.float)
            y = y.to(device)
            x = model.infer(y)
            x = x.cpu()
            x = x.numpy()
            x += x.min()
            x /= x.max()
            x *= 255
            x = x.astype(np.uint8)
            # --------------------   plot   --------------------
            for idx,ax,arr in zip(range(config.num_class),axs,x):
                ax.set_title(str(idx))
                ax.axis('off')
                ax.imshow(arr.reshape((28,28)), cmap='BuGn')
            # --------------------   save   --------------------
            # plt.show()
            plt.savefig(path)
            # --------------------   end    --------------------
#

dynamics

  • SGVB (stochastic_gradient + variational_bayesian) 框架根据 EM算法的原理 使用 变分推断 优化 ELBO.
  • log ⁡ p ( v ) = E L B O ( q ( z ∣ x ) , p ( x ∣ z ) ) + K L ( q ( z ∣ x ) ∥ p ( z ∣ x ) ) log p(v) = mathrm{ELBO} left( q(z|x), p(x|z) right) + mathrm{KL} left( q(z|x) | p(z|x) right) logp(v)=ELBO(q(z∣x),p(x∣z))+KL(q(z∣x)∥p(z∣x)) ELBO 是 对数似然 的代理.
  • E L B O = E q ( z ∣ x ) [ log ⁡ p ( x ∣ z ) p ( z ) ] + E n t r o p y ( q ( z ∣ x ) ) = E q ( z ∣ x ) [ log ⁡ p ( x ∣ z ) ] − K L ( q ( z ∣ x ) ∥ p ( z ) ) mathrm{ELBO} = mathop{mathbb{E}} limits_{q(z|x)} left[ log p(x|z)p(z) right] + mathrm{Entropy} left( q(z|x) right) = mathop{mathbb{E}} limits_{q(z|x)} left[ log p(x|z) right] - mathrm{KL} left( q(z|x) | p(z) right) ELBO=q(z∣x)E​[logp(x∣z)p(z)]+Entropy(q(z∣x))=q(z∣x)E​[logp(x∣z)]−KL(q(z∣x)∥p(z))
    • E q ( z ∣ x ) [ log ⁡ p ( x ∣ z ) p ( z ) ] + E n t r o p y ( q ( z ∣ x ) ) mathop{mathbb{E}} limits_{q(z|x)} left[ log p(x|z)p(z) right] + mathrm{Entropy} left( q(z|x) right) q(z∣x)E​[logp(x∣z)p(z)]+Entropy(q(z∣x)) 用于证明EM算法的原理.
    • E q ( z ∣ x ) [ log ⁡ p ( x ∣ z ) ] − K L ( q ( z ∣ x ) ∥ p ( z ) ) mathop{mathbb{E}} limits_{q(z|x)} left[ log p(x|z) right] - mathrm{KL} left( q(z|x) | p(z) right) q(z∣x)E​[logp(x∣z)]−KL(q(z∣x)∥p(z)) 用于神经网络优化.
      • max ⁡ E q ( z ∣ x ) [ log ⁡ p ( x ∣ z ) ] ≈ sampling max ⁡ q ( z i ∣ x i ) log ⁡ p ( x i ∣ z i ) = opposite min ⁡ c r o s s _ e n t r o p y _ l o s s ∼ substitution min ⁡ m s e _ l o s s max mathop{mathbb{E}} limits_{q(z|x)} left[ log p(x|z) right] stackrel{textsf{sampling}}{approx} max q(z_i|x_i) log p(x_i|z_i) stackrel{textsf{opposite}}{=} min mathtt{cross_entropy_loss} stackrel{textsf{substitution}}{sim} min mathtt{mse_loss} maxq(z∣x)E​[logp(x∣z)]≈samplingmaxq(zi​∣xi​)logp(xi​∣zi​)=oppositemincross_entropy_loss∼substitutionminmse_loss
      • min ⁡ K L ( q ( z ∣ x ) ∥ p ( z ) ) ≈ Variational   Inference min ⁡ K L ( q ( z ∣ x ) ∥ p ^ ( z ) ) min mathrm{KL} left( q(z|x) | p(z) right) stackrel{textsf{Variational Inference}}{approx} min mathrm{KL} left( q(z|x) | hat{p}(z) right) minKL(q(z∣x)∥p(z))≈Variational InferenceminKL(q(z∣x)∥p^​(z))
















kld_loss_weight = 1e-5
{'batch_size': 25,
 'conv_encoder': True,
 'learning_rate': 1e-05,
 'num_class': 10,
 'num_epoch': 16,
 'save_fig_path': './figs',
 'use_cuda': True}

以上这组超参数能较快的收敛到较优模型参数.
实验发现, batch_size较大时收敛到较差模型参数, learning_rate较小时收敛非常缓慢.

  • 神经网络先学数字范围再学数字形状. epoch[0-3]数字有很多噪声点, epoch[4-15]数字呈平滑图形.
  • 神经网络先学前景(数字)再学背景(白色). epoch[0-10]背景都是暗色, epoch[11-15]背景都是亮色.
  • epoch11开始学最不重要的细节(白色背景), epoch12开始就逐渐发生了过拟合! 尤其是数字0, 在epoch15中看起来像数字8一样.
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947429.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号