惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
I
InfoQ
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 【当耐特】
小众软件
小众软件
B
Blog RSS Feed
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
Microsoft Security Blog
Microsoft Security Blog
Last Week in AI
Last Week in AI
H
Help Net Security
爱范儿
爱范儿
云风的 BLOG
云风的 BLOG
博客园 - 司徒正美
Y
Y Combinator Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Microsoft Azure Blog
Microsoft Azure Blog
L
LangChain Blog
WordPress大学
WordPress大学
GbyAI
GbyAI
Google DeepMind News
Google DeepMind News
腾讯CDC

又见苍岚

COLMAP PatchMatch Stereo 算法详解 事件驱动的状态机框架:从理论到工程实践 Git 在国内网络环境下无法 Push 的排查与修复 —— 配置 Clash 代理 分段五次多项式插值原理详解 路径插值方法深度对比研究 Claude Code 使用指南 OpenClaw 记忆管理与技能创建指南 CBS(Conflict-Based Search)算法详解 A* 算法及其变种详解 OpenClaw 配置多 Agents Windows Powershell 无法加载文件,因为在此系统上禁止运行脚本问题的解决方案 MaxClaw 安装流程 大模型 AI 名词介绍 AList 网盘聚合工具简介 Protobuf 简介与测试 Claude Code 简介以及 GLM 4.7 模型接入 Github 歌词下载工具 163MusicLyrics Python __getattr__ 懒加载 Python TypedDict 机器人仿真平台 Gazebo 安装记录 机器人仿真平台 Gazebo 简介 多机器人路径规划问题(Multi-Agent Path Finding, MAPF)简介 Python exifread 读取修改过的 jpeg 信息错误问题修复 3D 坐标系变换的理解 3D 旋转矩阵基本概念 MongoDB Compass 介绍 Python 环境管理工具 uv Flutter 开发指南 Snipaste 安装下载与黑屏问题解决方案 全局路径规划算法记录
对 VAE 的理解与实现
Yiwei Zhang · 2022-09-07 · via 又见苍岚
  • 如果我们有一组关于参数 $\beta$ 的生成器族 $g_\beta$,可以不断生成和 $x$ 维度相同的数据, 优化 $\beta$ 使得生成的数据和 $p$ 生成的数据难以区分,我们就可以说得到了 $p$ 的近似分布,GAN 基本上就延用了这个思路

  • 如果我们觉得直接用模型描述 $X$ 分布困难或过于暴力,我们可以引入带有隐变量 $z$ 的概率分布,也就走上了 ELBO 的生成模型 道路

  • 在ELBO 的生成模型中,我们为了描述复杂的概率分布引入了 $z$,建立了 $X,Z$ 的联合分布,但是这个 $z$ 却是个大麻烦,因为我们的目标是 $p$,这个分布和 $Z$ 无关,仅和 $X$ 有关,我们还得把 $z$ 消掉

  • 直接的想法是对 $z $ 积分,$ p_{\theta}(x)=\int p_{\theta}(x \mid z) p(z) d z $,可以蒙特卡洛积分计算,但是如果要求精度会很慢,因此我们转向贝叶斯的思路,也就走上了 ELBO 贝叶斯评估器 的道路

  • ELBO 的神奇之处在于同时结合了生成器和评估器的分布描述方式,在多处受阻的境况中巧妙运用贝叶斯公式找到了一种可以参数化、可以优化、贪心最大化变量 (ELBO) 的方法

  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    class SimpleVAE(BaseVAE):
    def __init__(self, in_channels: int=2, latent_dim: int=2, hidden_dims: List = None) -> None:
    super(SimpleVAE, self).__init__()

    self.latent_dim = latent_dim

    if hidden_dims is None:
    hidden_dims = [128, 128]

    ori_in_channels = in_channels

    # Build Encoder
    modules = []
    for h_dim in hidden_dims:
    modules.append(
    nn.Sequential(
    nn.Linear(in_channels, h_dim),
    nn.LeakyReLU())
    )
    in_channels = h_dim

    self.encoder = nn.Sequential(*modules)
    self.fc_mu = nn.Linear(hidden_dims[-1], latent_dim)
    self.fc_var = nn.Linear(hidden_dims[-1], latent_dim)

    # Build Decoder
    modules = []
    de_hidden_dims = [hidden_dims[-1]] + hidden_dims

    self.decoder_input = nn.Linear(latent_dim, hidden_dims[-1])
    hidden_dims.reverse()

    for i in range(len(de_hidden_dims) - 1):
    modules.append(
    nn.Sequential(
    nn.Linear(de_hidden_dims[i], de_hidden_dims[i + 1]),
    nn.LeakyReLU())
    )

    self.decoder = nn.Sequential(*modules)
    self.final_layer = nn.Sequential(
    nn.Linear(de_hidden_dims[-1], ori_in_channels))

    def encode(self, input: Tensor) -> List[Tensor]:
    """
    Encodes the input by passing through the encoder network
    and returns the latent codes.
    :param input: (Tensor) Input tensor to encoder [N x in_channels]
    :return: (Tensor) List of latent codes [N x latent_dim]
    """
    result = self.encoder(input)

    # Split the result into mu and var components
    # of the latent Gaussian distribution
    mu = self.fc_mu(result)
    log_var = self.fc_var(result)

    return [mu, log_var]

    def decode(self, z: Tensor) -> Tensor:
    """
    Maps the given latent codes onto the data space.

    :param z: (Tensor) [N x latent_dim]
    :return: (Tensor) [N x in_channels]
    """
    result = self.decoder_input(z)
    result = self.decoder(result)
    result = self.final_layer(result)
    return result

    def reparameterize(self, mu: Tensor, logvar: Tensor) -> Tensor:
    """
    Reparameterization trick to sample from N(mu, var) from N(0,1).
    :param mu: (Tensor) Mean of the latent Gaussian [N x latent_dim]
    :param logvar: (Tensor) Standard deviation of the latent Gaussian [N x latent_dim]
    :return: (Tensor) [N x latent_dim]
    """
    std = torch.exp(0.5 * logvar)
    eps = torch.randn_like(std)
    return eps * std + mu

    def forward(self, input: Tensor) -> List[Tensor]:
    mu, log_var = self.encode(input)
    z = self.reparameterize(mu, log_var)
    return [self.decode(z), input, mu, log_var, z]

    def loss_function(self, forward_res, kld_weight) -> dict:
    """
    Computes the VAE loss function.
    KL(N(\mu, \sigma), N(0, 1)) = \log \frac{1}{\sigma} + \frac{\sigma^2 + \mu^2}{2} - \frac{1}{2}
    """
    recons = forward_res[0]
    input = forward_res[1]
    mu = forward_res[2]
    log_var = forward_res[3]

    recons_loss =F.mse_loss(recons, input)
    kld_loss = torch.mean(-0.5 * torch.sum(1 + log_var - mu ** 2 - log_var.exp(), dim = 1), dim = 0)

    loss = recons_loss + kld_weight * kld_loss
    return {'loss': loss, 'Reconstruction_Loss':recons_loss.detach(), 'KLD':kld_loss.detach()}