微网站建设价格,买房网站排名,福建省住房和建设厅网站,点点网转wordpress归一化流 (Normalizing Flow) #xff08;Rezende Mohamed#xff0c;2015#xff09;学习可逆映射 f : X → Z f: X \rightarrow Z f:X→Z, 在这里X是我们的数据分布#xff0c;Z是选定的潜在分布。
归一化流是生成模型家族的一部分#xff0c;其中包括变分自动编… 归一化流 (Normalizing Flow) Rezende Mohamed2015学习可逆映射 f : X → Z f: X \rightarrow Z f:X→Z, 在这里X是我们的数据分布Z是选定的潜在分布。
归一化流是生成模型家族的一部分其中包括变分自动编码器 (VAE) (Kingma Welling, 2013)和生成对抗网络 (GAN) (Goodfellow 等人, 2014)。一旦我们学会了映射 f f f我们通过采样生成数据 z p Z zp_Z zpZ, 然后应用逆变换, f − 1 ( z ) X G e n f^{-1}(z)X_{Gen} f−1(z)XGen 。
在本博客中为了更好地理解归一化流我们将介绍算法的理论并在 PyTorch 中实现流模型。但首先让我们来看看归一化流的优点和缺点。
注意如果您对生成模型之间的比较不感兴趣您可以跳至“归一化流的工作原理”。
为什么要归一化流
有了 VAE 和 GAN 所显示的惊人结果为什么要使用归一化流我们列出了以下优点。(注大部分优点来自 GLOW 论文Kingma Dhariwal2018
NF 优化数据的精确对数似然 l o g ( p X log(p_X log(pX VAE 优化下限 (ELBO)GAN 学会欺骗鉴别器网络 NF 推断精确的潜变量值z这对于下游任务很有用。 VAE 推断潜变量值的分布GAN 没有潜在分布 具有节省内存的潜力NF 梯度计算按其深度恒定缩放。 VAE 和 GAN 的梯度计算都与其深度线性缩放 NF 只需要一个编码器即可学习。 VAE 需要编码器和解码器网络GAN 需要生成网络和判别网络
但请记住妈妈所说的话“天下没有免费的午餐”。
归一化流的一些缺点如下
可逆性和高效雅可比计算的要求限制了模型架构。 稍后会详细介绍…… 与其他生成模型相比NF 的资源/研究较少。 写这个博客的原因 NF 生成结果仍然落后于 VAE 和 GAN。
现在让我们深入了解一些理论
归一化流如何工作
在本节中我们简要回顾一下归一化流的核心。
变量的概率分布变化
考虑一个随机变量 X ∈ R d X \in \mathbb{R}^d X∈Rd (我们的数据分布和可逆变换 f : R d ↦ R d f: \mathbb{R}^d \mapsto \mathbb{R}^d f:Rd↦Rd。 那么有一个随机变量 Z ∈ R d Z \in \mathbb{R}^d Z∈Rd 是从 X X X 通过 f f f 映射而来。 进一步的 P ( X x ) P ( f ( X ) f ( x ) ) P ( Z z ) (0) P(X x) P(f(X) f(x)) P(Z z)\tag{0} P(Xx)P(f(X)f(x))P(Zz)(0) 现在考虑一些X上的某个区间 β \beta β那么存在Z上一定的区间 β ′ \beta^{\prime} β′ 使得 P ( X ∈ β ) P ( Z ∈ β ′ ) (1) P(X \in \beta) P(Z \in \beta^{\prime})\tag{1} P(X∈β)P(Z∈β′)(1) ∫ β p X d x ∫ β ′ p Z d z (2) \int_{\beta} p_X dx \int_{\beta^{\prime}} p_Z dz\tag{2} ∫βpXdx∫β′pZdz(2) 为了简单起见我们考虑单个区域。 d x ⋅ p X ( x ) d z ⋅ p Z ( z ) (3) dx \cdot p_X(x) dz \cdot p_Z(z) \tag{3} dx⋅pX(x)dz⋅pZ(z)(3) p X ( x ) ∣ d z d x ∣ ⋅ p Z ( z ) (4) p_X(x) \mid\dfrac{dz}{dx}\mid \cdot p_Z(z) \tag{4} pX(x)∣dxdz∣⋅pZ(z)(4) 注意我们应用绝对值来保持相等因为根据概率公理 p X p_X pX和 p Z p_Z pZ永远都是正的。 p X ( x ) ∣ d f ( x ) d x ∣ ⋅ p Z ( f ( x ) ) (5) p_X(x) \mid\dfrac{df(x)}{dx}\mid \cdot p_Z(f(x)) \tag{5} pX(x)∣dxdf(x)∣⋅pZ(f(x))(5) p X ( x ) ∣ d e t ( d f d x ) ∣ ⋅ p Z ( f ( x ) ) (6) p_X(x) \mid det(\dfrac{df}{dx}) \mid \cdot p_Z(f(x)) \tag{6} pX(x)∣det(dxdf)∣⋅pZ(f(x))(6) 注意我们使用行列式来推广到多元情况( d 1 d1 d1) log ( p X ( x ) ) log ( ∣ d e t ( d f d x ) ∣ ) log ( p Z ( f ( x ) ) ) (7) \log(p_X(x)) \log(\mid det(\dfrac{df}{dx}) \mid) \log(p_Z(f(x))) \tag{7} log(pX(x))log(∣det(dxdf)∣)log(pZ(f(x)))(7) 为我们的随机变量建模X我们需要最大化等式7的右侧。 分解方程式 log ( ∣ d e t ( d f d x ) ∣ ) \log(\mid det(\dfrac{df}{dx}) \mid) log(∣det(dxdf)∣) 是拉伸/变化 f f f的量 适用于概率分布 p X p_X pX 此项是雅可比矩阵的对数行列式 d f d x \dfrac{df}{dx} dxdf。我们将雅可比矩阵的行列式称为雅可比行列式。 log ( p Z ( f ( x ) ) ) \log(p_Z(f(x))) log(pZ(f(x))) 限制 f f f 为将 x x x转换到 p Z p_Z pZ.
由于对Z没有任何限制我们可以选择 p Z p_Z pZ, 通常我们选择 p Z p_Z pZ为高斯分布。 单一功能并不能令我满意。我渴望更多。 顺序应用多个函数
我将向您展示如何顺序应用多个函数。 令 z n z_n zn是顺序应用n个函数到 x ∼ p X x \sim p_X x∼pX的结果。 z n f n ∘ ⋯ ∘ f 1 ( x ) (8) z_n f_n \circ \dots \circ f_1(x) \tag{8} znfn∘⋯∘f1(x)(8) f f n ∘ ⋯ ∘ f 1 (9) f f_n \circ \dots \circ f_1 \tag{9} ffn∘⋯∘f1(9) 利用链式法则我们可以用方程8修改方程7得到方程10, 如下。 log ( p X ( x ) ) log ( ∣ d e t ( d f d x ) ∣ ) log ( p Z ( f ( x ) ) ) (7) \log(p_X(x)) \log(\mid det(\dfrac{df}{dx}) \mid) \log(p_Z(f(x))) \tag{7} log(pX(x))log(∣det(dxdf)∣)log(pZ(f(x)))(7) log ( p X ( x ) ) log ( ∏ i 1 n ∣ d e t ( d z i d z i − 1 ) ∣ ) log ( p Z ( f ( x ) ) ) (10) \log(p_X(x)) \log(\prod_{i1}^{n} \mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) \log(p_Z(f(x)))\tag{10} log(pX(x))log(i1∏n∣det(dzi−1dzi)∣)log(pZ(f(x)))(10) 其中为了简洁 x ≜ z 0 x \triangleq z_0 x≜z0 log ( p X ( x ) ) ∑ i 1 n log ( ∣ d e t ( d z i d z i − 1 ) ∣ ) log ( p Z ( f ( x ) ) ) (11) \log(p_X(x)) \sum_{i1}^{n} \log(\mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) \log(p_Z(f(x))) \tag{11} log(pX(x))i1∑nlog(∣det(dzi−1dzi)∣)log(pZ(f(x)))(11) 我们希望雅可比项易于计算因为我们需要计算它n次。
为了有效计算雅可比行列式函数 f i f_i fi(对应 z i z_i zi)被选择为具有下三角雅可比矩阵或上三角雅可比矩阵。由于三角矩阵的行列式是其对角线的乘积因此很容易计算。
现在您已经了解了归一化流的一般理论让我们来浏览一些 PyTorch 代码。
归一化流家族
在这篇文章中我们将重点关注RealNVPDinh 等人2016。
尽管还有许多其他流函数例如 NICE (Dinh et al., 2014)和 GLOW (Kingma Dhariwal, 2018)。对于想要了解更多信息的同学可以参考前面的博文。
RealNVP Flows
我们考虑单个 R-NVP 函数 f : R d → R d f: \mathbb{R}^d \rightarrow \mathbb{R}^d f:Rd→Rd, 其中输入 x ∈ R d \mathbf{x} \in \mathbb{R}^d x∈Rd, 输出 z ∈ R d \mathbf{z} \in \mathbb{R}^d z∈Rd。
快速回顾一下为了优化我们的功能 f f f 以建模我们的数据分布 p X p_X pX, 我们想知道前向传递 f f f以及雅可比行列式 ∣ d e t ( d f d x ) ∣ \mid det(\dfrac{df}{dx}) \mid ∣det(dxdf)∣
然后我们想知道函数的反函数 f − 1 f^{-1} f−1, 所以我们可以转换采样的潜在值 z ∼ p Z z \sim p_Z z∼pZ 到我们的数据分布 p X p_X pX,生成新样本
前向传递 f ( x ) z (12) f(\mathbf{x}) \mathbf{z}\tag{12} f(x)z(12) 前向传递是复制值同时拉伸和移动其他值的组合。首先我们选择一些任意值$ k$ (满足 0 k d 0kd 0kd) 分割我们的输入。 RealNVPs 前向传播如下: z 1 : k x 1 : k (13) \mathbf{z}_{1:k} \mathbf{x}_{1:k} \tag{13} z1:kx1:k(13) z k 1 : d x k 1 : d ⊙ exp ( σ ( x 1 : k ) ) μ ( x 1 : k ) (14) \mathbf{z}_{k1:d} \mathbf{x}_{k1:d} \odot \exp(\sigma(\mathbf{x}_{1:k})) \mu(\mathbf{x}_{1:k})\tag{14} zk1:dxk1:d⊙exp(σ(x1:k))μ(x1:k)(14) 这里 σ , μ : R k → R d − k \sigma, \mu: \mathbb{R}^k \rightarrow \mathbb{R}^{d-k} σ,μ:Rk→Rd−k是任意函数。因此我们会选择σ和μ两者都作为深度神经网络。下面是一个简单实现的 PyTorch 代码。
def forward(self, x):x1, x2 x[:, :self.k], x[:, self.k:] sig self.sig_net(x1)mu self.mu_net(x1)z1 x1z2 x2 * torch.exp(sig) muz torch.cat([z1, z2], dim-1)# log(p_Z(f(x)))log_pz self.p_Z.log_prob(z)#...
view raw对数雅可比行列式
该函数的雅可比行列式 d f d x \dfrac{df}{d\mathbf{x}} dxdf: [ I d 0 d z k 1 : d d x 1 : k diag ( exp [ σ ( x 1 : k ) ] ) ] (15) \begin{bmatrix}I_d 0 \\ \frac{d z_{k1:d}}{d \mathbf{x}_{1:k}} \text{diag}(\exp[\sigma(\mathbf{x}_{1:k})]) \end{bmatrix} \tag{15} [Iddx1:kdzk1:d0diag(exp[σ(x1:k)])](15) 雅可比矩阵的对数行列式将是: log ( det ( d f d x ) ) log ( ∏ i 1 d − k ∣ exp [ σ i ( x 1 : k ) ] ∣ ) (16) \log(\det(\dfrac{df}{d\mathbf{x}})) \log(\prod_{i1}^{d-k} \mid\exp[\sigma_i(\mathbf{x}_{1:k})]\mid) \tag{16} log(det(dxdf))log(i1∏d−k∣exp[σi(x1:k)]∣)(16) log ( ∣ det ( d f d x ) ∣ ) ∑ i 1 d − k log ( exp [ σ i ( x 1 : k ) ] ) (17) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) \sum_{i1}^{d-k} \log(\exp[\sigma_i(\mathbf{x}_{1:k})]) \tag{17} log(∣det(dxdf)∣)i1∑d−klog(exp[σi(x1:k)])(17) log ( ∣ det ( d f d x ) ∣ ) ∑ i 1 d − k σ i ( x 1 : k ) (18) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) \sum_{i1}^{d-k} \sigma_i(\mathbf{x}_{1:k}) \tag{18} log(∣det(dxdf)∣)i1∑d−kσi(x1:k)(18)
# single R-NVP calculation
def forward(x): #...log_jacob sig.sum(-1)#...return z, log_pz, log_jacob# multiple sequential R-NVP calculation
def forward(self, x):log_jacobs []z xfor rvnp in self.rvnps:z, log_pz, log_j rvnp(z)log_jacobs.append(log_j)return z, log_pz, sum(log_jacobs)反向 f − 1 ( z ) x (19) f^{-1}(\mathbf{z}) \mathbf{x}\tag{19} f−1(z)x(19) 与其他流程相比RealNVP 的优势之一是易于反转 F \mathbf{F} F进入 F − 1 \mathbf{F}^{-1} F−1我们使用等式 (14) 的前向传递将其表述如下: x 1 : k z 1 : k (20) \mathbf{x}_{1:k} \mathbf{z}_{1:k} \tag{20} x1:kz1:k(20) x k 1 : d ( z k 1 : d − μ ( x 1 : k ) ) ⊙ exp ( − σ ( x 1 : k ) ) (21) \mathbf{x}_{k1:d} (\mathbf{z}_{k1:d} - \mu(\mathbf{x}_{1:k})) \odot \exp(-\sigma(\mathbf{x}_{1:k})) \tag{21} xk1:d(zk1:d−μ(x1:k))⊙exp(−σ(x1:k))(21) ⇔ x k 1 : d ( z k 1 : d − μ ( z 1 : k ) ) ⊙ exp ( − σ ( z 1 : k ) ) (22) \Leftrightarrow \mathbf{x}_{k1:d} (\mathbf{z}_{k1:d} - \mu(\mathbf{z}_{1:k})) \odot \exp(-\sigma(\mathbf{z}_{1:k})) \tag{22} ⇔xk1:d(zk1:d−μ(z1:k))⊙exp(−σ(z1:k))(22)
def inverse(self, z):z1, z2 z[:, :self.k], z[:, self.k:] sig self.sig_net(z1)mu self.mu_net(z1)x1 z1x2 (z2 - mu) * torch.exp(-sig)x torch.cat([x1, x2], dim-1)return x小结
瞧R-NVP 的配方完成了
总而言之我们现在知道如何计算 F ( X ) F(\mathbf{X}) F(X), log ( ∣ det ( d f d x ) ∣ ) \log(\mid\det(\dfrac{df}{d\mathbf{x}})\mid) log(∣det(dxdf)∣) 以及 f − 1 ( z ) f^{-1}(\mathbf{z}) f−1(z)。
下面是Github中完整的 jupyter 笔记本其中包含用于模型优化和数据生成的 PyTorch 代码。
注意在笔记本中多层 R-NVP 在正向/反向传递之前翻转输入以获得更具表现力的模型。
优化模型 log ( p X ( x ) ) log ( ∣ d e t ( d f d x ) ∣ ) log ( p Z ( f ( x ) ) ) log ( p X ( x ) ) ∑ i 1 n log ( ∣ d e t ( d z i d z i − 1 ) ∣ ) log ( p Z ( f ( x ) ) ) \log(p_X(x)) \log(\mid det(\dfrac{df}{dx}) \mid) \log(p_Z(f(x))) \\ \log(p_X(x)) \sum_{i1}^{n} \log(\mid det(\dfrac{dz_i}{dz_{i-1}}) \mid) \log(p_Z(f(x))) log(pX(x))log(∣det(dxdf)∣)log(pZ(f(x)))log(pX(x))i1∑nlog(∣det(dzi−1dzi)∣)log(pZ(f(x)))
for _ in range(epochs):optim.zero_grad()# forward passX get_batch(data)z, log_pz, log_jacob model(X)# maximize p_X(x) minimize -p_X(x)loss -(log_jacob log_pz).mean()losses.append(loss)# backpropigate lossloss.backward()optim.step()从模型生成数据 z ∼ p Z x g e n f − 1 ( z ) z \sim p_Z \\ x_{gen} f^{-1}(z) z∼pZxgenf−1(z)
# p_Z - gaussian
mu, cov torch.zeros(2), torch.eye(2)
p_Z MultivariateNormal(mu, cov)# sample 3000 points (z ~ p_Z)
z p_Z.rsample(sample_shape(3000,))# invert f^-1(z) x
x_gen model.inverse(z)结论
总之我们学习了如何使用可逆函数将数据分布建模为选定的潜在分布 f f f。我们使用变量变化公式发现为了对数据进行建模我们必须最大化 f f f的雅可比行列式同时也约束 f f f到我们的潜在分布。然后我们将这个概念扩展到顺序应用多个函数 f n ∘ ⋯ ∘ f 0 f_n\circ \cdots \circ f_0 fn∘⋯∘f0。最后我们了解了RealNVP流程的理论和实现。