Variational Inference变分推断,在LDA与VAE中都使用到了,这里是视频https://www.youtube.com/watch?v=Dv86zdWjJKQ的观后笔记,视频略长所以只把重要部分做了一个笔记。
变分推断首先做了一系列假设:
数据x可以从隐变量z推算出,\(p(z \mid x)\)是我们想要得到的inference model,也可以叫encoder。\(p(x \mid z)\)是生成模型,也叫decoder。两个model都属于指数分布族exponential family。
存在某种参数化parameterization方法,全局参数\(\nu\)用来描述inference model。
存在一个分布\(q(z \mid \nu)\),使得从inference分布q在参数\(\nu\)的情况下采样得到的熵\(H_q(Z \mid \nu)\) 与data分布p的熵 \(H_p(Z \mid X)\)尽可能接近。
从最直观的公式来看,\(p(z \mid x) = \frac {p(z, x)} {p(x)}\)左边是我们想要得到的东西,但是右边分母的\(p(x)=\int\limits_{z’} p(x \mid z’) p(z’) dz’\) 这个积分太难评估了,所以要想办法绕开。
所以我们假设存在一个归一化的映射f,叫做inference模型,使得,\(f(x, \nu)=q(x\mid \nu) \approx p(z \mid x) \)。其中\(\nu\)是全局参数,不随样本序号i改变而改变,而x与z都是可以带下标i的。
由于我们假设了后验分布的近似\(q(x\mid \nu)\)是指数分布,所以\(\nu\)可以是对应指数分布的关键参数,比如Normal的\(\sigma\),或是beta分布的\(\beta\)。
我们希望最终近似出的结果尽可能准确,采用\(KL(q(z\mid\nu) || p(z \mid x))\)作为评估目标,需要将KL距离最小化。(这熟悉的味道,不就是bottleneck distortion么……只不过从匹配输入与输出的信息变成匹配输入与全局参数\(\nu\)的信息。)
要最小化KL距离但是无法评估\(p(z \mid x)\),这时候就需要计算ELBO了。
\(KL(q(z \mid \nu) || p(z \mid x)) = \mathbb{E}_q[logq(z\mid \nu)] -\mathbb{E}_q[logp(z \mid x)]\)
\(ELBO:=-KL(q(z \mid \nu) || p(z \mid x)) -\mathbb{E}_q[log(p(z \mid x))] +\mathbb{E}_q[log(p(z, x))]\)
\(=\mathbb{E}_q[log(p(z, x))] -\mathbb{E}_q[log(q(z \mid \nu))] \)
注意到\(\mathbb{E}_q [logp(z, x)-logp(z \mid x)] =\mathbb{E}_q[logp(x)]\)
所以\(\mathbb{E}_q[logp(x)]=ELBO+KL(q(z \mid \nu) || p(z \mid x))\)
由于Jensen不等式对于log凸函数\(\mathbb{E}_q[logp(x)] \leq log(\mathbb{E}_q[p(x)])\),右边是最大似然。
所以 \(log(p(x)) \geq ELBO+KL(q(z \mid \nu) || p(z \mid x))\),ELBO是最大似然的下界(KL大于等于0)
使用梯度上升优化ELBO:
\(\nabla_\nu ELBO = \int dz \{ \nabla_\nu [q(z \mid \nu) (logp(x, z) – logq(z \mid \nu ))] \}\)
注意到\(\nabla_\nu q(z \mid \nu)=q(z \mid \nu) \nabla_\nu log q(z \mid \nu)\)
\(\nabla_\nu ELBO = \int dz \{ q(z \mid \nu) \nabla_\nu logq(z \mid \nu) (logp(x, z) – logq(z \mid \nu )) \} + \int dz \{ q(z \mid \nu) \nabla_\nu (logp(x, z) – logq(z \mid \nu )) \}\)
\(=\mathbb{E}_q[\nabla_\nu (q(z \mid \nu) (logp(x, z) – logq(z \mid \nu )))] + \int \nabla_\nu q(z \mid \nu) dz\)
第二项先对z积分得到1,再对$\nu$求导得到0。
所以\(\nabla_\nu ELBO =\mathbb{E}_q[\nabla_\nu (q(z \mid \nu) (logp(x, z) – logq(z \mid \nu )))]\)
\(\mathbb{E}_{q(z, \nu)}\)里的内容是可以采样评估的,使用当前参数\(\nu\)然后在对应的指数分布里多采样几个\(z_i\),最后平均即可。
当然采样得到的ELBO梯度会存在噪音,不过sgd优化过程中噪音对于收敛也是有作用的,其他文章里有论述这里就不细讲了。
有了\(\nu\)就能按照分布公式计算出\(p(z_i \mid \nu)\);有了采样的\(z_i\),就能计算生成模型的\(p(x_i \mid z_i)\),从而得到\(p(x_i, z_i)\)。
计算梯度所需的东西就都能够获取了。
优化ELBO时,除了要对\(\nu\)求导做梯度下降更新外,生成模型\(g_{\theta}(z) = p(x \mid z)\)里的神经网络权重\(\theta\)同样需要求导
\(\nabla_\theta ELBO = \mathbb{E}_{q} \nabla_\theta logp(x_i \mid z_i, \theta)\)
所以我们只需要像EM一样循环更新inference模型的参数\(\nu\)以及生成模型里的权重\(\theta\)就可以对目标ELBO进行梯度上升优化了。
变分法的本质其实很直白,就是首先假设存在一个全局共享的信息,这个信息概括了某一类数据的共性,所有样本的隐变量\(z_i\)都从这段信息(熵)对应的指数分布\(q(z \mid \nu)\)下采样得到,该分布函数可以被inference model使用几个简单的参数\(\nu\)来描述。接下来我们需要找到一个合适的\(\nu\),使得机器在看到\(\nu\)的时候,与看到原始输入x时得到的隐变量内包含的信息尽量相同。
打个比方就是当我看到\(\nu\) = 2眼睛+1鼻子+1嘴巴 这串字符串,x = 人脸图片.jpg 时,我脑中某一堆神经元组成的隐变量里的信息,都代表了一张人脸。
我所要做的,就是调整这串字符串的内容,是“2眼睛+1鼻子+1嘴巴”合适,还是“椭圆形轮廓+顶部一片黑色”的字符串描述更合适。
当然这个比喻不太恰当的地方就是字符串描述毕竟是离散化,而\(\nu\)是连续化的,不过作为信息载体而言本质上并没有太大区别。