【深度学习】VAE变分自编码器原理推导+Python代码实现

本文围绕变分自编码器(VAE)展开,先引入高斯混合模型,对比其与VAE的关联。接着阐述VAE原理,指出训练时需约束概率分布以避免过拟合,建立目标函数。然后进行原理推导,包括引入、细化目标函数及重参数化技巧,最后给出代码实现但效果一般。
该文章已生成可运行项目,

1、前言

变分自编码器是近些年较火的一个生成模型,我个人认为其本质上仍然是一个概率图模型,只是在此基础上引入了神经网络。本文将就变分自编码器(VAE)进行简单的原理讲解和数学推导。

论文: Auto-Encoding Variational Bayes

视频:【VAE变分自编码器原理解析-哔哩哔哩】

2、引入

2.1、高斯混合模型

生成模型,可以简单的理解为生成数据 ( 不止,但我们暂且就这么理解它 ) \boxed{(不止,但我们暂且就这么理解它)} (不止,但我们暂且就这么理解它)。假如现在我们有样本数据,而我们发现这些样本符合正态分布且样本具有充分的代表性,因此我们计算出样本的均值和方差,就能得到样本的概率分布。然后从正态分布中抽样,就能得到样本。 这种生成样本的过程就是生成过程 \boxed{\mathbf{这种生成样本的过程就是生成过程}} 这种生成样本的过程就是生成过程

可是,假如我们的数据长这样

在这里插入图片描述

很显然,它的数据是由两个不同的正态分布构成。我们可以计算出这些样本的概率分布。但是一种更为常见的方法就是将其当作是两个正态分布。我们引入一个隐变量z。

假设 z 的取值为 0 , 1 \boxed{\mathbf{假设z的取值为0,1}} 假设z的取值为01,如果z为0,我们就从蓝色的概率分布中抽样;否则为1,则从橙色的概率分布中抽样。这就是生成过程。

但是这个隐变量z是什么?它其实就是隐藏特征 训练数据 x 的抽象出来的特征 \boxed{\mathbf{训练数据x的抽象出来的特征}} 训练数据x的抽象出来的特征,比如,如果x偏小,我们则认为它数据蓝色正太分布,否则为橙色。这个 “偏小” \boxed{“偏小”} 偏小就是特征,我们把它的取值为0,1(0代表偏小,1代表偏大)。

那这种模型我们如何取训练它呢?如何去找出这个z呢? 一种很直观的方法就是重构代价最小 \boxed{\mathbf{一种很直观的方法就是重构代价最小}} 一种很直观的方法就是重构代价最小,我们希望,给一个训练数据x,由x去预测隐变量z,再由隐变量z预测回x,得到的误差最小。比如假如我们是蓝色正态分布,去提取特征z,得到的z再返回来预测x,结果得到的却是橙色的正态分布,这是不可取的。其模型图如下

在这里插入图片描述

这个模型被称为GMM高斯混合模型

2.2、变分自编码器(VAE)

那它和VAE有什么关联呢?其实VAE的模型图跟这个原理差不多。只是有些许改变, 隐变量 z 的维度是连续且高维的,不再是简单的离散分布 \boxed{\mathbf{隐变量z的维度是连续且高维的,不再是简单的离散分布}} 隐变量z的维度是连续且高维的,不再是简单的离散分布,因为假如我们生成的是图片,我们需要提取出来的特征明显是要很多的,传统的GMM无法做到。

在VAE中, q ( z ∣ x ) q(z|x) q(zx) (也就是用样本 x 预测变量 z ) \boxed{(也就是用样本x预测变量z)} (也就是用样本x预测变量z,其服从高斯分布,接下来,我们来看模型图

在这里插入图片描述

也就是将训练样本x给神经网络,让神经网络计算出均值和协方差矩阵 μ , log ⁡ σ 2 \mu,\log \sigma^2 μ,logσ2 取 log ⁡ 的原因是传统的神经网络输出值总是有正有负 \boxed{\mathbf{取\log的原因是传统的神经网络输出值总是有正有负}} log的原因是传统的神经网络输出值总是有正有负。有了这两个值就可以在对应的高斯分布中采样,得到隐变量z。再让z经过神经网络重构回样本,得到新样本。这就是整个VAE的大致过程了。

再次强调 训练过程我们希望每次重构的时候,新样本和训练样本尽可能的相似 \boxed{\mathbf{训练过程我们希望每次重构的时候,新样本和训练样本尽可能的相似}} 训练过程我们希望每次重构的时候,新样本和训练样本尽可能的相似

如果我们这样直接去训练的化,可以吗?可以!但是会有个问题,神经网络会趋向于将协方差变0,而让概率分布 q ( z ∣ x ) q(z|x) q(zx)将不再具备随机性,概率分布空间会坍缩成一个点,每次采样都是均值,这种情况我们俗称过拟合。

为什么协方差会变成0?因为采样具有随机性,也就是存在噪声,噪声是肯定会增加重构的误差的。神经网络为了让误差最小,是肯定让这个随机性越小越好,因为只有这样,才能重构误差最小

但是我们肯定是希望有随机性的,为什么?因为有随机性,我们才可以生成不同的样本啊!

所以,对于概率分布 q ( z ∣ x ) q(z|x) q(zx),我们不希望它的协方差为0,所以我们需要对其进行约束。在论文中,它对其进行约束,要求它尽量的往 N ( 0 , I ) N(0,I) N(0,I)靠近( 其实与先验分布 P ( z ) 有关,后续数学推导中可见 , 假设 P ( z ) ∼ N ( z ∣ 0 , I ) \boxed{其实与先验分布P(z)有关,后续数学推导中可见,假设P(z)\sim N(z|0,I)} 其实与先验分布P(z)有关,后续数学推导中可见,假设P(z)N(z∣0,I)

所以,有KL散度去衡量两个概率分布的相似性
min ⁡ K L ( P ( z ∣ x ) ∣ ∣ P ( z ) ) \min KL\left(P(z|x)||P(z)\right) minKL(P(zx)∣∣P(z))
KL散度是大于等于0的值,越小则证明越相似
K L ( q ( x ) ∣ ∣ p ( x ) ) = ∫ x q ( x ) log ⁡ q ( x ) p ( x ) d x KL(q(x)||p(x))=\int_x q(x)\log\frac{q(x)}{p(x)}dx KL(q(x)∣∣p(x))=xq(x)logp(x)q(x)dx
所以,我们就是两个优化目标
①最小化重构代价 ②最小化上述的 K L 散度 \boxed{\mathbf{①最小化重构代价}}\\ \boxed{\mathbf{②最小化上述的KL散度}} 最小化重构代价最小化上述的KL散度
依照这两个条件,建立目标函数,直接梯度下降 ( 其实还需要重参数化,后面会讲到 ) \boxed{\mathbf{(其实还需要重参数化,后面会讲到)}} (其实还需要重参数化,后面会讲到),刷刷刷地往下降,最终收敛。

下面,我们就对其进行简单的数学推导,并以此推导出目标函数

3、原理推导

3.1、引入目标函数

以VAE的简略图为例

在这里插入图片描述

设我们有N个样本
X = ( x 1 , x 2 , ⋯   , x N ) X=\begin{pmatrix}x^1,x^2,\cdots,x^N\end{pmatrix} X=(x1,x2,,xN)
定义隐变量先验分布 P ( z ) ∼ N ( 0 , I ) P(z) \sim N(0,I) P(z)N(0,I)。很自然的想法,我们直接对x求log极大似然,假设我们有N的样本,记作X。设所需求解的参数为 θ \theta θ,似然函数记为 P θ ( ∣ x ) P_\theta(|x) Pθ(x),为了简便,以下省略 θ \theta θ,第 i i i个样本记为 x i x^{i} xi,某个样本的第 j j j个维度记作 x j x_j xj

log ⁡ P ( X ) = log ⁡ P ( x 1 ) P ( x 2 ) ⋯ P ( x N ) = log ⁡ ∏ i = 1 N P ( x i ) = ∑ i = 1 N log ⁡ P ( x i ) \begin{aligned}\log P(X)=&\log P(x^1)P(x^2)\cdots P(x^N)\\=&\log\prod\limits_{i=1}^N P(x^i)\\=&\sum\limits_{i=1}^N\log P(x^i)\end{aligned} logP(X)===logP(x1)P(x2)P(xN)logi=1NP(xi)i=1NlogP(xi)
现在,我们先单独看看里面某一个样本的似然,某个样本记为 x x x
log ⁡ P ( x ) = log ⁡ P ( x , z ) P ( z ∣ x ) = log ⁡ P ( x , z ) − log ⁡ P ( z ∣ x ) \begin{aligned}\log P(x)=&\log\frac{P(x,z)}{P(z|x)}\\=&\log P(x,z) -\log P(z|x)\end{aligned} logP(x)==logP(zx)P(x,z)logP(x,z)logP(zx)
引入一个 q ϕ ( z ∣ x ) q_\phi(z|x) qϕ(zx)分布, ϕ \phi ϕ是它的参数,为了简便,后续省略掉 ϕ \phi ϕ,直接记为 q ( z ∣ x ) q(z|x) q(zx)

log ⁡ P ( x ) \log P(x) logP(x)等式左右分别对 q ( z ∣ x ) q(z|x) q(zx)求积分
左边: ∫ z log ⁡ P ( x ) q ( z ∣ x ) d z = log ⁡ P ( x ) ∫ z q ( z ∣ x ) d z = log ⁡ P ( x ) \begin{aligned}&\mathbf{左边:}\int_z \log P(x)q(z|x)dz=\log P(x)\int_z q(z|x)dz=\log P(x) \\\end{aligned} 左边:zlogP(x)q(zx)dz=logP(x)zq(zx)dz=logP(x)
所以左边等于右边
log ⁡ P ( x ) = ∫ z ( log ⁡ P ( x , z ) − log ⁡ P ( z ∣ x ) ) q ( z ∣ x ) d z = ∫ z ( log ⁡ P ( x , z ) q ( z ∣ x ) − log ⁡ P ( z ∣ x ) q ( z ∣ x ) ) q ( z ∣ x ) d z = ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z − ∫ z log ⁡ P ( z ∣ x ) q ( z ∣ x ) q ( z ∣ x ) d z = ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z ⏟ ① + K L ( q ( z ∣ x ) ∣ ∣ P ( z ∣ x ) ) ⏟ ② \begin{align}\log P(x)=&\int_z (\log P(x,z)-\log P(z|x))q(z|x)dz\tag{a}\\=&\int_z (\log \frac{P(x,z)}{q(z|x)}-\log \frac{P(z|x)}{q(z|x)})q(z|x)dz\tag{b}\\=&\int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz-\int_z\log\frac{P(z|x)}{q(z|x)}q(z|x)dz\nonumber\\=&\underbrace{\int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz}_{①}+\underbrace{KL(q(z|x)||P(z|x))}_{②}\nonumber\end{align} logP(x)====z(logP(x,z)logP(zx))q(zx)dzz(logq(zx)P(x,z)logq(zx)P(zx))q(zx)dzzlogq(zx)P(x,z)q(zx)dzzlogq(zx)P(zx)q(zx)dz zlogq(zx)P(x,z)q(zx)dz+ KL(q(zx)∣∣P(zx))(a)(b)
(式a)到(式b)用到了 log ⁡ \log log的性质。

那么,现在,我们开始极大似然,似然函数的参数为 θ \theta θ
max ⁡ θ log ⁡ P ( x ) = max ⁡ θ ( ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z ⏟ ① + K L ( q ( z ∣ x ) ∣ ∣ P ( z ∣ x ) ) ⏟ ② ) \max\limits_{\theta}\log P(x)=\max\limits_{\theta}\left(\underbrace{\int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz}_{①}+\underbrace{KL(q(z|x)||P(z|x))}_{②}\right) θmaxlogP(x)=θmax zlogq(zx)P(x,z)q(zx)dz+ KL(q(zx)∣∣P(zx))
因为 P ( z ∣ x ) P(z|x) P(zx)我们算不出来(原因请看,分母的积分计算不了)
P ( z ∣ x ) = P ( z , x ) P ( x ) = P ( x ∣ z ) P ( z ) ∫ P ( x ∣ z ) P ( z ) d z P(z|x)=\frac{P(z,x)}{P(x)}=\frac{P(x|z)P(z)}{\int P(x|z)P(z)dz} P(zx)=P(x)P(z,x)=P(xz)P(z)dzP(xz)P(z)
故而,使用 q ( z ∣ x ) q(z|x) q(zx)去逼近,所以,更新q的参数 ϕ \phi ϕ,以最小化第②项。
min ⁡ ϕ K L ( q ( z ∣ x ) ∣ ∣ P ( z ∣ x ) ) \min\limits_{\phi} KL(q(z|x)||P(z|x)) ϕminKL(q(zx)∣∣P(zx))
在给定x跟 θ \theta θ的情况下, log ⁡ P ( x ) \log P(x) logP(x)的值是确定的,所以最小化第②项,就等于最大化第①项
max ⁡ ϕ ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z ↔ min ⁡ ϕ K L ( q ( z ∣ x ) ∣ ∣ P ( z ∣ x ) ) \max\limits_{\phi} \int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz \leftrightarrow\min\limits_{\phi} KL(q(z|x)||P(z|x)) ϕmaxzlogq(zx)P(x,z)q(zx)dzϕminKL(q(zx)∣∣P(zx))
举个例子,在VAE中,里面的参数 θ , ϕ \theta,\phi θ,ϕ,其实都是用神经网络去逼近的。所以,如果按照刚刚提到的,步骤就长这样
步骤①:固定 θ 参数,利用梯度下降 , 更新参数 ϕ , 以最小化② 步骤②:固定 ϕ 参数,利用梯度下降 , 更新参数 θ , 以最大化① \mathbf{步骤①:固定\theta参数,利用梯度下降,更新参数\phi,以最小化②}\\\mathbf{步骤②:固定\phi参数,利用梯度下降,更新参数\theta,以最大化①} 步骤:固定θ参数,利用梯度下降,更新参数ϕ,以最小化步骤:固定ϕ参数,利用梯度下降,更新参数θ,以最大化

按照上面提到的,我们可以把第一步改成
步骤①:固定 θ 参数,利用梯度下降 , 更新参数 ϕ , 以最大化① \mathbf{步骤①:固定\theta参数,利用梯度下降,更新参数\phi,以最大化①} 步骤:固定θ参数,利用梯度下降,更新参数ϕ,以最大化
更一般地,我们把它们写成一起
max ⁡ θ , ϕ ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z \max\limits_{\theta,\phi} \int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz θ,ϕmaxzlogq(zx)P(x,z)q(zx)dz
由于KL散度是大于等于0的,所以第①项,就被称为变分下界。
log ⁡ P ( x ) ≥ ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z \log P(x)\ge\int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz logP(x)zlogq(zx)P(x,z)q(zx)dz

好,现在我们只需要最大化其变分下界(以下省略掉参数)
max ⁡ ∫ z log ⁡ P ( x , z ) q ( z ∣ x ) q ( z ∣ x ) d z = max ⁡ ∫ z log ⁡ P ( x ∣ z ) P ( z ) q ( z ∣ x ) q ( z ∣ x ) d z = max ⁡ ∫ z ( log ⁡ P ( z ) q ( z ∣ x ) + log ⁡ P ( x ∣ z ) ) q ( z ∣ x ) d z = max ⁡ ∫ z log ⁡ P ( x ∣ z ) q ( z ∣ x ) d z − ∫ log ⁡ q ( z ∣ x ) P ( z ) q ( z ∣ x ) d z = max ⁡ ( E z ∼ q ( z ∣ x ) [ log ⁡ P ( x ∣ z ) ] ⏟ ① − K L ( q ( z ∣ x ) ∣ ∣ P ( z ) ) ⏟ ② ) \begin{aligned}&\max \int_{z}\log\frac{P(x,z)}{q(z|x)}q(z|x)dz\\=&\max \int_z\log \frac{P(x|z)P(z)}{q(z|x)}q(z|x)dz\\=&\max \int_z \left(\log \frac{P(z)}{q(z|x)}+\log P(x|z)\right)q(z|x)dz\\=&\max \int_z\log P(x|z)q(z|x)dz-\int \log \frac{q(z|x)}{P(z)}q(z|x)dz\\=&\max \left(\underbrace{\mathbb{E}_{z\sim q(z|x)}\left[\log P(x|z)\right]}_{①} -\underbrace{KL(q(z|x)||P(z))}_{②}\right)\end{aligned} ====maxzlogq(zx)P(x,z)q(zx)dzmaxzlogq(zx)P(xz)P(z)q(zx)dzmaxz(logq(zx)P(z)+logP(xz))q(zx)dzmaxzlogP(xz)q(zx)dzlogP(z)q(zx)q(zx)dzmax( Ezq(zx)[logP(xz)] KL(q(zx)∣∣P(z)))

发现了吗,最大化里面的第一项就期望,不就是从 q ( z ∣ x ) q(z|x) q(zx)采样z,再让 log ⁡ P ( x ∣ z ) \log P(x|z) logP(xz)概率最大。这不就是重构代价最小吗;而对于第二项,最大化 − K L -KL KL散度,就相当于最小化 K L KL KL散度。这和我们上面提到的两个优化目标是一样的。

3.2、细化目标函数

既然得到了目标函数,那么我们就对 log ⁡ P ( x ∣ z ) \log P(x|z) logP(xz)似然和KL散度都求出具体的表达。

先来看 K L 散度 \boxed{先来看KL散度} 先来看KL散度

q ( z j ∣ x ) ∼ N ( μ ϕ , σ ϕ 2 ) P ( z j ) ∼ N ( 0 , 1 ) q(z_j|x)\sim N(\mu_\phi,\sigma_\phi^2)\\P(z_j)\sim N(0,1) q(zjx)N(μϕ,σϕ2)P(zj)N(0,1)
q ( z ∣ x ) q(z|x) q(zx)需要逼近 P ( z ) P(z) P(z),而 P ( z ) ∼ N ( 0 , I ) P(z) \sim N(0,I) P(z)N(0,I)的多维高斯分布,并且各个维度之间相互独立,所以 q ( z ∣ x ) q(z|x) q(zx)也是如此设定,

那么最小化其KL散度,只需要对每一个维度求KL最小即可,单独看某一个维度,设某一个维度为 z j z_j zj,设 q ( z j ∣ x ) ∼ N ( μ ϕ , σ ϕ 2 ) q(z_j|x)\sim N(\mu_{\phi},\sigma^2_\phi) q(zjx)N(μϕ,σϕ2)(后续为了简便,也同样将 ϕ \phi ϕ隐去)
min ⁡ K L ( q ( z j ∣ x ) ∣ ∣ P ( z j ) ) = min ⁡ ∫ q ( z j ∣ x ) log ⁡ q ( z j ∣ x ) P ( z j ) d z j = min ⁡ ∫ q ( z j ∣ x ) log ⁡ N ( μ , σ 2 ) N ( 0 , 1 ) d z j = min ⁡ ∫ q ( z j ∣ x ) log ⁡ 1 2 π σ exp ⁡ { − ( z j − μ ) 2 2 σ 2 } 1 2 π exp ⁡ { − z j 2 2 } d z j = min ⁡ ∫ q ( z j ∣ x ) log ⁡ 1 σ exp ⁡ { − ( z j − μ ) 2 2 σ 2 } exp ⁡ { − z j 2 2 } d z j = min ⁡ ∫ q ( z j ∣ x ) ( log ⁡ 1 σ + log ⁡ exp ⁡ { − ( z j − μ ) 2 2 σ 2 } exp ⁡ { − z j 2 2 } ) d z j = min ⁡ ∫ q ( z j ∣ x ) ( log ⁡ 1 σ + log ⁡ exp ⁡ { − ( z j − μ ) 2 2 σ 2 + z j 2 2 } ) d z j = min ⁡ ∫ q ( z j ∣ x ) ( log ⁡ 1 σ − ( z j − μ ) 2 2 σ 2 + z j 2 2 ) d z j = min ⁡ ∫ q ( z j ∣ x ) 1 2 ( 2 log ⁡ 1 σ − ( z j − μ ) 2 σ 2 + z j 2 ) d z j = min ⁡ 1 2 ∫ q ( z j ∣ x ) ( z j 2 − log ⁡ σ 2 − ( z j − μ ) 2 σ 2 ) d z j \begin{aligned}&\min KL(q(z_j|x)||P(z_j))\\=&\min \int q(z_j|x) \log\frac{q(z_j|x)}{P(z_j)}dz_j\\=&\min \int q(z_j|x)\log \frac{N(\mu,\sigma^2)}{N(0,1)}dz_j\\=&\min \int q(z_j|x) \log \frac{\frac{1}{\sqrt{2\pi}\sigma}\exp\{-\frac{(z_j-\mu)^2}{2\sigma^2}\}}{\frac{1}{\sqrt{2\pi}}\exp \{-\frac{z_j^2}{2}\}}dz_j\\=&\min \int q(z_j|x) \log \frac{\frac{1}{\sigma}\exp\{-\frac{(z_j-\mu)^2}{2\sigma^2}\}}{\exp \{-\frac{z_j^2}{2}\}}dz_j\\=&\min \int q(z_j|x) \left(\log \frac{1}{\sigma}+\log\frac{\exp\{-\frac{(z_j-\mu)^2}{2\sigma^2}\}}{\exp \{-\frac{z_j^2}{2}\}}\right)dz_j\\=&\min \int q(z_j|x) \left(\log \frac{1}{\sigma}+\log\exp\{-\frac{(z_j-\mu)^2}{2\sigma^2}+\frac{z_j^2}{2}\}\right)dz_j\\=&\min \int q(z_j|x) \left(\log \frac{1}{\sigma}-\frac{(z_j-\mu)^2}{2\sigma^2}+\frac{z_j^2}{2}\right)dz_j\\=&\min \int q(z_j|x) \frac{1}{2}\left(2\log \frac{1}{\sigma}-\frac{(z_j-\mu)^2}{\sigma^2}+z_j^2\right)dz_j\\=&\min \frac{1}{2}\int q(z_j|x)\left(z_j^2-\log \sigma^2-\frac{(z_j-\mu)^2}{\sigma^2}\right)dz_j\end{aligned} =========minKL(q(zjx)∣∣P(zj))minq(zjx)logP(zj)q(zjx)dzjminq(zjx)logN(0,1)N(μ,σ2)dzjminq(zjx)log2π 1exp{2zj2}2π σ1exp{2σ2(zjμ)2}dzjminq(zjx)logexp{2zj2}σ1exp{2σ2(zjμ)2}dzjminq(zjx) logσ1+logexp{2zj2}exp{2σ2(zjμ)2} dzjminq(zjx)(logσ1+logexp{2σ2(zjμ)2+2zj2})dzjminq(zjx)(logσ12σ2(zjμ)2+2zj2)dzjminq(zjx)21(2logσ1σ2(zjμ)2+zj2)dzjmin21q(zjx)(zj2logσ2σ2(zjμ)2)dzj
可以分为三部分
min ⁡ K L ( q ( z j ∣ x ) ∣ ∣ P ( z j ) ) = min ⁡ 1 2 ( ∫ q ( z j ∣ x ) z j 2 d z j − ∫ q ( z j ∣ x ) log ⁡ σ 2 d z j − ∫ z q ( z j ∣ x ) ( z j − μ ) 2 σ 2 d z j ) \min KL(q(z_j|x)||P(z_j))=\min\frac{1}{2}\left( \int q(z_j|x)z_j^2 dz_j -\int q(z_j|x)\log \sigma^2 dz_j-\int_z q(z_j|x)\frac{(z_j-\mu)^2}{\sigma^2}dz_j\right) minKL(q(zjx)∣∣P(zj))=min21(q(zjx)zj2dzjq(zjx)logσ2dzjzq(zjx)σ2(zjμ)2dzj)

①: ∫ z q ( z j ∣ x ) z j 2 d z = E [ z j 2 ] = D ( z j ) + E [ z j ] 2 = σ 2 + μ 2 ②: ∫ z q ( z j ∣ x ) log ⁡ σ 2 d z j = log ⁡ σ 2 ∫ z q ( z j ∣ x ) d z j = log ⁡ σ 2 ③: ∫ z q ( z j ∣ x ) ( z j μ ) 2 σ 2 d z j = 1 σ 2 ∫ z q ( z j ∣ x ) ( z j μ ) 2 d z j = 1 σ 2 E [ ( z j − μ ) 2 ] = 1 \begin{align}①:&\int_z q(z_j|x)z_j^2 dz=\mathbb{E}[z_j^2]=D(z_j)+\mathbb{E}[z_j]^2=\sigma^2+\mu^2\tag{A}\\②:&\int_z q(z_j|x)\log \sigma^2dz_j=\log\sigma^2\int_zq(z_j|x)dz_j=\log \sigma^2\tag{B} \\③:&\int_zq(z_j|x)\frac{(z_j\mu)^2}{\sigma^2}dz_j=\frac{1}{\sigma^2}\int_z q(z_j|x)(z_j\mu)^2dz_j=\frac{1}{\sigma^2}\mathbb{E}[(z_j-\mu)^2]=1\tag{C}\end{align} zq(zjx)zj2dz=E[zj2]=D(zj)+E[zj]2=σ2+μ2zq(zjx)logσ2dzj=logσ2zq(zjx)dzj=logσ2zq(zjx)σ2(zjμ)2dzj=σ21zq(zjx)(zjμ)2dzj=σ21E[(zjμ)2]=1(A)(B)(C)
对于(式 A ),里面用到了方差的计算公式 D ( z ) = E ( z 2 ) − E ( z ) 2 \boxed{\mathbf{对于(式A),里面用到了方差的计算公式D(z)=E(z^2)-E(z)^2}} 对于(式A),里面用到了方差的计算公式D(z)=E(z2)E(z)2

对于(式 B ) , 是因为 q ( x j ∣ x ) 积分为 1 \boxed{\mathbf{对于(式B),是因为q(x_j|x)积分为1}} 对于(式B,是因为q(xj∣x)积分为1

对于(式 C ) \boxed{\mathbf{对于(式C)}} 对于(式C
1 σ 2 E [ ( z j − μ ) 2 ] = 1 σ 2 E [ z j 2 − 2 μ z j + μ 2 ] = 1 σ 2 ( E ( z j 2 ) − 2 μ E ( z j ) + μ 2 ) = 1 σ 2 ( σ 2 + μ 2 − 2 μ 2 + μ 2 ) = 1 \begin{aligned}&\frac{1}{\sigma^2}\mathbb{E}[(z_j-\mu)^2]\\\\=&\frac{1}{\sigma^2}\mathbb{E}[z_j^2-2\mu z_j +\mu^2]\\=&\frac{1}{\sigma^2}\left(\mathbb{E}(z_j^2)-2\mu\mathbb{E}(z_j)+\mu^2\right)\\=&\frac{1}{\sigma^2}\left(\sigma^2+\mu^2-2\mu^2+\mu^2\right)\\=&1\end{aligned} ====σ21E[(zjμ)2]σ21E[zj22μzj+μ2]σ21(E(zj2)2μE(zj)+μ2)σ21(σ2+μ22μ2+μ2)1
如果你熟悉高斯分布的高阶矩的话,式A和式C完全就是二阶原点矩和中心距,是直接可以的得出答案的。

所以对于所有维度的 K L 散度 , 有 ( 假设隐变量有 J 维 ) \boxed{\mathbf{所以对于所有维度的KL散度,有(假设隐变量有J维)}} 所以对于所有维度的KL散度,(假设隐变量有J)
min ⁡ 1 2 ∑ j = 1 J ( σ j 2 + μ j 2 − log ⁡ σ j 2 − 1 ) \min \frac{1}{2}\sum\limits_{j=1}^J(\sigma^2_j+\mu^2_j-\log \sigma^2_j -1 ) min21j=1J(σj2+μj2logσj21)

再来看 log ⁡ P ( x ∣ z ) 极大似然,即 max ⁡ E q ( z ∣ x ) [ log ⁡ P ( x ∣ z ) ] \boxed{\mathbf{再来看\log P(x|z)极大似然,即\max \mathbb{E}_{q(z|x)}[\log P(x|z)]}} 再来看logP(x∣z)极大似然,即maxEq(z∣x)[logP(x∣z)]

值得注意的是,我看很多文章中都说此处就直接采用均方差来计算。这种说法是不准确的,在论文中提到 P ( x ∣ z ) P(x|z) P(xz)是服从一个概率分布的,而不是无端的就计算其差值。它不像是GAN一样,对于其隐藏在内部的概率分布不作约束,VAE是仍然对 P ( x ∣ z ) P(x|z) P(xz)进行约束。

在这里插入图片描述

“ log ⁡ p θ ( x ( i ) ∣ z ( i , l ) ) 是伯努利或高斯 M L P ,这取决于我们建模的数据类型” \boxed{“\log p_θ (x^{(i)} |z^{(i,l)} )是伯努利或高斯MLP,这取决于我们建模的数据类型”} logpθ(x(i)z(i,l))是伯努利或高斯MLP,这取决于我们建模的数据类型

当然了,其实我们也可以不对其概率分布进行约束,归根究底,其让然是最小重构代价,那么我们的目标函数如果可以充分表达出“最小重构代价”,那么是什么又有何关系呢?

在论文中,其假设 P ( x ∣ z ) ∼ N ( μ , σ 2 I ) P(x|z) \sim N(\mu,\sigma^2 I) P(xz)N(μ,σ2I),其中 μ \mu μ σ 2 \sigma^2 σ2都是需要使用神经网络去逼近。

但是,一般地,我们假设 P ( x ∣ z ) ∼ ( f ( z ) , c I ) P(x|z) \sim (f(z),cI) P(xz)(f(z),cI),也就是其均值用神经网络去逼近,对于其协方差矩阵,我们设定为常数c和 I I I相乘,所以依然是各个维度之间相互独立。我们来看看它的极大似然估计得什么(假设采样n个样本)

max ⁡ E q ( z ∣ x ) [ log ⁡ P ( x ∣ z ) ] ≈ max ⁡ 1 n ∑ i = 1 n log ⁡ P ( x ∣ z i ) = max ⁡ 1 n ∑ i = 1 n log ⁡ 1 2 π D / 2 ∣ c I ∣ 1 / 2 exp ⁡ { − 1 2 ( x − f ( z i ) ) T ( c I ) − 1 ( x − f ( z i ) ) } = max ⁡ 1 n ∑ i = 1 n log ⁡ 1 2 π D / 2 ∣ c I ∣ 1 / 2 − 1 2 ( x − f ( z i ) ) T ( c I ) − 1 ( x − f ( z i ) ) ∝ min ⁡ 1 n ∑ i = 1 n ( x − f ( z i ) ) T ( x − f ( z i ) ) = min ⁡ 1 n ∑ i = 1 n ∣ ∣ x − f ( z i ) ∣ ∣ 2 \begin{aligned}\max \mathbb{E}_{q(z|x)}[\log P(x|z)]\approx&\max\frac{1}{n}\sum\limits_{i=1}^n\log P(x|z^i)\\=&\max\frac{1}{n}\sum\limits_{i=1}^n\log \frac{1}{{2\pi }^{D/2}|cI|^{1/2}}\exp\left\{-\frac{1}{2}(x-f(z^i))^T(cI)^{-1}(x-f(z^i))\right\}\\=&\max\frac{1}{n}\sum\limits_{i=1}^n\log \frac{1}{{2\pi }^{D/2}|cI|^{1/2}}-\frac{1}{2}(x-f(z^i))^T(cI)^{-1}(x-f(z^i))\\\propto &\min \frac{1}{n}\sum\limits_{i=1}^n(x-f(z^i))^T(x-f(z^i))\\=&\min \frac{1}{n}\sum\limits_{i=1}^n||x-f(z^i)||^2\end{aligned} maxEq(zx)[logP(xz)]===maxn1i=1nlogP(xzi)maxn1i=1nlog2πD/2cI1/21exp{21(xf(zi))T(cI)1(xf(zi))}maxn1i=1nlog2πD/2cI1/2121(xf(zi))T(cI)1(xf(zi))minn1i=1n(xf(zi))T(xf(zi))minn1i=1n∣∣xf(zi)2
可以看到,这就是一个均方差

综合得到最终目标函数表达式 \boxed{\mathbf{综合得到最终目标函数表达式}} 综合得到最终目标函数表达式
min ⁡ ( 1 2 ∑ j = 1 J ( σ j 2 + μ j 2 − log ⁡ σ j 2 − 1 ) + 1 n ∑ i = 1 n ∣ ∣ x − f ( z i ) ∣ ∣ 2 ) \min \left(\frac{1}{2}\sum\limits_{j=1}^J(\sigma^2_j+\mu^2_j-\log \sigma^2_j -1 )+\frac{1}{n}\sum\limits_{i=1}^n||x-f(z^i)||^2\right) min(21j=1J(σj2+μj2logσj21)+n1i=1n∣∣xf(zi)2)

3.3、重参数化技巧

有了目标函数,理论上我们直接梯度下降就可以了。然而,别忘了,我们是从 q ( z ∣ x ) q(z|x) q(zx)中采样出z来。可是我们却是用的神经网络去计算的均值和方差,得到的高斯分布再去采样,这种情况是不可导的。中间都已经出现了一个断层了。神经网络是一层套一层的计算。而采样计算了一层之后,从这一层中去采样新的值,再计算下一层。因此,采样本身是不可导的。

所以要引入重参数化技巧,假定 q ( z ∣ x ) ∼ N ( μ , σ 2 ) q(z|x) \sim N(\mu,\sigma^2) q(zx)N(μ,σ2)。那么可以构造一个概率分布 p ( ϵ ) ∼ N ( 0 , 1 ) p(\epsilon) \sim N(0,1) p(ϵ)N(0,1)。有
z = μ + ϵ σ z=\mu +\epsilon\sigma z=μ+ϵσ
我们从 P ( ϵ ) P(\epsilon) P(ϵ)采样,然后利用上述公式,就相当于得到了从 q ( z ∣ x ) q(z|x) q(zx)采样的采样值。

证明 \boxed{\mathbf{证明}} 证明
E ( z ) = E ( μ ) + E ( ϵ ) σ = μ V a r ( z ) = E [ ( z − μ ) 2 ] = E [ ( ϵ σ ) 2 ] = σ 2 \begin{aligned}\mathbb{E}(z)=&\mathbb{E}(\mu)+\mathbb{E}(\epsilon)\sigma=\mu\\Var(z)=&\mathbb{E}[(z-\mu)^2]=\mathbb{E}[(\epsilon\sigma)^2]=\sigma^2\end{aligned} E(z)=Var(z)=E(μ)+E(ϵ)σ=μE[(zμ)2]=E[(ϵσ)2]=σ2

4、代码实现

在这里插入图片描述

效果一般,不晓得论文里面用了什么手段,效果看起来比这个好。(这个结果甚至还是我加了一层隐藏层的)

import torch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import transforms
from  torch import nn
from tqdm import tqdm
import matplotlib.pyplot as plt
class VAE(nn.Module):
    def __init__(self,input_dim,hidden_dim,gaussian_dim):
        super().__init__()
        #编码器
        #隐藏层
        self.fc1=nn.Sequential(
            nn.Linear(in_features=input_dim,out_features=hidden_dim),
            nn.Tanh(),
            nn.Linear(in_features=hidden_dim, out_features=256),
            nn.Tanh(),
        )
        #μ和logσ^2
        self.mu=nn.Linear(in_features=256,out_features=gaussian_dim)
        self.log_sigma=nn.Linear(in_features=256,out_features=gaussian_dim)



        #解码(重构)
        self.fc2=nn.Sequential(
            nn.Linear(in_features=gaussian_dim,out_features=256),
            nn.Tanh(),
            nn.Linear(in_features=256, out_features=512),
            nn.Tanh(),
            nn.Linear(in_features=512,out_features=input_dim),
            nn.Sigmoid() #图片被转为为0,1的值了,故用此函数
        )
    def forward(self,x):
        #隐藏层
        h=self.fc1(x)

        #计算期望和log方差
        mu=self.mu(h)
        log_sigma=self.log_sigma(h)

        #重参数化
        h_sample=self.reparameterization(mu,log_sigma)

        #重构
        reconsitution=self.fc2(h_sample)

        return reconsitution,mu,log_sigma

    def reparameterization(self,mu,log_sigma):
        #重参数化
        sigma=torch.exp(log_sigma*0.5) #计算σ
        e=torch.randn_like(input=sigma,device=device)

        result=mu+e*sigma #依据重参数化技巧可得

        return result
    def predict(self,new_x): #预测
        reconsitution=self.fc2(new_x)

        return reconsitution
def train():

    transformer = transforms.Compose([
        transforms.ToTensor(),
    ]) #归一化
    data = MNIST("./data", transform=transformer,download=True) #载入数据

    dataloader = DataLoader(data, batch_size=128, shuffle=True) #写入加载器

    model = VAE(784, 512, 20).to(device) #初始化模型

    optimer = torch.optim.Adam(model.parameters(), lr=1e-3) #初始化优化器

    loss_fn = nn.MSELoss(reduction="sum") #均方差损失
    epochs = 100 #训练100轮

    for epoch in torch.arange(epochs):
        all_loss = 0
        dataloader_len = len(dataloader.dataset)

        for data in tqdm(dataloader, desc="第{}轮梯度下降".format(epoch)):
            sample, label = data
            sample = sample.to(device)
            sample = sample.reshape(-1, 784) #重塑
            result, mu, log_sigma = model(sample) #预测

            loss_likelihood = loss_fn(sample, result) #计算似然损失

            #计算KL损失
            loss_KL = torch.pow(mu, 2) + torch.exp(log_sigma) - log_sigma - 1

            #总损失
            loss = loss_likelihood + 0.5 * torch.sum(loss_KL)

            #梯度归0并反向传播和更新
            optimer.zero_grad()

            loss.backward()

            optimer.step()
            with torch.no_grad():
                all_loss += loss.item()
        print("函数损失为:{}".format(all_loss / dataloader_len))
        torch.save(model, "./model/VAE.pth")
if __name__ == '__main__':
    #是否有闲置GPU
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    #训练
    train()

    #载入模型,预测
    model=torch.load("./model/VAE (1).pth",map_location="cpu")
    #预测20个样本
    x=torch.randn(size=(20,20))
    result=model.predict(x).detach().numpy()
    result=result.reshape(-1,28,28)
    #绘图
    for i in range(20):
        plt.subplot(4,5,i+1)
        plt.imshow(result[i])
        plt.gray()
    plt.show()

5、结束

以上,就是VAE的原理和推导过程了。能力有限,过程并不严谨,如有问题,还望指出。阿里嘎多

在这里插入图片描述

本文章已经生成可运行项目
<think>嗯,用户想了解变分自编码器VAE)的工作原理和数学推导。我需要先回忆一下VAE的基础知识,然后结合提供的引用资料来组织回答。 首先,VAE是生成模型,结合了自编码器和概率建模。自编码器有编码器和解码器,但传统自编码器的潜在空间可能是离散的,而VAE引入了概率分布,通常是高斯分布,这样潜在变量可以连续,方便生成新数据。 接下来是数学部分。VAE的损失函数包括重构损失和KL散度。重构损失类似于传统自编码器的重建误差,比如均方误差或交叉熵。而KL散度用于衡量潜在变量的分布与先验分布(通常是标准正态分布)的差异。这部分可能需要详细推导变分下界(ELBO),因为用户提到了数学推导。 根据引用3,传统自编码器使用平方误差作为重建损失,而VAE在此基础上添加了KL散度项。引用1提到VAE属于无监督学习,使用概率建模,所以需要解释如何通过概率模型生成数据。 然后,用户可能想知道VAE的结构,比如编码器输出的是均值和方差,然后通过重参数化技巧采样潜在变量。这部分需要解释为什么需要重参数化,比如为了允许梯度传播。 数学推导部分可能需要从概率模型出发,假设数据由潜在变量z生成,然后通过最大化边缘似然,引入变分推断来近似后验分布。推导ELBO的时候,需要分解log p(x)为重构项和KL散度项。这部分可能需要一步步展开,确保正确性。 另外,用户提供的引用2中有VAE代码结构,可以提到编码器和解码器的构建,损失函数如何结合重构损失和KL散度。比如,编码器输出均值和对数方差,解码器从潜在变量重建输入。 可能的问题点:用户是否熟悉KL散度的计算?是否需要解释KL散度的公式,比如对于两个高斯分布的KL散度如何简化?另外,重参数化技巧的具体步骤,比如从标准正态分布采样,然后乘以方差加上均值。 还要注意使用正确的LaTeX格式,比如变量用$符号包裹,独立公式用$$。例如,潜在变量$z$的分布,ELBO的公式等。 最后,生成的相关问题需要考虑用户可能的后续疑问,比如VAE和GAN的区别,KL散度消失的问题,重参数化的必要性,以及应用场景等。 现在需要组织这些内容,确保结构清晰,分步骤解释VAE原理、数学推导,并附上代码示例。同时,在适当的地方加入引用标记,比如引用1、2、3中的相关内容。</think>### 变分自编码器VAE原理及数学推导 #### 一、核心思想 变分自编码器(Variational Autoencoder, VAE)是一种结合了**自编码器结构**与**概率建模**的生成模型。其核心思想是通过学习数据的潜在分布(即隐含变量$z$的概率分布),实现数据的生成与重建[^1]。与传统自编码器不同,VAE的编码器输出的是潜在变量的**概率分布参数**(如均值和方差),而非固定值,并通过**重参数化技巧**(Reparameterization Trick)实现梯度反向传播[^2]。 --- #### 二、数学推导 ##### 1. 概率建模假设 - **数据生成过程**:假设观测数据$\mathbf{x}$由隐含变量$\mathbf{z}$生成,即$\mathbf{z} \sim p(\mathbf{z})$(先验分布,通常为标准正态分布$\mathcal{N}(0,I)$),$\mathbf{x} \sim p_\theta(\mathbf{x}|\mathbf{z})$(由解码器建模的似然分布)。 - **目标**:最大化观测数据的边缘似然$\log p_\theta(\mathbf{x})$,但直接计算困难,因此引入变分分布$q_\phi(\mathbf{z}|\mathbf{x})$(编码器建模的后验分布)近似真实后验$p_\theta(\mathbf{z}|\mathbf{x})$。 ##### 2. 变分下界(ELBO) 通过变分推断推导**证据下界(ELBO)**: $$ \log p_\theta(\mathbf{x}) \geq \mathbb{E}_{q_\phi(\mathbf{z}|\mathbf{x})} \left[ \log p_\theta(\mathbf{x}|\mathbf{z}) \right] - D_{\text{KL}}\left( q_\phi(\mathbf{z}|\mathbf{x}) \parallel p(\mathbf{z}) \right) $$ - **第一项**:重构损失,衡量解码器重建数据的能力(如均方误差或交叉熵)。 - **第二项**:KL散度,约束$q_\phi(\mathbf{z}|\mathbf{x})$与先验分布$p(\mathbf{z})$的相似性[^3]。 ##### 3. KL散度计算 假设$q_\phi(\mathbf{z}|\mathbf{x}) = \mathcal{N}(\mu, \sigma^2 I)$,$p(\mathbf{z}) = \mathcal{N}(0, I)$,则: $$ D_{\text{KL}} = \frac{1}{2} \sum_{i=1}^d \left( \sigma_i^2 + \mu_i^2 - 1 - \log \sigma_i^2 \right) $$ 其中$d$为潜在空间维度。 --- #### 三、模型结构 1. **编码器**(推断网络): - 输入数据$\mathbf{x}$,输出潜在分布的参数$\mu$和$\log \sigma^2$。 - 代码示例(简化): ```python encoder = Sequential([ Dense(256, activation='relu', input_shape=(784,)), Dense(128, activation='relu'), Dense(2 * latent_dim) # 输出均值和对数方差 ]) ``` 2. **重参数化**: - 采样$\mathbf{z} = \mu + \sigma \odot \epsilon$,其中$\epsilon \sim \mathcal{N}(0, I)$。 3. **解码器**(生成网络): - 输入潜在变量$\mathbf{z}$,输出重建数据$\mathbf{\hat{x}}$。 ```python decoder = Sequential([ Dense(128, activation='relu', input_shape=(latent_dim,)), Dense(256, activation='relu'), Dense(784, activation='sigmoid') # 输出像素概率 ]) ``` --- #### 四、损失函数 VAE总损失为**重构损失 + KL散度**: ```python def vae_loss(x, x_recon): reconstruction_loss = tf.reduce_mean( tf.keras.losses.binary_crossentropy(x, x_recon) ) * 784 # 假设输入为28x28图像 kl_loss = -0.5 * tf.reduce_mean( 1 + log_var - tf.square(mu) - tf.exp(log_var) ) return reconstruction_loss + kl_loss ``` --- #### 五、应用场景 - 生成新数据(如手写数字、图像插值) - 数据降维与特征提取 - 半监督学习中的特征表示 ---
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值