Lecture 7 · 归一化流(一):变量替换公式 · Normalizing Flows I: The Change of Variables

Deep Generative Models · Lecture 07。个人学习讲义与配套实验,按主题整理并持续修订。

课程源码 ZIP ↓

个人整理的学习笔记,非官方讲义;课程来源与整理说明见课程介绍。配套示例未逐一运行验证。

本篇目录

对应 Maps to:Stanford CS236 Deep Generative Models(Fall 2023,Stefano Ermon),Lecture 7 · 2023-10-18 · Normalizing Flow Models(slides:cs236_lecture7.pdf,19 页);课程笔记 Normalizing Flow Models。 依据说明:本讲按原课 slides 的顺序展开:似然学习的回顾(自回归模型 vs VAE)→ 从简单先验到复杂分布 → 流和 VAE 的关系 → 连续随机变量回顾 → 一维变量替换公式与证明 → 行列式与体积 → 一般的变量替换 → 二维例子 → 归一化流模型与”一串变换” → 平面流 → 学习与推断 → 对流模型的要求 → 三角雅可比 → 平面流的行列式。极坐标、“在 (r, θ) 上均匀 ≠ 在圆盘上均匀”、不单调变换的反例、单调变换造出双峰、平面流的反向 KL 拟合与退火、“流不能改变拓扑”都是本讲义补充的。实验在一维、二维的分布上进行,真实密度全部已知(第 5 讲的 toy2d.py)。 配套代码 Code:code/lecture07/(PyTorch;1 个模块 + 4 个演示脚本,最长的约 65 秒) 预计阅读时间:3 小时(含运行代码)


0. 本讲导航 · How to read this lecture

0.1 学习目标 Learning goals

学完这一讲,你应该能够:

  1. 说明流模型想解决的问题:要一个既有隐变量、似然又精确可算的模型;为什么”让 x=f(z)x = f(z) 确定、可逆”就能做到。
  2. 推导一维的变量替换公式 pX(x)=pZ(h(x))∣h′(x)∣p_X(x) = p_Z(h(x))|h'(x)|,知道它为什么要求单调(可逆),以及”密度不是概率”。
  3. 解释行列式 = 体积的缩放,写出一般的变量替换公式 pX(x)=pZ(f−1(x)) ∣det⁡∂f−1/∂x∣p_X(x) = p_Z(f^{-1}(x))\,|\det \partial f^{-1}/\partial x|,以及它的正向写法。
  4. 写出归一化流模型:复合一串可逆变换,log det 逐层相加;采样走正向,求密度走反向,隐表示 z=f−1(x)z = f^{-1}(x) 不需要推断网络。
  5. 理解平面流:矩阵行列式引理、可逆的条件、为什么它适合变分推断而不适合密度估计。
  6. 说出流模型的三条设计要求,解释为什么要让雅可比矩阵是三角的(O(n3)→O(n)O(n^3) \to O(n))。

0.2 先修与本讲范围 Prerequisites & scope

默认你已经会 Assumed本讲只给直觉,后面几讲再展开 Previewed only
第 4 讲:最大似然、KL 散度(前向 / 反向)耦合层(NICE、RealNVP)、自回归流(MAF、IAF)、高斯化流、去量化(第 8 讲)
第 5–6 讲:隐变量模型、ELBO、VAE(流模型是”没有 ELBO 差距的隐变量模型”)连续时间的流:神经 ODE、流匹配(第 16 讲、MIT6.S184)
微积分:导数、链式法则;线性代数:行列式、逆矩阵

0.3 本讲地图 Map

§1  回顾与问题:精确似然 + 隐变量,能兼得吗?从简单先验到复杂分布;流 vs VAE
§2  一维变量替换:X = 4Z 的陷阱;公式与证明;不单调时会怎样;单调变换造出双峰          ← 代码 01
§3  几何:行列式 = 体积的缩放                                                         ← 代码 02
§4  一般的变量替换:雅可比;极坐标;两种写法                                         ← 代码 02
§5  归一化流:一串可逆变换;log det 相加                                              ← 代码 02
§6  平面流:矩阵行列式引理;可逆的条件;拟合目标密度;求逆的代价                      ← 代码 03
§7  学习与推断;设计要求;三角雅可比;用最大似然训练二维的流;流不能改变拓扑          ← 代码 02、04
§8  2023 年之后
§9–13  小结、常见误区、练习、延伸阅读、下一讲预告

0.4 记号 Notation

符号含义
ZZ,XX隐变量(先验,通常 N(0,I)\mathcal{N}(0, I)),观测变量;维数相同
f=fθf = f_\theta,h=f−1h = f^{-1}正向变换 x=f(z)x = f(z);反向变换 z=h(x)z = h(x)
FXF_X,pXp_X累积分布函数(CDF),概率密度函数(pdf)pX=FX′p_X = F_X'
∂f∂z\frac{\partial f}{\partial z},JJ雅可比矩阵,Jij=∂fi/∂zjJ_{ij} = \partial f_i / \partial z_j
∣det⁡J∣\lvert\det J\rvert雅可比行列式的绝对值:局部的体积缩放比例
z0→f1z1→⋯→fMzM=xz_0 \xrightarrow{f^1} z_1 \to \dots \xrightarrow{f^M} z_M = x一串变换(“流”)

0.5 关于数字 · About the numbers

一维、二维的实验都用 float64,真实密度已知(双月牙、香蕉形、八高斯圆环来自第 5 讲的 toy2d.py;平面流的目标密度来自 Rezende & Mohamed 2015),所以 KL 是真正的 KL(nat),∫p=1\int p = 1 也能用网格积分直接验证。计时依机器而定。和预想不同的结果(例如平面流拟合圆环时卡在 KL ≈ ln 2、“拓扑细缝”处面积几乎不变)记录在 代码 README 的”关于实验结果”里。


1. 回顾与问题 · Where we are

1.1 精确似然 vs 隐变量

原课第 2 页回顾了到目前为止的两个模型家族:

  • 自回归模型 pθ(x)=∏ipθ(xi∣x<i)p_\theta(x) = \prod_i p_\theta(x_i \mid x_{<i}):似然精确可算,但没有直接学习特征的机制(第 3 讲)。
  • 变分自编码器 pθ(x)=∫pθ(x,z) dzp_\theta(x) = \int p_\theta(x, z)\,dz:能通过隐变量 zz 学到特征表示,但边际似然算不出来(第 5–6 讲)——只能用 ELBO 训练、用 IWAE 估计,而且像第 6 讲看到的那样,ELBO 比真实的 log⁡pθ\log p_\theta 低 1 bit 多,后验近似不完美还会导致后验坍塌。

关键问题:能不能设计一个似然精确可算的隐变量模型?能!

1.2 从简单的先验到复杂的数据分布

slide 3:一个模型分布 pθ(x)p_\theta(x) 最好有两个性质——密度容易计算(有闭式解,训练要用)、容易采样(生成要用)。高斯、均匀分布都满足,可惜数据分布复杂得多(多峰的)。

流模型的关键想法:通过一个可逆变换,把简单的分布(容易采样、容易求密度)映射成复杂的分布。

1.3 流和 VAE 的关系

slide 4 把流放在 VAE 旁边:

  1. 从简单的先验出发:z∼N(0,I)=p(z)z \sim \mathcal{N}(0, I) = p(z);
  2. 用 p(x∣z)=N(μθ(z),Σθ(z))p(x \mid z) = \mathcal{N}(\mu_\theta(z), \Sigma_\theta(z)) 变换;
  3. 尽管 p(z)p(z) 简单,边缘 pθ(x)p_\theta(x) 非常复杂、灵活。但 pθ(x)=∫pθ(x,z) dzp_\theta(x) = \int p_\theta(x, z)\,dz 计算代价高:要枚举所有可能生成 xx 的 zz(第 5 讲 §3)。
  4. 如果我们能轻易地”反转” p(x∣z)p(x \mid z)、按设计就能算出 p(z∣x)p(z \mid x) 呢?怎么做?让 x=fθ(z)x = f_\theta(z) 成为 zz 的确定性、可逆的函数,于是对任何 xx 都恰好有一个对应的 zz——不需要枚举。

换个角度:VAE 的解码器 p(x∣z)p(x \mid z) 加了噪声 Σθ(z)\Sigma_\theta(z),同一个 xx 可以来自很多 zz,所以后验是一团分布;流把噪声拿掉(Σ→0\Sigma \to 0)、并且要求 ff 可逆,于是”后验”退化成一个点 z=f−1(x)z = f^{-1}(x)。代价是:zz 和 xx 维数必须相同,zz 不再是一个压缩的表示。

剩下的问题只有一个:给定 pZp_Z 和可逆的 ff,x=f(z)x = f(z) 的密度是多少?这就是变量替换公式。


2. 一维变量替换 · Change of variables in 1D

2.1 连续随机变量回顾

slide 5:连续随机变量 XX 的 CDF FX(a)=P(X≤a)F_X(a) = P(X \leq a);pdf pX(a)=FX′(a)=dFX(a)dap_X(a) = F_X'(a) = \frac{dF_X(a)}{da}。常用带参数的密度:高斯 pX(x)=1σ2πe−(x−μ)2/2σ2p_X(x) = \frac{1}{\sigma\sqrt{2\pi}}e^{-(x-\mu)^2/2\sigma^2},均匀 pX(x)=1b−a1[a≤x≤b]p_X(x) = \frac{1}{b - a}\mathbb{1}[a \leq x \leq b];随机向量用联合密度,例如多元高斯 1(2π)n∣Σ∣exp⁡(−12(x−μ)⊤Σ−1(x−μ))\frac{1}{\sqrt{(2\pi)^n|\Sigma|}}\exp(-\frac{1}{2}(x - \mu)^\top\Sigma^{-1}(x - \mu))。

2.2 一个陷阱:X=4ZX = 4Z

slide 6:Z∼U[0,2]Z \sim U[0, 2],pZ(1)=1/2p_Z(1) = 1/2(检查:∫0212=1\int_0^2 \frac{1}{2} = 1)。令 X=4ZX = 4Z,pX(4)p_X(4) 是多少?

"pX(4)=p(X=4)=p(4Z=4)=p(Z=1)=pZ(1)=1/2p_X(4) = p(X = 4) = p(4Z = 4) = p(Z = 1) = p_Z(1) = 1/2"——错! XX 显然在 [0,8][0, 8] 上均匀,pX(4)=1/8p_X(4) = 1/8。

代码 01 第 1 部分:直方图估计的密度在 x=1,4,7x = 1, 4, 7 处都约为 0.125;天真的”密度” pZ(x/4)p_Z(x/4) 在 [0,8][0, 8] 上积分等于 4——它根本不是一个概率密度。

错在哪里?密度不是概率。pX(4)p_X(4) 不是”XX 恰好等于 4 的概率”(那是 0),而是”XX 落在 4 附近一个小区间里的概率 ÷ 区间长度”。X=4ZX = 4Z 把 [0,2][0, 2] 拉长成 [0,8][0, 8]:同样多的概率摊在 4 倍长的区间上,密度就要除以 4。

2.3 一维变量替换公式

slide 7:若 X=f(Z)X = f(Z),ff 单调,反函数 Z=f−1(X)=h(X)Z = f^{-1}(X) = h(X),则

  pX(x)=pZ(h(x)) ∣h′(x)∣  \boxed{\;p_X(x) = p_Z(h(x))\,\lvert h'(x)\rvert\;}

X=4ZX = 4Z:h(x)=x/4h(x) = x/4,pX(4)=pZ(1)⋅∣1/4∣=1/8p_X(4) = p_Z(1) \cdot |1/4| = 1/8。✓

证明(slide 8,设 ff 单调递增):

FX(x)=P(X≤x)=P(f(Z)≤x)=P(Z≤h(x))=FZ(h(x)),F_X(x) = P(X \leq x) = P(f(Z) \leq x) = P(Z \leq h(x)) = F_Z(h(x)),

两边对 xx 求导:pX(x)=pZ(h(x)) h′(x)p_X(x) = p_Z(h(x))\,h'(x)。(递减时 h′<0h' < 0,多一个负号,合起来就是绝对值。)由反函数的导数 h′(x)=1/f′(f−1(x))h'(x) = 1/f'(f^{-1}(x)),令 z=h(x)z = h(x),也可以写成

pX(x)=pZ(z) 1∣f′(z)∣.p_X(x) = p_Z(z)\,\frac{1}{\lvert f'(z)\rvert}.

更有意思的例子(slide 7):X=eZX = e^Z,Z∼U[0,2]Z \sim U[0, 2]。h(x)=ln⁡xh(x) = \ln x,pX(x)=pZ(ln⁡x)⋅∣1/x∣=12xp_X(x) = p_Z(\ln x)\cdot|1/x| = \frac{1}{2x},x∈[1,e2]x \in [1, e^2]。代码 01 第 2 部分的直方图逐格吻合;CDF 那张表就是证明本身:P(X≤2)=ln⁡2/2=0.3466P(X \leq 2) = \ln 2 / 2 = 0.3466,样本里是 0.3469。注意 pXp_X 的形状和先验不同——先验是平的,pXp_X 是斜的。变换改变了分布的形状:eze^z 在 zz 小的地方拉伸得少、在 zz 大的地方拉伸得多,概率就在左边挤、右边摊开。

2.4 为什么要单调(可逆)

代码 01 第 3 部分对比了两个变换(Z∼N(0,1)Z \sim \mathcal{N}(0, 1)):

  • X=sinh⁡(Z)X = \sinh(Z) 单调,pX(x)=φ(asinh⁡x)/1+x2p_X(x) = \varphi(\operatorname{asinh} x)/\sqrt{1 + x^2},和直方图逐格吻合。(附带一个观察:XX 的尾巴比高斯重得多——一个光滑的单调变换就能改变分布的尾部行为。)
  • X=Z2X = Z^2 不单调:xx 有两个原像 ±x\pm\sqrt{x}。只套一个反函数 h(x)=+xh(x) = +\sqrt{x},得到的密度只有真实值的一半(x=1x = 1 时 0.1210 vs 直方图 0.2432);要把两个原像的贡献加起来才对。更糟的是,看到一个 xx,我们无法确定它来自哪个 zz。

所以流模型要求变换可逆:每个 xx 恰好对应一个 zz,密度公式只有一项,“推断”也是确定的。

2.5 一个单调变换就能造出双峰

代码 01 第 4 部分:f(z)=z+0.9sin⁡(πz)/πf(z) = z + 0.9\sin(\pi z)/\pi,f′(z)=1+0.9cos⁡(πz)∈[0.1,1.9]f'(z) = 1 + 0.9\cos(\pi z) \in [0.1, 1.9],严格单调。把 Z∼N(0,1)Z \sim \mathcal{N}(0, 1) 推过去,XX 的密度在 x=±1x = \pm 1 处有两个尖峰(峰值 pZ(1)/f′(1)=2.42p_Z(1)/f'(1) = 2.42),中间有一个谷。

原因就写在 pX(x)=pZ(z)/f′(z)p_X(x) = p_Z(z)/f'(z) 里:ff 在 z=±1z = \pm 1 附近几乎是平的(导数只有 0.1),一大段 zz 被”挤”到很短的一段 xx 上,密度就高;在 z=0z = 0 附近拉伸得最厉害,密度被摊薄。单峰的高斯 → 双峰,只用了一个单调、可逆、处处光滑的一维函数。 把很多这样的变换叠起来、推广到高维,就是归一化流。代价也看得见:要算 pX(x)p_X(x),必须能求 f−1(x)f^{-1}(x) 和 f′(z)f'(z)。


3. 几何:行列式与体积 · Determinants and volumes

slide 9:设 ZZ 在单位超立方体 [0,1]n[0, 1]^n 上均匀,X=AZX = AZ,AA 是可逆方阵,W=A−1W = A^{-1}。XX 服从什么分布?几何上,AA 把单位超立方体映成一个平行多面体(parallelotope,正方形 / 立方体 → 平行四边形 / 平行六面体的推广)。A=(acbd)A = \begin{pmatrix} a & c \\ b & d\end{pmatrix} 把单位正方形映成一个平行四边形。

slide 10:平行多面体的体积等于 AA 的行列式的绝对值,det⁡A=ad−bc\det A = ad - bc。XX 在面积为 ∣det⁡A∣|\det A| 的平行多面体上均匀分布,于是

pX(x)=pZ(Wx)/∣det⁡A∣=pZ(Wx) ∣det⁡W∣,p_X(x) = p_Z(Wx)/|\det A| = p_Z(Wx)\,|\det W|,

因为 det⁡W=det⁡A−1=1/det⁡A\det W = \det A^{-1} = 1/\det A。和一维公式的相似之处一目了然:∣h′∣|h'| 是长度的缩放,∣det⁡∣|\det| 是面积 / 体积的缩放。

代码 02 第 1 部分(A=[[2,1],[0.5,1.5]]A = [[2, 1], [0.5, 1.5]]):ad−bc=2.5ad - bc = 2.5;鞋带公式算出的平行四边形面积 2.5000;在外接矩形里撒 40 万个点、映回单位正方形判断”在不在里面”,估计面积 2.4969;XX 在 (1.6,1.1)(1.6, 1.1) 处的密度:公式 1/2.5=0.41/2.5 = 0.4,样本直方图 0.41。行列式可以是负数(AA 含一次翻转),密度公式用绝对值——翻转不改变体积。


4. 一般的变量替换 · The general change of variables

4.1 雅可比行列式

slide 11:线性变换的体积变化由 det⁡A\det A 给出;对非线性变换 f(⋅)f(\cdot),线性化以后的体积变化由雅可比矩阵的行列式给出。

变量替换(一般情形):f:Rn→Rnf: \mathbb{R}^n \to \mathbb{R}^n 可逆,X=f(Z)X = f(Z),Z=f−1(X)Z = f^{-1}(X),则 pX(x)=pZ(f−1(x))∣det⁡(∂f−1(x)∂x)∣.p_X(x) = p_Z\big(f^{-1}(x)\big)\left|\det\left(\frac{\partial f^{-1}(x)}{\partial x}\right)\right|.

三条注释:

  • Note 0:它推广了一维的 pX(x)=pZ(h(x))∣h′(x)∣p_X(x) = p_Z(h(x))|h'(x)|。
  • Note 1:和 VAE 不同,xx、zz 必须是连续的,而且维数相同。x∈Rnx \in \mathbb{R}^n,则 z∈Rnz \in \mathbb{R}^n。(维数不同的映射不可能可逆;离散的 xx 要特殊处理,第 8 讲的”去量化”。)
  • Note 2:对任何可逆矩阵 AA,det⁡(A−1)=det⁡(A)−1\det(A^{-1}) = \det(A)^{-1},所以也可以写成正向的形式: pX(x)=pZ(z)∣det⁡(∂f(z)∂z)∣−1,z=f−1(x).p_X(x) = p_Z(z)\left|\det\left(\frac{\partial f(z)}{\partial z}\right)\right|^{-1}, \qquad z = f^{-1}(x).

4.2 局部线性化:极坐标

为什么非线性变换的体积变化是雅可比行列式?因为可导的函数在每一点附近”看起来像”一个线性变换:f(z+δ)≈f(z)+J(z)δf(z + \delta) \approx f(z) + J(z)\delta。一个边长 ε\varepsilon 的小方块被映成一个近似的平行四边形,面积 ≈∣det⁡J(z)∣ ε2\approx |\det J(z)|\,\varepsilon^2。

代码 02 第 2 部分用极坐标 (r,θ)↦(rcos⁡θ,rsin⁡θ)(r, \theta) \mapsto (r\cos\theta, r\sin\theta) 验证:雅可比行列式是 rr。在 (r,θ)(r, \theta) 平面上以 (r0,θ0)(r_0, \theta_0) 为中心、边长 0.01 的小正方形,映射过去的曲边四边形面积 / ε2\varepsilon^2 在 r0=0.2,1,3r_0 = 0.2, 1, 3 时分别是 0.2000、1.0000、3.0000——恰好是 r0r_0。rr 越大,同样的 dθd\theta 扫过的弧越长,面积放大得越多。

一个经典的推论:在 (r,θ)(r, \theta) 上均匀撒点,变换以后点会挤在圆心附近——pX(x)=pU(u)/∣det⁡J∣=12πrp_X(x) = p_U(u)/|\det J| = \frac{1}{2\pi r}。半径 0.25 的圆里有 24.9% 的点,而均匀圆盘应该只有 6.25%。要得到圆盘上的均匀分布,rr 必须取 U\sqrt{U}(练习 6)。这就是用变量替换公式”设计”一个变换,让它产生我们想要的分布——流模型做的是同一件事,只是变换要从数据里学。


5. 归一化流 · Normalizing flows

5.1 二维的例子

slide 12:Z1,Z2Z_1, Z_2 有联合密度 pZ1,Z2p_{Z_1, Z_2};u=(u1,u2):R2→R2u = (u_1, u_2): \mathbb{R}^2 \to \mathbb{R}^2 可逆,反函数 v=(v1,v2)v = (v_1, v_2);X1=u1(Z1,Z2)X_1 = u_1(Z_1, Z_2),X2=u2(Z1,Z2)X_2 = u_2(Z_1, Z_2)。则

pX1,X2(x1,x2)=pZ1,Z2(v1(x),v2(x))∣det⁡(∂v1∂x1∂v1∂x2∂v2∂x1∂v2∂x2)∣  (反向)=pZ1,Z2(z1,z2)∣det⁡(∂u1∂z1∂u1∂z2∂u2∂z1∂u2∂z2)∣−1  (正向).p_{X_1, X_2}(x_1, x_2) = p_{Z_1, Z_2}(v_1(x), v_2(x))\left|\det\begin{pmatrix}\frac{\partial v_1}{\partial x_1} & \frac{\partial v_1}{\partial x_2} \\ \frac{\partial v_2}{\partial x_1} & \frac{\partial v_2}{\partial x_2}\end{pmatrix}\right| \;(\text{反向}) = p_{Z_1, Z_2}(z_1, z_2)\left|\det\begin{pmatrix}\frac{\partial u_1}{\partial z_1} & \frac{\partial u_1}{\partial z_2} \\ \frac{\partial u_2}{\partial z_1} & \frac{\partial u_2}{\partial z_2}\end{pmatrix}\right|^{-1} \;(\text{正向}).

代码 02 第 3 部分用第 5 讲的香蕉形 u(z)=(z1,0.5z2+0.4(z12−1))u(z) = (z_1, 0.5z_2 + 0.4(z_1^2 - 1)) 验证:四个点上,反向写法、正向写法和 toy2d.Banana 的闭式解逐位相同(例如 (1,0.5)(1, 0.5) 处都是 0.117100);在 [−8,8]2[-8, 8]^2 上数值积分 ∫pX=0.999994\int p_X = 0.999994。这个变换的雅可比是下三角的(x1x_1 只依赖 z1z_1),行列式就是对角线之积 1×0.51 \times 0.5——记住这一点,§7 会用到。

5.2 归一化流模型

slide 13:考虑一个有向的隐变量模型,观测 XX、隐变量 ZZ。在归一化流模型里,ZZ 和 XX 之间的映射 fθ:Rn→Rnf_\theta: \mathbb{R}^n \to \mathbb{R}^n 是确定性、可逆的:X=fθ(Z)X = f_\theta(Z),Z=fθ−1(X)Z = f_\theta^{-1}(X)。由变量替换,边际似然是

pX(x;θ)=pZ(fθ−1(x))∣det⁡(∂fθ−1(x)∂x)∣.p_X(x; \theta) = p_Z\big(f_\theta^{-1}(x)\big)\left|\det\left(\frac{\partial f_\theta^{-1}(x)}{\partial x}\right)\right|.

5.3 “归一化”与”流”

slide 14 解释了这个名字:

  • 归一化(normalizing):变量替换公式在一次可逆变换之后,给出的仍然是一个归一化的密度(积分为 1)——不需要像第 11–12 讲的能量模型那样去算一个归一化常数。
  • 流(flow):可逆变换可以互相复合: zm=fθm∘⋯∘fθ1(z0)=fθm(fθm−1(⋯(fθ1(z0))))≜fθ(z0).z_m = f_\theta^m \circ \cdots \circ f_\theta^1(z_0) = f_\theta^m(f_\theta^{m-1}(\cdots(f_\theta^1(z_0)))) \triangleq f_\theta(z_0). 从一个简单的分布 z0z_0(例如高斯)出发,经过 MM 个可逆变换,最后得到 x=zMx = z_M。由变量替换,
pX(x;θ)=pZ(fθ−1(x))∏m=1M∣det⁡(∂(fθm)−1(zm)∂zm)∣.p_X(x; \theta) = p_Z\big(f_\theta^{-1}(x)\big)\prod_{m=1}^M\left|\det\left(\frac{\partial (f_\theta^m)^{-1}(z_m)}{\partial z_m}\right)\right|.

(乘积的行列式等于行列式的乘积。)取对数,就是逐层相加。代码 02 第 4 部分把五种层串起来,逐层的 log det 之和与”对整个复合函数自动求导再求行列式”的结果最大差 3.9×10−163.9 \times 10^{-16}。所以每一层只要能便宜地算出自己的 log det,整个流的 log det 就是逐层相加,不需要碰完整的 n×nn \times n 矩阵。

代码里的约定(flows.py):每一层都有 forward(z) → (x, log|det ∂x/∂z|)(采样方向)和 inverse(x) → (z, log|det ∂z/∂x|)(求密度方向),两个 log det 互为相反数。


6. 平面流 · Planar flows

6.1 定义与行列式

slide 19(Rezende & Mohamed 2015):

x=fθ(z)=z+u h(w⊤z+b),θ=(w,u,b),x = f_\theta(z) = z + u\,h(w^\top z + b), \qquad \theta = (w, u, b),

hh 是一个非线性函数(如 tanh)。它只在一个方向上做文章:zz 在 ww 上的投影决定了沿 uu 方向推多远;离超平面 w⊤z+b=0w^\top z + b = 0 近的点被推得多,远处的点因为 hh 饱和几乎不动。雅可比 J=I+h′(w⊤z+b) uw⊤J = I + h'(w^\top z + b)\,u w^\top 是”单位阵 + 秩 1 矩阵”,矩阵行列式引理 det⁡(I+uv⊤)=1+v⊤u\det(I + u v^\top) = 1 + v^\top u(练习 4)给出

∣det⁡∂fθ(z)∂z∣=∣1+h′(w⊤z+b) u⊤w∣,\left|\det\frac{\partial f_\theta(z)}{\partial z}\right| = \left|1 + h'(w^\top z + b)\,u^\top w\right|,

只要 O(n)O(n),不用 O(n3)O(n^3)。

可逆的条件:需要限制参数和非线性函数。例如 h=tanh⁡h = \tanh 时要求 h′(w⊤z+b) u⊤w≥−1h'(w^\top z + b)\,u^\top w \geq -1,即 u⊤w≥−1u^\top w \geq -1(练习 5)。代码里把自由参数 uu 修正成 u^=u+(m(w⊤u)−w⊤u)w∥w∥2\hat{u} = u + (m(w^\top u) - w^\top u)\frac{w}{\lVert w\rVert^2},m(a)=−1+softplus(a)m(a) = -1 + \mathrm{softplus}(a),保证 u^⊤w>−1\hat{u}^\top w > -1。

代码 03 第 1 部分:w=(3,0)w = (3, 0) 时,u^⊤w=2.63>0\hat{u}^\top w = 2.63 > 0 的平面流把高斯”撕”成两半,u^⊤w=−0.66\hat{u}^\top w = -0.66 的把它”挤”成一条窄带(u=(1.2,0)u = (1.2, 0)、(−0.3,0)(-0.3, 0),修正以后真正起作用的是 u^\hat{u})。不修正、u⊤w=−3u^\top w = -3 时,z1↦x1=z1−tanh⁡(3z1)z_1 \mapsto x_1 = z_1 - \tanh(3z_1) 不再单调:z1=−1,0,1z_1 = -1, 0, 1 被映到了几乎同一个 x1≈0x_1 \approx 0,det⁡J\det J 在 29.3% 的样本上 ≤ 0——平面被折叠了,变量替换公式失效(§2.4 的 Z2Z^2)。

slide 15 展示了 10 个平面变换能把高斯或均匀分布塑造成复杂的形状。代码 03 第 2 部分用 10 层随机参数的平面流重现了这张图:同一串变换作用在高斯和均匀分布上,得到的是”同样的形变”作用在两种起点上。

6.2 用平面流拟合一个目标密度

Rezende & Mohamed 用平面流做变分推断:给一个只知道到常数为止的目标密度 p~(x)=e−U(x)\tilde{p}(x) = e^{-U(x)},在流的族里找最接近它的 qq,最小化

DKL(q∥p)=Ez∼N(0,I)[log⁡q(f(z))+U(f(z))]+log⁡Z,log⁡q(f(z))=log⁡N(z)−log⁡∣det⁡∂f∂z∣.D_{\mathrm{KL}}(q \Vert p) = \mathbb{E}_{z \sim \mathcal{N}(0, I)}\big[\log q(f(z)) + U(f(z))\big] + \log Z, \qquad \log q(f(z)) = \log \mathcal{N}(z) - \log\left|\det \tfrac{\partial f}{\partial z}\right|.

整个训练只用正向(z→xz \to x)和样本自己的 log⁡q\log q,不需要求逆,目标也不需要归一化。这正是第 6 讲 slide 24 说的”用流做更灵活的近似后验”。代码 03 第 3 部分(每个 3,000 步,KL 是真正的 KL,log⁡Z\log Z 用网格积分算出):

目标训练方式K=1K = 1K=2K = 2K=8K = 8K=32K = 32
圆环(U1U_1)直接最小化0.967(右 100%)0.901(右 100%)0.697(右 100%)0.699(右 0%)
圆环(U1U_1)退火1.176(右 50%)0.927(右 50%)0.049(右 50%)0.051(右 52%)
波浪(U2U_2 × 高斯包络)直接最小化0.9220.2350.2120.238
波浪退火1.5091.3600.3520.105

(括号里是 qq 的样本落在右半平面的比例;目标的左右两瓣质量相等,应为 50%。)

最醒目的是圆环、直接最小化:K=8K = 8 和 K=32K = 32 的 KL 都停在 0.697 ≈ ln 2 = 0.693,样本全在一侧。这不是巧合:目标的两瓣质量相等,qq 若完美地拟合其中一瓣、完全忽略另一瓣,DKL(q∥p)=ln⁡2D_{\mathrm{KL}}(q \Vert p) = \ln 2(练习 7)。这是第 4 讲 §2.3 的反向 KL 模式寻找:qq 一旦落进一个峰,跨到另一个峰要先经过目标几乎为 0 的地带,代价很大,梯度不会带它过去。层数再多也没用——问题出在目标函数和优化,不在表达力。

退火(Rezende & Mohamed 的做法):前一半步数里把目标换成 p~β\tilde{p}^\beta,β\beta 从 0.01 线性增加到 1。β\beta 小时目标很平坦,qq 先铺满整个区域;β\beta 慢慢变大,qq 再收拢到各个峰上。圆环的 KL 从 0.70 降到 0.05,两瓣各占一半。波浪更复杂:退火让 K=32K = 32 从 0.24 降到 0.10,却让 K=8K = 8 变差了;直接训练时 K=32K = 32 也不比 K=8K = 8 好。反向 KL 的优化对训练方式很敏感,平面流每层只有 2n+1=52n + 1 = 5 个参数,需要叠很多层、训练很久。

6.3 反过来求密度的代价

平面流的逆没有闭式解。记 s=w⊤zs = w^\top z,由 x=z+u^tanh⁡(s+b)x = z + \hat{u}\tanh(s + b) 得 w⊤x=s+(w⊤u^)tanh⁡(s+b)w^\top x = s + (w^\top\hat{u})\tanh(s + b)——关于 ss 单调递增,可以二分求解,再 z=x−u^tanh⁡(s+b)z = x - \hat{u}\tanh(s + b)。代码 03 第 4 部分:32 层、1 万个点,正向(采样 + 样本自己的 log⁡q\log q)6.5 ms,反向(给定 xx 求 log⁡p(x)\log p(x),每层二分 80 次)224 ms,慢约 35 倍;结果是对的(和正向得到的 log⁡q\log q 差 4.7×10−134.7 \times 10^{-13})。

这决定了平面流的用途:变分推断只需要正向,平面流很合适;密度估计 / 最大似然训练要对每个训练样本求 f−1(x)f^{-1}(x),平面流就太慢了。我们需要”正反两个方向都便宜、行列式也便宜”的变换。


7. 学习与推断 · Learning and inference

7.1 最大似然、采样、推断

slide 16:

  • 学习:在数据集 D\mathcal{D} 上最大似然, max⁡θlog⁡pX(D;θ)=∑x∈D[log⁡pZ(fθ−1(x))+log⁡∣det⁡(∂fθ−1(x)∂x)∣].\max_\theta \log p_X(\mathcal{D}; \theta) = \sum_{x \in \mathcal{D}}\left[\log p_Z\big(f_\theta^{-1}(x)\big) + \log\left|\det\left(\frac{\partial f_\theta^{-1}(x)}{\partial x}\right)\right|\right].
  • 精确的似然:通过反向变换 x↦zx \mapsto z 和变量替换公式——不是 ELBO 那样的下界。
  • 采样:通过正向变换,z∼pZ(z)z \sim p_Z(z),x=fθ(z)x = f_\theta(z)。
  • 隐表示:通过反向变换推断,z=fθ−1(x)z = f_\theta^{-1}(x)——不需要推断网络!

7.2 对流模型的要求

slide 17:

  1. 简单的先验 pZ(z)p_Z(z),能高效采样、能算似然。例如各向同性的高斯。
  2. 可逆变换,而且两个方向都好算:求似然需要高效的 x↦zx \mapsto z,采样需要高效的 z↦xz \mapsto x。
  3. 雅可比行列式好算:求似然还需要 n×nn \times n 雅可比矩阵的行列式,nn 是数据的维数。n×nn \times n 矩阵的行列式要 O(n3)O(n^3)——在训练循环里完全负担不起!

关键想法:选择雅可比矩阵有特殊结构的变换。 例如三角矩阵的行列式是对角线之积,O(n)O(n)。代码 02 第 5 部分:n=2048n = 2048 时稠密矩阵的 slogdet 要约 30 ms,三角矩阵把对角线加起来只要 0.02 ms,差上千倍;nn 每翻一倍,稠密行列式的时间涨约 8 倍。一张 64×64 的彩色图有 12,288 维,每个训练步对每张图都算一次 12,288 × 12,288 的行列式,完全不现实。

7.3 三角雅可比

slide 18:x=(x1,…,xn)=f(z)=(f1(z),…,fn(z))x = (x_1, \dots, x_n) = f(z) = (f_1(z), \dots, f_n(z)),雅可比 J=∂f∂zJ = \frac{\partial f}{\partial z} 一般是满的。如果 xi=fi(z)x_i = f_i(z) 只依赖 z≤iz_{\leq i},JJ 就是下三角的:

J=(∂f1∂z1⋯0⋯⋯⋯∂fn∂z1⋯∂fn∂zn),det⁡J=∏i∂fi∂zi,J = \begin{pmatrix}\frac{\partial f_1}{\partial z_1} & \cdots & 0 \\ \cdots & \cdots & \cdots \\ \frac{\partial f_n}{\partial z_1} & \cdots & \frac{\partial f_n}{\partial z_n}\end{pmatrix}, \qquad \det J = \prod_i \frac{\partial f_i}{\partial z_i},

行列式可以在线性时间内算出。类似地,若 xix_i 只依赖 z≥iz_{\geq i},JJ 是上三角的。”xix_i 只依赖前面的 zz“——这正是第 3 讲自回归的结构。第 8 讲会看到:自回归模型本身就是流(MAF),耦合层也是三角雅可比。

7.4 用最大似然训练二维的流

代码 04 先在香蕉形上比较两种流:

模型参数DKL(p∥q)D_{\mathrm{KL}}(p \Vert q)z=f−1(x)z = f^{-1}(x) 的协方差zz 的峰度(高斯 = 3)
线性流(逐元素仿射 + LU 线性层)160.415≈I\approx I(8.88, 5.28)
一层二维三角变换1,1880.004≈I\approx I(3.03, 3.04)
  • 线性流只是一个高斯(线性变换把高斯变成高斯)。最大似然把均值、协方差学对了,所以 z=f−1(x)z = f^{-1}(x) 的均值是 0、协方差是 II;但画出来仍是一根香蕉,峰度也不是 3——”zz 是标准高斯”只是表面上满足了。
  • 一层三角变换 x1=z1ea1+m1x_1 = z_1 e^{a_1} + m_1,x2=z2ea2(x1)+m2(x1)x_2 = z_2 e^{a_2(x_1)} + m_2(x_1)(a2,m2a_2, m_2 是小 MLP):香蕉形本身就是这样生成的,模型族里包含真实分布。KL 几乎为 0,学到的 m2(x1)m_2(x_1) 和真实的 0.4(x12−1)0.4(x_1^2 - 1) 吻合(x1=0x_1 = 0 时 −0.364 vs −0.400),ea2≈0.50e^{a_2} \approx 0.50,z=f−1(x)z = f^{-1}(x) 变成了标准高斯;数值积分 ∫q=1.00000\int q = 1.00000。

双月牙不在一层三角变换的模型族里(一层里 x1x_1 只被逐元素缩放平移,边缘还是高斯),于是叠 KK 层、层间交换坐标:

层数 KK参数DKL(p∥q)D_{\mathrm{KL}}(p \Vert q)(nat)
11,1880.488
22,3760.159
44,7520.047
89,5040.032

(对照:第 5 讲 EM 拟合的高斯混合,16 个成分 0.032。)每一层都是”一个坐标不动,另一个坐标按它做仿射变换”——这正是第 8 讲的仿射耦合层(RealNVP)在二维的样子。它的正向、反向、行列式都便宜,不像平面流那样要二分求逆,所以可以直接做最大似然。

7.5 隐表示,以及流不能改变拓扑

代码 04 第 4 部分把 4,000 个数据点映到 z=f−1(x)z = f^{-1}(x)(8 层的流):上面的月牙占 zz 空间的右半边,下面的月牙占左半边,合起来像一个标准高斯(半径 2 以内的比例 0.845,标准高斯 0.865)。隐表示是精确、确定的,不需要推断网络,也没有后验近似的误差(对比第 6 讲的编码器)。但 zz 和 xx 维数相同,zz 不是压缩的表示,每一维也不一定有语义——流学到的是一个把数据”高斯化”的坐标变换,而不是 VAE 那种低维的变化因素。

在 zz 空间里从一个”上月牙”点沿直线走到一个”下月牙”点,映回 xx 空间:zz 空间每步只走 0.0115,xx 空间里却有一步跳了 0.985——直接跨过了两个月牙之间的空隙。在那一步的位置,雅可比的两个奇异值是 72.2 和 0.0169,∣det⁡∣=1.22|\det| = 1.22:沿一个方向拉长 72 倍、沿另一个方向压扁 59 倍,面积几乎不变。zz 空间里交界处一条细细的带子,被拉成 xx 空间里一条横跨空隙、又长又窄的带子。

这揭示了流的一个根本局限:连续、可逆的变换不能改变拓扑——它不能把一个连通的高斯真正”撕”成两块(或第 8 讲圆环的 8 块)。要拟合分开的数据,只能留一道被极度拉伸的”细缝”,密度图里两个月牙之间总有一点残留质量。


8. 2023 年之后 · Since 2023

  • “流”这个名字在流匹配里延续。 2023 年以来最有影响的生成模型训练方法之一是流匹配(flow matching,Lipman et al., ICLR 2023)与整流(rectified flow,Liu et al., ICLR 2023):用一个神经网络表示一个随时间变化的速度场,从噪声沿常微分方程”流”到数据。它是连续时间的归一化流(Chen et al. 2018 的神经 ODE / FFJORD 的后继):变量替换公式变成了沿轨迹积分的”瞬时变量替换”(log det 的变化率 = 速度场的散度),而训练不再需要算行列式。Stable Diffusion 3 等图像模型就用整流目标训练。第 16 讲和本仓库的 MIT6.S184 会详细展开。
  • 离散时间的归一化流复兴。 长期以来,流模型在图像上的样本质量落后于扩散模型和 GAN。2024 年以来的工作把 Transformer 用到流里——例如 Apple 的 TarFlow(Zhai et al.,用 Transformer 做自回归流的条件网络)、Google 的 Jet(基于 ViT 的耦合流)——报告了在 ImageNet 等数据上显著缩小的差距,说明本讲的”精确似然 + 一步采样”仍有竞争力。
  • 科学计算里的流。 在统计物理、格点场论、分子构象采样中,流被用来学习一个能精确算密度的提议分布(“Boltzmann 生成器”一类的方法),再用重要性采样或 MCMC 修正。这里用的正是 §6.2 的反向 KL训练(目标是一个未归一化的 Boltzmann 分布),模式寻找和 §7.5 的拓扑问题都是那个领域的核心难点。

9. 小结 · Summary

  1. 流模型 = 简单的先验 + 确定、可逆的变换 x=fθ(z)x = f_\theta(z):每个 xx 恰好对应一个 zz,似然精确可算,没有 ELBO 差距;代价是 zz、xx 维数相同、必须连续。
  2. 一维变量替换 pX(x)=pZ(h(x))∣h′(x)∣=pZ(z)/∣f′(z)∣p_X(x) = p_Z(h(x))|h'(x)| = p_Z(z)/|f'(z)|:密度不是概率,变换拉伸的地方密度变稀、压缩的地方变密。必须单调(不单调时要把所有原像加起来,推断也不确定)。一个单调的光滑变换就能把单峰变成双峰。
  3. 行列式 = 体积的缩放;一般情形用雅可比行列式:pX(x)=pZ(f−1(x))∣det⁡∂f−1/∂x∣=pZ(z)∣det⁡∂f/∂z∣−1p_X(x) = p_Z(f^{-1}(x))|\det \partial f^{-1}/\partial x| = p_Z(z)|\det \partial f/\partial z|^{-1}。
  4. 归一化流:复合一串可逆变换,log det 逐层相加;“归一化”指变换后的密度自动归一化。
  5. 平面流 x=z+u h(w⊤z+b)x = z + u\,h(w^\top z + b):矩阵行列式引理让行列式 O(n)O(n);需要 u⊤w≥−1u^\top w \geq -1 才可逆;适合只需正向的变分推断。用反向 KL 拟合双峰目标时会只盖住一个峰(KL ≈ ln 2),退火能缓解。反向求密度要二分,慢约 35 倍。
  6. 设计要求:先验简单;两个方向都好算;雅可比行列式好算——让雅可比是三角的,O(n3)→O(n)O(n^3) \to O(n)。三角雅可比 = 自回归结构。
  7. 二维实验:线性流只是高斯;一层三角变换能精确拟合香蕉形;叠 8 层(层间交换坐标)拟合双月牙到 KL 0.032。流不能改变拓扑:拟合分开的数据只能留下被极度拉伸的细缝。

10. 常见误区 · Common pitfalls

  1. “pX(4)=pZ(1)p_X(4) = p_Z(1),因为 X=4X = 4 当且仅当 Z=1Z = 1。” 密度不是概率;要乘上长度 / 体积的缩放 ∣h′(x)∣|h'(x)|(§2.2)。
  2. “任何可导的变换都能用变量替换公式。” 必须可逆;不单调时一个 xx 有多个原像,只套一个反函数会漏掉概率(§2.4:Z2Z^2 只得到一半的密度)。
  3. “行列式小于 0 时密度为负。” 公式里是绝对值;负的行列式只是多了一次翻转(§3)。
  4. “流的隐变量 zz 就像 VAE 的隐变量。” 维数和 xx 相同,没有压缩;它是一个”高斯化的坐标”,每一维未必有语义(§7.5)。
  5. “层数越多,流越灵活,拟合越好。” 反向 KL 训练时,层数再多也可能卡在只盖住一个峰的局部最优(§6.2:K = 32 和 K = 8 都停在 ln 2)。
  6. “平面流可以拿来做密度估计。” 可以算,但每个样本都要逐层二分求逆,太慢(§6.3);它适合只需正向的变分推断。
  7. ”z=f−1(x)z = f^{-1}(x) 的均值是 0、协方差是 II,说明流学对了。” 线性流就能做到这一点,而形状完全不对(§7.4)。要看完整的分布(KL、峰度、画出来)。
  8. “流可以把一个高斯变成任意分布,包括几块分开的。” 连续可逆的变换不能改变拓扑,只能用被极度拉伸的细缝去近似(§7.5)。
  9. “雅可比行列式只是一个理论上的修正项。” 它是训练的核心代价:稠密行列式 O(n3)O(n^3),在高维完全不可行;所有实用的流都围绕”让行列式便宜”来设计(§7.2)。

11. 练习 · Exercises

练习 1(线性变换的高斯) Z∼N(0,1)Z \sim \mathcal{N}(0, 1),X=σZ+μX = \sigma Z + \mu(σ>0\sigma > 0)。用变量替换公式写出 pX(x)p_X(x),确认它是 N(μ,σ2)\mathcal{N}(\mu, \sigma^2)。σ<0\sigma < 0 时呢?

参考答案

h(x)=(x−μ)/σh(x) = (x - \mu)/\sigma,∣h′(x)∣=1/∣σ∣|h'(x)| = 1/|\sigma|,pX(x)=φ(x−μσ)1∣σ∣=1∣σ∣2πe−(x−μ)2/2σ2p_X(x) = \varphi\left(\frac{x - \mu}{\sigma}\right)\frac{1}{|\sigma|} = \frac{1}{|\sigma|\sqrt{2\pi}}e^{-(x - \mu)^2/2\sigma^2}。σ<0\sigma < 0 时 ff 单调递减,公式里的绝对值保证结果相同:仍是 N(μ,σ2)\mathcal{N}(\mu, \sigma^2)(高斯关于均值对称,翻转不改变它)。这也是 VAE 的重参数化 z=μ+σϵz = \mu + \sigma\epsilon(第 6 讲 §3.3)。

练习 2(导数为 0 的单调变换) Z∼N(0,1)Z \sim \mathcal{N}(0, 1),X=Z3X = Z^3。ff 严格单调,但 f′(0)=0f'(0) = 0。写出 pX(x)p_X(x)。x→0x \to 0 时密度怎样?这个 ff 的反函数可导吗?

参考答案

h(x)=x1/3h(x) = x^{1/3}(实数立方根),∣h′(x)∣=13∣x∣−2/3|h'(x)| = \frac{1}{3}|x|^{-2/3},pX(x)=φ(x1/3)13∣x∣2/3p_X(x) = \varphi(x^{1/3})\frac{1}{3|x|^{2/3}}。x→0x \to 0 时密度趋于无穷(但仍可积:∫∣x∣−2/3dx\int |x|^{-2/3}dx 在 0 附近收敛)。反函数在 0 处不可导(导数无穷大)。流模型通常要求 ff 是微分同胚(可逆、正反都可导),f′f' 处处不为 0——这也是 §6.1 要求 1+h′u⊤w>01 + h'u^\top w > 0(严格)的原因。

练习 3(三角矩阵的行列式) 证明下三角矩阵的行列式等于对角线元素之积。解一个 n×nn \times n 下三角方程组 Lz=bLz = b 要多少次乘法?为什么三角雅可比的流”求逆也便宜”?

参考答案

按第一行展开:第一行只有 L11L_{11} 非零,det⁡L=L11det⁡L′\det L = L_{11}\det L',L′L' 是去掉第一行第一列的下三角矩阵;归纳即得 ∏iLii\prod_i L_{ii}。前代法 z1=b1/L11z_1 = b_1/L_{11},zi=(bi−∑j<iLijzj)/Liiz_i = (b_i - \sum_{j<i}L_{ij}z_j)/L_{ii},约 n2/2n^2/2 次乘法。对三角雅可比的流,”xix_i 只依赖 z≤iz_{\leq i}“意味着可以按顺序逐个解出 ziz_i——不过对非线性的流,这一步可能要按顺序做 nn 次(第 8 讲的 MAF 采样 / IAF 求逆),而耦合层的结构让它一次完成。

练习 4(矩阵行列式引理) 证明 det⁡(I+uv⊤)=1+v⊤u\det(I + uv^\top) = 1 + v^\top u(u,v∈Rnu, v \in \mathbb{R}^n)。提示:uv⊤uv^\top 的特征值是什么?

参考答案

uv⊤uv^\top 的秩至多为 1:任何与 vv 正交的向量 yy 满足 uv⊤y=0uv^\top y = 0,这给出 n−1n - 1 个特征值 0;uv⊤u=(v⊤u)uuv^\top u = (v^\top u)u,所以 uu 是特征向量,特征值 v⊤uv^\top u。I+uv⊤I + uv^\top 的特征值是 11(n−1n - 1 重)和 1+v⊤u1 + v^\top u,行列式 = 特征值之积 = 1+v⊤u1 + v^\top u。平面流的雅可比 I+h′(⋅) uw⊤I + h'(\cdot)\,u w^\top 取 v=h′(⋅)wv = h'(\cdot)w 即得 slide 19 的公式。

练习 5(平面流可逆的条件) h=tanh⁡h = \tanh。(a) 证明沿 ww 方向,s=w⊤z↦w⊤x=s+(w⊤u)tanh⁡(s+b)s = w^\top z \mapsto w^\top x = s + (w^\top u)\tanh(s + b) 单调递增当且仅当 w⊤u≥−1w^\top u \geq -1。(b) 证明 u^⊤w=m(w⊤u)=−1+softplus(w⊤u)>−1\hat{u}^\top w = m(w^\top u) = -1 + \mathrm{softplus}(w^\top u) > -1。

参考答案

(a) 导数 1+(w⊤u)(1−tanh⁡2(s+b))1 + (w^\top u)(1 - \tanh^2(s + b)),而 1−tanh⁡2∈(0,1]1 - \tanh^2 \in (0, 1]。若 w⊤u≥−1w^\top u \geq -1,导数 ≥1−(1−tanh⁡2)≥0\geq 1 - (1 - \tanh^2) \geq 0(且只在孤立点可能为 0),单调;若 w⊤u<−1w^\top u < -1,在 s=−bs = -b 处导数 =1+w⊤u<0= 1 + w^\top u < 0,局部递减,不单调(代码 03 第 1 部分的折叠)。(b) u^⊤w=u⊤w+(m(w⊤u)−w⊤u)w⊤w∥w∥2=m(w⊤u)\hat{u}^\top w = u^\top w + (m(w^\top u) - w^\top u)\frac{w^\top w}{\lVert w\rVert^2} = m(w^\top u),softplus >0> 0,所以 >−1> -1。与 ww 垂直的部分保持不变,所以只要求一个方向就够了:zz 在与 ww 垂直的方向上只是被平移。

练习 6(圆盘上的均匀分布) 要在单位圆盘上均匀采样,令 θ∼U[0,2π]\theta \sim U[0, 2\pi]、r=g(V)r = g(V)、V∼U[0,1]V \sim U[0, 1]。用变量替换公式求 gg。(提示:圆盘上均匀意味着 rr 的边缘密度是 2r2r。)

参考答案

均匀圆盘的密度 1/π1/\pi,换到极坐标乘上 ∣det⁡J∣=r|\det J| = r:p(r,θ)=r/πp(r, \theta) = r/\pi,rr 的边缘密度 2r2r,CDF r2r^2。由逆 CDF,r=Vr = \sqrt{V}(代码 02 第 2 部分的第三列)。r∼U[0,1]r \sim U[0, 1] 时 rr 的密度是 1,换回 xx 坐标密度 12πr\frac{1}{2\pi r},在圆心附近发散——点挤在中间。

练习 7(为什么是 ln 2) 目标 p=12pA+12pBp = \frac{1}{2}p_A + \frac{1}{2}p_B,pAp_A、pBp_B 的支撑互不重叠。证明:若 q=pAq = p_A,则 DKL(q∥p)=ln⁡2D_{\mathrm{KL}}(q \Vert p) = \ln 2;而 DKL(p∥q)=∞D_{\mathrm{KL}}(p \Vert q) = \infty。由此解释代码 03 的圆环为什么停在 0.697,以及为什么”前向 KL”不会犯这种错误。

参考答案

在 q=pAq = p_A 的支撑上,p=12pAp = \frac{1}{2}p_A,所以 log⁡qp=ln⁡2\log\frac{q}{p} = \ln 2,DKL(q∥p)=Eq[ln⁡2]=ln⁡2≈0.693D_{\mathrm{KL}}(q \Vert p) = \mathbb{E}_q[\ln 2] = \ln 2 \approx 0.693。圆环的两瓣不是严格不重叠(它们沿圆环相连),所以实测 0.697 略大于 ln 2。反过来,pp 在 BB 上有质量而 q=0q = 0,DKL(p∥q)=∞D_{\mathrm{KL}}(p \Vert q) = \infty:前向 KL(最大似然)绝不允许漏掉一个峰。反向 KL 对”漏掉”的惩罚只有 ln⁡(1/该峰的质量)\ln(1/\text{该峰的质量}),对”多放”的惩罚却是无穷——这就是模式寻找(第 4 讲 §2.3、第 5 讲 §6.1)。

练习 8(线性流的最大似然) 线性流 x=Az+bx = Az + b,z∼N(0,I)z \sim \mathcal{N}(0, I)。证明 x∼N(b,AA⊤)x \sim \mathcal{N}(b, AA^\top),并说明最大似然解满足 b=b = 样本均值、AA⊤=AA^\top = 样本协方差。这解释了代码 04 的什么现象?

参考答案

高斯经过仿射变换仍是高斯,均值 bb,协方差 A Cov(z)A⊤=AA⊤A\,\mathrm{Cov}(z)A^\top = AA^\top。多元高斯的 MLE 是样本均值和样本协方差(AA 只通过 AA⊤AA^\top 进入似然,所以 AA 本身不唯一——任何 AQAQ,QQ 正交,都给出同一个分布)。于是 z=A−1(x−b)z = A^{-1}(x - b) 的样本均值为 0、协方差为 II——代码 04 里线性流的 zz 前两阶矩完全”正确”,形状却仍是香蕉。

练习 9(动手:更多的层) 在 04_flow_mle.py 第 3 部分把 for K in [1, 2, 4, 8] 改成 [8, 16]。预测 K=16K = 16 的 KL 和训练用时。

参考答案(预测的思路)

用时大约翻倍(约 13 秒)。KL 可能略降(0.02 附近),也可能因为 3,000 步不够而几乎不变;训练集 KL 和新样本 KL 的差距可能变大(参数翻倍,只有 5,000 个训练点)。§7.5 的拓扑局限决定了 KL 不会降到 0:两个月牙之间总有一道细缝。具体数字以你的运行为准。

练习 10(动手:退火的长短) 在 03_planar_flows.py 第 3 部分把 anneal=1500 改成 500 和 2500,只看圆环、K=8K = 8 的那一格。预测两瓣是否都能被盖住。

参考答案(预测的思路)

退火太短(500 步),qq 可能来不及在平坦的目标上铺开,就被拉进一个峰,重新卡在 ln 2 附近;退火更长(2500 步),两瓣更有可能都被盖住,但留给 β=1\beta = 1 精细拟合的步数变少,KL 可能略高。退火本质上是一个优化技巧,最佳长度依问题而定。具体结果以你的运行为准。


12. 延伸阅读 · Further reading

原课材料

综述与经典

  • Papamakarios, Nalisnick, Rezende, Mohamed & Lakshminarayanan, Normalizing Flows for Probabilistic Modeling and Inference, JMLR 2021(最全面的综述)
  • Kobyzev, Prince & Brubaker, Normalizing Flows: An Introduction and Review of Current Methods, TPAMI 2021
  • Rezende & Mohamed, Variational Inference with Normalizing Flows, ICML 2015(平面流、径向流、目标密度 U1U_1–U4U_4)
  • Tabak & Turner, A Family of Nonparametric Density Estimation Algorithms, CPAM 2013(流的早期思想)
  • Dupont, Doucet & Teh, Augmented Neural ODEs, NeurIPS 2019;Cornish et al., Relaxing Bijectivity Constraints with Continuously Indexed Normalising Flows, ICML 2020(流的拓扑局限)

2023 年之后

  • Lipman, Chen, Ben-Hamu, Nickel & Le, Flow Matching for Generative Modeling, ICLR 2023;Liu, Gong & Liu, Flow Straight and Fast: Learning to Generate and Transfer Data with Rectified Flow, ICLR 2023
  • Zhai et al., Normalizing Flows are Capable Generative Models(TarFlow, 2024)

13. 下一讲预告 · Next lecture

本讲得到了一张”设计图纸”:流的每一层要可逆、两个方向都便宜、雅可比行列式便宜,三角雅可比是关键。二维里我们已经用”一个坐标不动、另一个坐标按它做仿射变换”拟合了双月牙。第 8 讲(原课 Lecture 8)把它推广到高维,并给出整个家族:

  • NICE:加性耦合层(一半坐标不动,另一半加上前一半的任意函数),体积不变;RealNVP:仿射耦合层,体积可变;
  • 自回归模型就是流:MAF(求密度快、采样慢)与 IAF(采样快、求密度慢),二者互为逆;
  • Parallel WaveNet:用 MAF 老师蒸馏出 IAF 学生,训练快、采样也快;
  • MintNet(掩码卷积的可逆网络)与高斯化流(逐维高斯化 + 旋转);
  • 以及一个本讲留下的问题:图像是离散的,流定义的是连续密度——怎么办?(去量化)
← 返回课程目录