想象你是一位魔术师,面前有一堆乱糟糟的脏衣服。你的任务不是把它们洗干净,而是把它们叠成整齐划一的方块。一个笨办法是用脚猛踩,把衣服压成一个大饼——可这样衣服的纹理就全毁了。另一个办法是掏出手机拍张照,然后照着照片画一件“看起来像”的衣服——可细节总是模糊。真正的魔术师会怎么做?他会一格一格地“翻折”:把左袖折到胸前,右袖再叠上去,每一步都精确记录了袖子原本的位置。这样,只要按相反顺序展开,每件衣服都能完美还原。这就是标准化流的核心思想——通过一串可逆的“折叠动作”,让简单的分布变成复杂的数据分布,而且每一步都算得清、回得去。

岗位关联

掌握 RealNVP,你就掌握了生成模型三大路线中“精确计算概率密度”的那条路——这是 GAN 和 VAE 做不到的,也是你在密度估计、异常检测、科学计算模拟中脱颖而出的硬核技能。

目录
  1. 可视化演示
  2. 生成模型概览
  3. 核心数学基础
  4. 仿射耦合层
  5. 训练方法与技巧
  6. 三大优势与应用
  7. 动手实践
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示RealNVP仿射耦合层的前向变换与逆变换采样过程,切换模式观察数据分布与高斯分布之间的可逆映射。

本节配有交互动效(进入视口后自动加载,约 3KB)。

前向变换:数据到隐空间 复杂数据分布通过K层仿射耦合层逐步变换为标准高斯分布 每层将输入分为两半,一半不变另一半做仿射变换 log p(x)=log p(z)+log|det df/dx| 精确对数似然计算是标准化流的核心优势

生成模型概览

把“生成模型”想象成三位裁缝,都接到同一份订单:学会用手里的布料(随机噪声)做出顾客喜欢的衣服(真实数据)。

第一位裁缝是“画家”(GAN)。他从不直接看布料,而是拿出一幅目标画作,让助手反复对比“像不像”,直到画作能以假乱真。他的问题在于——画作虽然逼真,但永远没有“这件衣服到底合不合身”的量化数据。

第二位裁缝是“雕塑家”(VAE)。他先把布料揉成一团,塞进一个压缩袋,记录下压缩袋的拉链位置(隐变量),再试着从压缩袋复原出衣服。他只能保证“大概像”,因为压缩过程丢掉了许多细节。

第三位裁缝是“叠衣师”(标准化流)。他不揉、不压,而是把衣服放在桌上,一格一格地折叠:左袖折进、右袖折进、下摆上翻。每一步折叠都是完全可逆的,而且他能精确计算出“这一折改变了多少体积”。

标准化流的定位,就是这位“叠衣师”。它追求的不是“看起来像”,而是对数据分布进行显式概率建模——既能算清楚每个样本出现的概率,又能通过逆操作快速生成新样本。它不靠对抗训练,也不靠变分近似,而是用数学上严密的可逆变换,把简单分布一步步“雕刻”成复杂分布。

---

核心数学基础

叠衣师的关键能力,是“每一步都记得怎么还原”。如果你把一件衣服从“乱糟糟”变成“整齐”,这个折叠过程可以用一个数学函数 $f$ 描述。问题是:当 $f$ 把简单的噪声分布 $p_Z(z)$ 变成复杂的数据分布 $p_X(x)$ 时,$p_X(x)$ 到底是多少?

答案是变量替换公式。想象你在弹一张橡皮膜,膜上每个点都被 $f$ 挪到了新位置。如果你在某处把膜拉伸成原来的 3 倍面积,那么膜的密度就会变成原来的 1/3。这个“拉伸倍数”就是雅可比行列式的绝对值 $|\det J|$。

对两边取对数,得到更实用的形式:$\log p_X(x) = \log p_Z(f^{-1}(x)) + \log|\det J_f^{-1}(x)|$。这样做的好处是,把乘法变成加法,数值计算更稳定。而 RealNVP 的全部设计,都围绕一个目标:让 $f$ 足够强大(能拟合复杂分布),同时让 $f^{-1}$ 和 $\det J$ 计算得足够快。

---

pX(x)=pZ(z)⋅∣det⁡∂f−1(x)∂x∣=pZ(z)⋅∣det⁡Jf(z)∣−1\displaystyle p_X(x) = p_Z(z) \cdot \left|\det \frac{\partial f^{-1}(x)}{\partial x}\right| = p_Z(z) \cdot \left|\det J_f(z)\right|^{-1}
翻译成人话:新位置的概率密度 = 原位置的概率密度 ÷ 被拉伸的倍数。这正是“叠衣服”时,布料体积变化的数学账本。
  1. 前向变换把简单分布的样本 $z$ 变成数据样本 $x$,写作:
    x=f(z)x = f(z)
  2. 逆向还原训练时拿到真实数据 $x$,需要逆回去找到对应的 $z$,写作:
    z=f−1(x)z = f^{-1}(x)
  3. 雅可比矩阵计算 $f$ 对 $z$ 的偏导数矩阵,它记录了每个方向上的伸缩比例:
    J=∂f(z)∂zJ = \frac{\partial f(z)}{\partial z}
  4. 行列式修正概率用 $|\det J|$ 修正概率密度在变换中被拉伸或压缩的程度:
    pX(x)=pZ(f−1(x))⋅∣det⁡∂f−1∂x∣p_X(x) = p_Z(f^{-1}(x)) \cdot \left|\det \frac{\partial f^{-1}}{\partial x}\right|

仿射耦合层

叠衣师面临一个难题:如果一个折叠动作太复杂,就很难还原。聪明的做法是“只叠半边”——这正是 RealNVP 的核心创新:仿射耦合层。

把数据 $x$ 按维度切成两半:$x_{1:d_1}$ 和 $x_{d_1+1:d}$。让前半部分原封不动地通过:$y_{1:d_1} = x_{1:d_1}$。后半部分则根据前半部分的信息,做一个“缩放 + 平移”的仿射变换:

注意一个细节:缩放用的是 $\exp(s)$ 而不是直接乘 $s$。这就像叠衣时“折叠线”必须是正数——不能折叠出“负的宽度”;$\exp$ 保证了缩放因子恒为正数,因此变换永远可逆。而 $s$ 和 $t$ 本身由任意神经网络计算,不必是可逆的——这大大拓宽了模型容量,却丝毫不影响逆变换的精确性。

---

{y1:d1=x1:d1yd1+1:d=xd1+1:d⊙exp⁡(s(x1:d1))+t(x1:d1)\displaystyle \begin{cases} y_{1:d_1} = x_{1:d_1} \\ y_{d_1+1:d} = x_{d_1+1:d} \odot \exp\left(s(x_{1:d_1})\right) + t(x_{1:d_1}) \end{cases}
翻译成人话:把衣服对折,左半边不动(作为“说明书”),右半边按照说明书上的折叠线(缩放因子 $s$)和折痕位置(偏移因子 $t$)来叠。还原时,只要左半边还在,右半边就可以精确复原。
  1. 前半恒等映射为了保证可逆性,前 $d_1$ 维直接复制到输出,不进行任何变换:
    y1:d1=x1:d1y_{1:d_1} = x_{1:d_1}
  2. 后半仿射变换后 $d_2$ 维根据前半计算出的缩放 $s$ 和偏移 $t$ 做逐元素变换:
    yd1+1:d=xd1+1:d⋅exp⁡(s(x1:d1))+t(x1:d1)y_{d_1+1:d} = x_{d_1+1:d} \cdot \exp(s(x_{1:d_1})) + t(x_{1:d_1})
  3. 雅可比矩阵结构因为前半不变,后半只由前半决定,雅可比矩阵是下三角阵,对角线为前半的 1 和后半的缩放值:
    det⁡[∂y∂x]=∏jexp⁡(sj(x1:d1))=exp⁡(∑jsj(x1:d1))\det\left[\frac{\partial y}{\partial x}\right] = \prod_{j} \exp(s_j(x_{1:d_1})) = \exp\left(\sum_j s_j(x_{1:d_1})\right)
  4. 对数行列式化简取对数后得到简洁结果,无需计算高维矩阵:
    log⁡∣det⁡J∣=∑j=1d2sj(x1:d1)\log|\det J| = \sum_{j=1}^{d_2} s_j(x_{1:d_1})

训练方法与技巧

叠衣师的“手法”已经确定,但“每件衣服该叠多重、折几道”还需要学习。这就要靠数据来训练。

训练目标是最大化数据集的似然:对所有真实样本,我们希望模型给出的概率密度尽量大。取负对数,等价于最小化损失:

有了损失函数,还要解决“表达能力”问题。单层仿射耦合只有一半维度被变换,表达能力有限。RealNVP 给出的方案是交替遮罩(也叫交替翻转):第一层变换后一半、保持前一半;第二层则反过来变换前一半、保持后一半。如此交替堆叠 L 层,就像叠衣服时先叠左边再叠右边、先叠袖子再叠下摆,每层都是可逆的,叠加起来依然可逆,但变换能力大大增强。

多尺度架构则是另一个工程技巧:每次经过几个耦合层,就把一部分已经“叠得很好的维度”直接输出不再参与后续变换,从而缩短后续层的计算路径。这就像叠完下摆就把它固定住,专注于处理还乱的部分,兼顾了表达力和效率。

---

L=−1N∑i=1Nlog⁡pX(x(i))=−1N∑i=1N[log⁡pZ(f−1(x(i)))+∑jsj(x1:d1(i))]\displaystyle \mathcal{L} = -\frac{1}{N} \sum_{i=1}^{N} \log p_X(x^{(i)}) = -\frac{1}{N} \sum_{i=1}^{N} \left[ \log p_Z\left(f^{-1}(x^{(i)})\right) + \sum_{j} s_j\left(x^{(i)}_{1:d_1}\right) \right]
翻译成人话:每一件真实衣服叠回“整齐方块”后,它应该看起来非常像一个标准的噪声样本;同时由折叠产生的缩放因子(对数行列式)也要计入“手法得分”。这两部分加起来,就是这套叠衣手法的好坏分数。
  1. 特征拆分(切分)把向量按通道一分为二,一半作为“固定说明书”,一半作为“被变换对象”:
    x=[x1:d1,xd1+1:d]x = [x_{1:d_1}, x_{d_1+1:d}]
  2. 缩放网络与偏移网络由神经网络根据第一步计算缩放和偏移参数:
    s=sθ(x1:d1),t=tθ(x1:d1)s = s_\theta(x_{1:d_1}), \quad t = t_\theta(x_{1:d_1})
  3. 应用变换对后一半做逐元素缩放和平移,完成一步折叠:
    yd1+1:d=xd1+1:d⋅exp⁡(s)+ty_{d_1+1:d} = x_{d_1+1:d} \cdot \exp(s) + t
  4. 对数似然目标将逆变换对应噪声的概率密度与缩放因子相加,构成损失:
    log⁡pX(x)=log⁡N(f−1(x);0,I)+∑jsj\log p_X(x) = \log \mathcal{N}(f^{-1}(x); 0, I) + \sum_j s_j

三大优势与应用

叠衣师的三件法宝,恰好对应标准化流的三大优势。

第一,精确对数似然。由于每一步变换都可逆,且雅可比行列式可以精确计算,RealNVP 能给任何一个数据点算出准确的对数概率密度。GAN 做不到——它没有概率密度函数;VAE 只能算一个下界(ELBO)。这在异常检测中至关重要:给一个“可疑样本”,RealNVP 能直接说“它的概率密度是 -123.45”,密度极低,判定为异常。

第二,高效采样。生成一个新样本只需两步:先从标准高斯分布采样 $z$,再逆向穿过所有耦合层。整个过程是确定的、一次前向计算,不需要像扩散模型那样迭代上百步去噪。这在实时生成场景(如图像编辑、游戏资产生成)中优势明显。

第三,双向可逆变换。RealNVP 天然是一个“编码-解码”合一的模型。给定数据 $x$,正变换直接得到隐变量 $z$(相当于编码);给定 $z$,逆变换直接还原 $x$(相当于解码)。由于可逆,$z$ 完整保留了 $x$ 的所有信息,所以可以做无损压缩式表征、缺失值填补(用观测维度推测缺失维度)、图像属性编辑(在隐空间中对 $z$ 做线性运算再解码)。

在密度估计场景中,这些优势让 RealNVP 成为金融风控(异常交易发现)、工业质检(缺陷检测)、科学数据分析(高维物理量分布建模)等任务的有力工具。

---

动手实践

百闻不如一练。我们来训练一个 2D 的 RealNVP 模型,目标是学习一个“月牙形”数据分布。代码将实现仿射耦合层、前向变换(数据→噪声)、逆变换(噪声→数据)和对数似然损失。

我们从 sklearn 生成月牙数据,搭建三层耦合网络,用 Adam 优化器最大化对数似然。训练完成后,从标准高斯采样,逆变换生成新样本,看看模型是否学会了月牙的形状。这个例子麻雀虽小五脏俱全——它演示了标准化流 “精确似然 + 可逆采样” 的核心流程,把之前讲到的方法落地为可运行的代码。

---

AI 应用场景

金融交易异常检测

阶段:密度估计与异常检测

解决的问题:传统风控依赖规则引擎,只能拦截已知模式的黑产攻击;而新型欺诈手法层出不穷。RealNVP 直接建模“正常交易”的精确对数似然,给定一笔交易,计算其概率密度,密度低于阈值即触发告警。相比 VAE 的 ELBO 下界,RealNVP 的精确似然让误报率更低。

具体案例:某支付平台用 RealNVP 对用户的登录时间、金额、设备、地理位置等特征建模。一个深夜在异地登录并大额转账的请求,模型算出其对数似然为 -580,远低于正常阈值 -120,系统自动拦截并要求二次验证。整个推理过程只需 3 毫秒,无需等待图像采样或蒙特卡洛模拟。

医学影像缺失区域填补

阶段:生成模型的可逆表征

解决的问题:MRI 扫描中患者移动会产生伪影或缺失区域,传统插值方法会破坏组织纹理。RealNVP 的可逆性使其可将完整影像变换到隐空间,在隐空间中对缺失部分的隐变量进行插值,再解码回图像空间,保证生成的填补区域与真实组织纹理的统计特征一致。

具体案例:某医学影像实验室对脑部 MRI 的 3D 块进行 RealNVP 建模。当扫描某区域出现运动伪影时,模型利用相邻完好区域的隐变量推断缺失区域,生成的结构在放射科医生的盲评中被判定为“与真实扫描无显著差异”,且生成耗时不到 0.5 秒,满足临床实时需求。

Python 演示

python81 行
import numpy as npimport torchimport torch.nn as nnfrom sklearn.datasets import make_moons  class CouplingLayer(nn.Module):    def __init__(self, dim, hidden=64):        super().__init__()        self.dim = dim        half = dim // 2        self.net = nn.Sequential(            nn.Linear(half, hidden), nn.LeakyReLU(0.2),            nn.Linear(hidden, hidden), nn.LeakyReLU(0.2),            nn.Linear(hidden, 2 * (dim - half)),        )        self.scale = nn.Parameter(torch.zeros(dim - half))     def forward(self, x, reverse=False):        d1 = self.dim // 2        x1, x2 = x[:, :d1], x[:, d1:]        s, t = self.net(x1).chunk(2, dim=1)        s = s + self.scale        if not reverse:            y2 = x2 * torch.exp(s) + t            log_det = s.sum(1)        else:            y2 = (x2 - t) * torch.exp(-s)            log_det = -s.sum(1)        return torch.cat([x1, y2], dim=1), log_det  class RealNVP(nn.Module):    def __init__(self, dim):        super().__init__()        self.layers = nn.ModuleList([CouplingLayer(dim) for _ in range(4)])     def fwd(self, x):        log_det = 0        for i, layer in enumerate(self.layers):            x, ld = layer(x)            log_det = log_det + ld            if i % 2 == 0:                x = x.flip(1)        return x, log_det     def inv(self, z):        for i in range(len(self.layers) - 1, -1, -1):            if i % 2 == 0:                z = z.flip(1)            z, _ = self.layers[i](z, reverse=True)        return z     def log_prob(self, x):        z, log_det = self.fwd(x)        l = -0.5 * z.pow(2).sum(1) - 0.5 * z.size(1) * np.log(2 * np.pi)        return l + log_det  def train():    X, _ = make_moons(3000, noise=0.05)    X = (X - X.mean(0)) / X.std(0)    data = torch.tensor(X, dtype=torch.float32)    model = RealNVP(2)    opt = torch.optim.Adam(model.parameters(), lr=1e-3)    for epoch in range(300):        idx = torch.randperm(len(data))[:256]        x = data[idx]        loss = -model.log_prob(x).mean()        opt.zero_grad()        loss.backward()        opt.step()        if epoch % 50 == 0:            print(f'epoch {epoch:3d}  nll={loss.item():.3f}')    z = torch.randn(1000, 2)    samples = model.inv(z).detach().numpy()    print('sampled shape:', samples.shape)  if __name__ == '__main__':    train()
目的:在二维月牙分布上训练一个 4 层 RealNVP,演示完整的仿射耦合层、前向变换(数据→噪声)、逆变换采样(噪声→数据)和最大似然训练流程。
  1. y2 = x2 * torch.exp(s) + t仿射耦合层核心,后半维做“缩放 + 偏移”,exp 保证缩放为正数。
  2. torch.cat([x1, y2], dim=1)前半原样保留,后半变换后拼接,保证可逆。
  3. log_det = s.sum(1)对数雅可比行列式,就是所有缩放因子之和。
  4. z, log_det = self.fwd(x)前向把数据映射回高斯噪声,同时累计对数行列式。
  5. y2 = (x2 - t) * torch.exp(-s)逆向只用减法与乘法,完美还原原 x2。
  6. z = model.inv(torch.randn(...))从高斯采样再逆变换,一行代码生成新样本。

常见误区

误区我以为 RealNVP 和 GAN 一样,生成时会有随机噪声注入,每次生成同一张图结果都不同。训练好了之后,采样应该像摇骰子一样带有随机性。

正解RealNVP 的变换本身是完全确定性的(可逆函数)。随机性只存在于训练好的逆变换之前——你从标准高斯分布采样的那个 $z$ 才是随机的。一旦 $z$ 固定,生成的样本就唯一确定。可以把它理解为“叠衣师”:所有随机性来自“你递给他的那块面料”($z$),而叠的手法本身是一套固定的流程。

为何常见:因为 GAN 和 VAE 的生成都包含采样过程,初学者习惯性地把“生成模型”等价于“随机过程”,忽略了标准化流的设计核心是“确定性的可逆映射”。

误区每训练一步都要计算 d×d 矩阵的行列式,那图像(比如 256×256×3≈20 万维)不是要爆内存?RealNVP 怎么可能跑得动?

正解因为仿射耦合层的雅可比矩阵是三角阵,行列式等于对角线上所有元素相乘。代码中只需把网络输出的 log 缩放因子全部加起来即可得到对数行列式,根本不需要构造显式矩阵。这就是为什么 RealNVP 能处理高维数据——它用结构换来了 O(d) 的计算复杂度。

为何常见:大多数教材讲变量替换公式时都写了“计算雅可比行列式”,这让初学者误以为必须显式构造矩阵。RealNVP 的巧妙之处正是通过精心设计的网络结构避开这一步。

误区既然变换要可逆,那 s(x1) 和 t(x1) 的神经网络不也得是可逆网络吗?那训练会不会很不稳定?

正解s 和 t 的神经网络完全不需要可逆。耦合层可逆的关键是:前半维 $x_1$ 原样通过,后半维只由前半维决定。逆向时用 $x_1$ 重新算出 $s,t$,即可还原 $x_2$。至于 $s$、$t$ 自身的计算过程是什么,根本不影响可逆性——就像叠衣说明书($x_1$ 上的网络)无论多复杂,只要它存在,展开时照着同一本说明书做就可以。

为何常见:把“整个变换可逆”误认为是“每个内部模块都可逆”,混淆了耦合层整体与子网络的关系。

误区生成模型嘛,不就是用来生成图片的?其他方面好像没什么用。

正解RealNVP 最独特的价值在密度估计:它能对任意数据点给出精确的对数似然,这是异常检测、金融风控、科学数据分析的核心能力。此外,可逆变换还赋予它无损表征、隐空间编辑、缺失值填补等图像生成之外的能力。图像生成只是它的应用之一,而非全部。

为何常见:受 GAN 和扩散模型宣传的影响,大众对“生成模型”的认知被绑定在图像合成上,忽略了标准化流的“可逆 + 精确似然”这一更宽泛的数学优势。

面试题

Q1. RealNVP 中仿射耦合层的最关键设计目标是?

单选题 · mid

  • A.让网络参数更少,节省显存
  • B.让变换可逆且雅可比易算← 正确答案
  • C.让采样过程加入更多噪声
  • D.让模型支持有监督分类任务

答案:B。仿射耦合层通过“前半恒等、后半缩放平移”确保变换一定有逆,且雅可比行列式为三角阵、对数行列式只需累加。A 是附带效应而非目标,C 与流模型确定性相悖,D 与生成模型无关。

Q2. RealNVP 训练时使用的损失函数是?

单选题 · easy

  • A.最小化生成样本与真实样本的 L2 距离
  • B.最小化数据点的负对数似然← 正确答案
  • C.最大化判别器对真实样本的置信度
  • D.最小化重构图像与输入图像的像素差

答案:B。RealNVP 通过最大化 $\log p_X(x)$(即最小化负对数似然)训练,将数据变换到高斯分布并累计雅可比对数行列式。L2 距离是自编码器的目标,对抗损失是 GAN 的目标,像素差属于 VAE 重构项。

Q3. 仿射耦合层中为什么用 exp(s) 而不是直接用 s 做缩放?

单选题 · mid

  • A.使缩放因子必须为正,保证可逆← 正确答案
  • B.让网络梯度更稳定,防止梯度消失
  • C.为了减少计算量,加速推理速度
  • D.使模型输出服从标准高斯分布

答案:A。若缩放为负数,逆变换还原时会被“折出负数宽度”导致不可逆或值域错乱。exp(s) 保证缩放恒正,同时保留梯度通路的平稳性。B 是额外收益,但首要动机是正数约束。

Q4. 关于标准化流与 GAN 的区别,下列说法正确的是?

多选题 · hard

  • A.标准化流能显式计算精确对数似然← 正确答案
  • B.GAN 也能精确计算数据概率密度
  • C.标准化流通过可逆变换实现双向映射← 正确答案
  • D.GAN 的对抗训练本质上不可逆

答案:AC。A 是标准化流区别于 GAN 的最大优势——GAN 没有显式密度函数,故 B 错。C 的“正逆变换都是同一个函数”是标准化流的根本特性。D 的对抗训练虽无“可逆”需求,但“不可逆”属于事实描述——生成器无法把输出还原回隐变量。

Q5. RealNVP 中雅可比矩阵为什么计算特别快?

单选题 · mid

  • A.因为网络使用了稀疏正则化
  • B.因为它是三角形矩阵,行列式只需对角线乘积← 正确答案
  • C.因为矩阵尺寸被池化减小了
  • D.因为训练时不需要算雅可比矩阵

答案:B。仿射耦合层的雅可比是下三角阵,行列式 = 主对角线元素乘积,对角线的后部分是 exp(s)。因此只需把网络输出的 s 求和即可得对数行列式,无需构造矩阵。A、C 与结构无关,D 则完全错误。

Q6. RealNVP 生成新样本的正确流程是?

单选题 · easy

  • A.从数据集中随机抽取一张图直接输出
  • B.从标准高斯采样 z,再通过逆变换得到 x← 正确答案
  • C.先采样噪声,再经过判别器过滤
  • D.对隐变量插值后直接作为输出

答案:B。标准化流的采样是“先采样简单分布 z,再执行 f 的逆变换”得到数据。A 是记忆数据,C 是 GAN 流程,D 是隐空间编辑而非端到端采样。

Q7. RealNVP 的优势包括哪些?

多选题 · mid

  • A.精确计算对数似然用于密度估计← 正确答案
  • B.无需对抗训练,训练过程稳定← 正确答案
  • C.生成一张图需要数百步迭代去噪
  • D.可逆变换支持缺失值填补和隐空间编辑← 正确答案

答案:ABD。A 和 D 是 RealNVP 的招牌能力。B 的“无对抗训练”意味着没有判别器与生成器博弈,训练平稳,这是它比 GAN 更稳定的原因之一。C 是扩散模型的缺点,恰好是 RealNVP 要避免的目标。

Q8. 交替遮罩(flip)在 RealNVP 中的作用是?

单选题 · easy

  • A.让所有维度都有机会被变换,增强表达力← 正确答案
  • B.防止过拟合,做数据增强
  • C.让训练和推理分布保持一致
  • D.把 2D 图像展平成 1D 向量

答案:A。单层耦合层只变换后一半维度,交替遮罩让下一层变换前一半,从而所有维度都经历变换。没有它,每层的变换范围受限,模型表达力不足。B、C、D 与交替遮罩无关。

Q9. 下列哪些是 RealNVP 的应用场景?

多选题 · extreme

  • A.异常检测(计算样本精确对数似然)← 正确答案
  • B.高维数据的密度估计← 正确答案
  • C.用可逆变换做图像属性编辑← 正确答案
  • D.替代注意力机制做文本分类

答案:ABC。A、B、C 都直接利用标准化流的精确似然和可逆变换特性。D 与标准化流的本质无关——它既不是序列模型也不是分类器,强行用于文本分类属于乱点鸳鸯谱。

Q10. 训练 RealNVP 时,输入数据需要经过的变换方向是?

单选题 · mid

  • A.前向变换:从数据到隐变量← 正确答案
  • B.逆向变换:从隐变量到数据
  • C.同时执行前向和逆向两个分支
  • D.先逆向再前向的循环结构

答案:A。训练时拿到的是真实数据 x,需要正变换 $f(x)$ 把它映射到隐变量 z,以便用高斯先验计算似然。逆向变换只用于训练完毕后的采样阶段。B 是采样方向,C、D 均不符合标准流程。