read: Blog - 苏剑林 | VAE-2

Table of contents

笔记 for 变分自编码器(二):从贝叶斯观点出发

数值计算 vs 采样计算

数值计算是先给个数列,对里面的每个数求概率p(x⁽ⁱ⁾),再加权求和 ∑ᵢ₌₀ⁿ x⁽ⁱ⁾p(x⁽ⁱ⁾) (x⁽ⁱ⁾-x⁽ⁱ⁻¹⁾); 采样计算是先从分布中采样,求采样点概率的平均,所以不需要再乘样本点出现的概率:E[x]≈1/n⋅∑ᵢ₌₀ⁿ x⁽ⁱ⁾, x⁽ⁱ⁾∼p(x)。

推导VAE 的损失函数

苏神从逼近联合概率 p(x,z) 出发,而不是从逼近z的后验 p(z|x) 出发。 也许是因为沿着 EM 的思路走,就需要对后验 p(z|x) 求近似,所以很多人聚焦于推导 p(z|x)。

因为想求样本集合 x的分布,

但是难以直接描述复杂分布,所以通过引入隐变量把x的分布变成条件分布的叠加,而后可以对隐变量的分布和条件分布做适当简化(比如都假设为正态分布),并且可以用深度学习模型近似求(隐变量)条件分布的参数,即“深度概率图模型”。

假设 x 是由 z 生成的,所以求 p(x) 可以通过把联合分布 p(x,z) 中的 p(z) 积掉求得: p(x) = ∫p(x,z) dz = ∫ p(x|z)p(z) dz

目标是用一个 q(x,z) 逼近 p(x,z),又因为 p(z) 是先验(已知),所以当 q(x,z)≈p(x,z) 时,生成模型 p(x|z) 也就学到了,“一举两得”。

通过最小化 KL 散度逼近:KL( p(x,z) || q(x,z) ) = ∫∫ p(x,z) [ ln (p(x,z)/q(x,z)) ] dz dx,是一个二重积分

把 p(x,z) 写成 pᐢ(x)⋅p(z|x),也就是推断过程,由x的先验推出z:

KL( p(x,z) || q(x,z) ) = ∫∫ pᐢ(x)⋅p(z|x) [ ln ( pᐢ(x)⋅p(z|x) / q(x,z) ) ] dz dx
= ∫ pᐢ(x) [ ∫ p(z|x) ⋅ ln ( pᐢ(x)⋅p(z|x) / q(x,z) ) dz ] dx
= 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln ( pᐢ(x)⋅p(z|x) / q(x,z) ) dz]

可以蒙特卡罗采样近似求这个期望,也就是把每个样本 x⁽ⁱ⁾ 代入上面中括号里的函数(代入概率密度公式可算出概率值),把函数值求均值。

这个期望可以进一步简化,把 ln 拆开: ln ( pᐢ(x)⋅p(z|x) / q(x,z) ) = ln pᐢ(x) + ln (p(z|x)/q(x,z))

𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln ( pᐢ(x)⋅p(z|x) / q(x,z) ) dz ]
= 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln pᐢ(x) dz] + 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln (p(z|x)/q(x,z)) dz]

上面第 1 个期望: 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln pᐢ(x) dz] = 𝔼_pᐢ(x) [ ln pᐢ(x)⋅∫ p(z|x) dz ] = 𝔼_pᐢ(x) [ ln pᐢ(x) ]

这里的 pᐢ(x) 是根据样本 x⁽⁰⁾, x⁽¹⁾,…, x⁽ⁿ⁾ 确定的关于 x 的先验分布,是已知的确定的,所以这一项是一个常数。 所以 KL 散度 = 常数 + 一个期望:

KL( p(x,z) || q(x,z) ) = 常数 + 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln (p(z|x)/q(x,z)) dz]

所以最小化KL散度,对应目标函数 𝓛 就是第2个期望:

𝓛 = KL( p(x,z) || q(x,z) ) - 常数,则𝓛 的下界就是"-常数": -𝔼_pᐢ(x) [ ln pᐢ(x) ], 其中 pᐢ(x) 不一定是概率,在连续情况时,pᐢ(x) 是概率密度函数,它可以大于1 也可以小于1,所以下界不一定是非负的,即 loss 可能是负数。

再把 𝓛 里的 ln 和 q(x,z) 展开:

𝓛 = 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln ( p(z|x) / q(x,z) ) dz]
= 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln ( p(z|x) / (q(x|z)q(z)) dz ]
= 𝔼_pᐢ(x) [ ∫ p(z|x) ⋅ ln ( p(z|x)/q(z) ) dz - ∫ p(z|x) ⋅ ln q(x|z) dz]

把里面的积分写成期望:

𝓛 = 𝔼_pᐢ(x) [ KL( p(z|x)||q(z) ) + 𝔼_p(z|x) [ -ln q(x|z) ] ]

括号里的就是 VAE 的损失函数:KL散度(正则化项)+ x的后验按照 z 的后验求期望 shuhuai008-30VAE

不能把括号里面的两项分开看或分开最小化。 如果只令 KL( p(z|x)||q(z) )=0,即每个后验都是标准正态分布,与x无关,导致生成的 x 不准,概率 q(x|z) 会很小,-ln q(x|z) 就会很大。 而如果 -ln q(x|z) 很小,即x后验概率 q(x|z) 大,后验分布 p(z|x) 的峰肯定集中在 x 附近,即 p(z|x) 的方差小,与标准正态的差距大,KL( p(z|x)||q(z) ) 不会小。 所以这两部分 loss 是相互拮抗的,𝓛 要以整体来看。 也就是要推断过程与生成过程相互博弈。

算法设计

损失函数中未知的分布包括:z 的先验 q(z),z 的后验 p(z|x),x 的后验 q(x|z) (x 的先验pᐢ(x) 是已知的)

  1. 为了便于采样,假设 z 的先验分布为标准多元正态分布:q(z)=N(0,I)

  2. 用神经网络拟合 z 的后验 p(z|x) 和 x 的后验 q(x|z)。

计算 z 的后验是推断过程,对应 EM 的 E步:近似求得 p(z|x);计算 x 的后验是生成过程,对应 EM 的 M步:把z的近似后验代入似然函数,求极大似然时,对应的模型参数。 (EM中用于逼近 p(z|x) 的神经网络的参数是 ϕ;用于逼近 q(x|z) 的神经网络(也可直接求导)的参数是 θ)

后验分布近似

假设 z 的后验是(各分量独立的)一般正态分布,所以需要神经网络逼近它的期望和方差。期望和方差都由 x 决定,即是 x 的函数 μ_ϕ(x), Σ_ϕ(x)

然后 KL 散度就可以写出来了: 1/2(-logσ² + μ² + σ² -1),已在VAE第一篇推导过。变分自编码器(一):原来是这么一回事

生成模型近似

对于生成模型部分 q(x|z) 的假设,原作者在论文《Auto-Encoding Variational Bayes》中,给出了两种方案:二项分布或正态分布。“既要满足概率的定义(归一化),又要容易算,没多少选择”

二项分布只有一个参数:“抛硬币向上的概率 ρ”。所以对于一个 D 维的样本 x,x 的每一维都是个二值的,所以一个输入样本 x 在 z 成立的情况下,发生的概率就是: q(x|z) = ∏ₖ₌₁ᴰ (ρₖ(z))ˣᵏ (1-ρₖ(z))¹⁻ˣᵏ

此时的 -ln q(x|z) = ∑ₖ₌₁ᴰ [ -xₖ ln ρₖ(z) - (1-xₖ) ln(1-ρₖ(z)) ]

也就是说神经网络的输出 ρ(z) 需要是在 0~1 之间(比如用 sigmoid 激活),然后用交叉熵作为损失函数。

如果假设 q(x|z) 是正态分布,用神经网络估计它的期望 μ_θ(z) 和方差 Σ_θ(z),于是: -ln q(x|z) = ½ || (x-μ_θ(z)) / Σ_θ(z) ||² + D/2 ln 2π + ½∑ₖ₌₁ᴰ lnΣ_θ(z)。

很多时候,训练时方差会固定为一个较小的常数(每次采样都会采到μ),所以神经网络只需估计μ,也就是把 μ 当作生成的 x’,则上式重构误差可简化为: -ln q(x|z) = ½ || (x-μ_θ(z)) / Σ_θ(z) ||²

x –> z –> x'

综上,对于二值数据,假设 q(x|z) 是伯努利分布(二项分布),可以对 decoder (第2个神经网络)的输出用 sigmoid 激活,并用交叉熵作为损失函数; 而对于一般数据,假设 q(x|z) 是正态分布,则使用 mse 作为损失函数。

从后验中采样 z 的技巧

损失函数的第 2 项是:𝔼_p(z|x) [ -ln q(x|z) ],根据蒙特卡罗的思想,这个期望用均值近似:先采样 z,用 z 计算 x 的后验分布 q(x|z),再从中采样 x 计算它出现概率的对数:-ln q(x|z),再求均值:

𝔼_p(z|x) [ -ln q(x|z) ] = -1/n ∑ᵢ₌₁ᴺ ln q(x|zᵢ), zᵢ~p(z|x)

假设了 p(z|x) 是正态分布,它的参数 μ_ϕ, Σ_ϕ 已由神经网络算出,再使用重参数化技巧就能采样出 z 。

但是要采样多少个合适呢?因为每个 z 是专属于 1 个 x,所以只从 p(z|x) 中采一个 z 来计算 x 的分布 q(x|z),再计算 -ln q(x|z),就是loss值。

最终:𝓛 = 𝔼_pᐢ(x) [ KL( p(z|x)||q(z) ) -ln q(x|z) ] , z~p(z|x)

因为每次 epoch 的隐变量都是随机生成的,因此当 epoch 数足够多时,可以保证采样的充分行。苏神试过采样多个的情形,感觉生成的样本没有明显变化。

Built with Hugo
Theme Stack designed by Jimmy