Skip to content

NF

Normalizing Flow(归一化流)

NF 是一类生成模型。基本想法是:先从一个简单分布采样,比如标准高斯,再通过一串可逆变换,把这个简单分布变成复杂的数据分布。

可以写成:

zpZ(z)x=fθ(z)xpX(x)

这里:

  • z 是简单潜变量,通常来自标准高斯;
  • x 是生成出来的数据;
  • fθ 是可逆变换;
  • pZ(z) 是简单分布;
  • pX(x) 是模型希望学到的数据分布。

NF 的关键词是 可逆。只要 fθ 可逆,就可以从数据 x 反推回潜变量 z

z=fθ1(x)

这让 NF 同时具备两种能力:可以采样,也可以计算样本概率。

为什么可逆很重要

很多生成模型只能生成样本,却不容易精确计算样本概率。NF 的优势在于,它通过可逆变换把复杂分布和简单分布连接起来。

从简单分布生成数据时:

zpZ(z),x=fθ(z)

给定数据计算概率时:

z=fθ1(x)

然后利用变量替换公式算 pX(x)

这就是 NF 和普通神经网络生成器的主要区别:它不是只学一个从 zx 的方向,还要求这条映射能反过来走。

变量替换公式

NF 的核心公式来自概率论里的变量替换。

x=fθ(z)

fθ 可逆。给定一个数据点 x,先反推出

z=fθ1(x)

那么 x 的概率密度是:

pX(x)=pZ(z)|detzx|

也可以写成:

pX(x)=pZ(fθ1(x))|detJfθ1(x)|

其中 Jfθ1(x) 是反函数的雅可比矩阵。

TIP

同一批样本,在变换前后的总概率不变,但概率密度会随之调整。

以一维为例,即:

pX(x)dx=pZ(z)dz

也就是:

pX(x)dx=pZ(z)|dzdx|

绝对值是因为概率密度不能为负数。

实际训练时更常用对数形式:

logpX(x)=logpZ(z)+log|detJfθ1(x)|

如果用正向映射 x=fθ(z) 的雅可比矩阵,也可以写成:

logpX(x)=logpZ(z)log|detJfθ(z)|

因为反函数的雅可比行列式和正向函数互为倒数。

这条公式说明了两件事:

第一,数据点 x 的概率和它对应的潜变量 z 的概率有关。

第二,变换 fθ 会拉伸或压缩空间,因此还要乘上体积变化项,也就是雅可比行列式。

一个一维例子

先看最简单的一维变换:

x=az+b

其中 a0。反函数是:

z=xba

根据变量替换公式:

pX(x)=pZ(xba)|1a|

这里的 |1a| 就是体积缩放因子。

如果 |a|>1,原来的分布被拉宽,同样的概率质量分散到更大的区域里,密度会变小。

如果 |a|<1,原来的分布被压窄,概率质量集中到更小的区域里,密度会变大。

高维 NF 做的事情也是类似的,只是把一维的缩放因子换成了雅可比行列式。

多层 flow

一个单独的可逆变换通常不够强,所以 NF 会把很多层可逆变换串起来:

z0pZ(z0)z1=f1(z0)z2=f2(z1)x=zK=fK(zK1)

整体变换是:

x=fKfK1f1(z0)

由于每一层都是可逆的,整体仍然可逆。

对数概率也会逐层累加:

logpX(x)=logpZ(z0)k=1Klog|detJfk(zk1)|

这就是 “flow” 这个词的来源:分布经过一串可逆变换,一步步流向数据分布。

训练目标

NF 通常直接最大化训练数据的对数似然。

给定数据集 D,目标是:

maxθxDlogpθ(x)

实际优化时常写成最小化负对数似然:

LNLL(θ)=ExD[logpθ(x)]

这也是 NF 的一个特点:它可以做显式概率建模,训练目标比较直接。

采样过程

训练完成后,采样很简单。

先从简单分布采样:

zN(0,I)

再通过正向变换生成数据:

x=fθ(z)

所以 NF 的采样路径是从简单分布流向数据分布。

计算似然过程

给定真实样本 x,要计算它的概率,则走反方向。

先反推潜变量:

z=fθ1(x)

再计算:

logpX(x)=logpZ(z)+log|detJfθ1(x)|

因此 NF 同时支持生成和似然计算。

为什么不是所有神经网络都能当 flow

普通神经网络通常不满足两个条件。

第一,它不一定可逆。比如从高维压到低维的信息压缩层,反过来就无法唯一恢复。

第二,即使它可逆,也不一定容易计算雅可比行列式。高维矩阵的行列式直接算通常很贵。

所以 NF 的网络结构通常要专门设计,让它同时满足:

可逆

雅可比行列式容易算

这两个条件。

常见结构:耦合层

耦合层是 NF 里很经典的一类结构。它的基本做法是把输入拆成两部分:

x=(xa,xb)

然后保持一部分不变,用它去控制另一部分的变换:

ya=xayb=xbexp(s(xa))+t(xa)

这里 s()t() 可以是普通神经网络。

这个结构的好处是反函数很容易写:

xa=yaxb=(ybt(ya))exp(s(ya))

它的雅可比矩阵是三角结构,所以行列式也很容易算:

log|detJ|=isi(xa)

这种设计让模型既有可逆性,又能保持计算效率。

NF 的优点

NF 的优势主要在三个方面。

它可以精确计算似然,因为变量替换公式给出了 pX(x) 的明确表达。

它可以直接采样,因为只要从先验分布采样 z,再经过正向 flow 就能得到 x

它的训练目标清晰,通常就是最大化对数似然,不需要对抗训练,也不需要变分下界。

NF 的局限

NF 的限制也来自同一个地方:可逆性。

因为每一层都要可逆,结构设计会受到约束。模型不能随便使用任意维度变化,也不能随便用会丢失信息的操作。

另外,雅可比行列式必须容易计算,这会进一步限制网络结构。很多强表达能力的普通神经网络模块,并不能直接放进 flow 里。

在图像生成上,NF 能给出精确似然,但生成质量长期以来不一定总能超过 GAN 或 diffusion。它的价值更多体现在显式密度建模、可逆表示学习和需要精确概率的场景。

和 Autoencoder 的区别

普通 Autoencoder 通常学习:

z=E(x),x^=D(z)

它主要关心重建。

NF 学的是一个严格可逆的变换:

x=f(z),z=f1(x)

它不仅能重建,还能通过变量替换公式精确计算概率密度。

所以二者看起来都有编码和解码方向,但目标不同。

Autoencoder 更偏表示学习。

Normalizing Flow 更偏显式生成建模。

总结

Normalizing Flow 是一种基于可逆变换的生成模型。它从一个简单分布出发,通过一串可逆函数把简单分布变成复杂数据分布。由于每一步都可逆,并且雅可比行列式可以计算,NF 可以直接计算样本概率,也可以从先验中采样生成新样本。

它的核心公式是变量替换公式:

logpX(x)=logpZ(f1(x))+log|detJf1(x)|

训练时通常最大化数据的对数似然:

maxθxDlogpθ(x)

NF 的关键不在于某个具体网络,而在于这三个条件:分布变换、可逆映射、可计算的体积变化。