9 Generative Models¶
之前我们讲的都是监督学习 (Supervised Learning),是通过给定数据以及相应的标签进行学习的。相对应的无监督学习 (Unsupervised Learning) 只有数据并没有标签,需要我们根据数据学习到潜在的数据结构
这一讲我们要介绍 生成模型,其与无监督学习的关系如下:
- 生成模型属于无监督学习的子集:大多数生成模型(如自编码器、变分自编码器 VAE、生成对抗网络 GAN、扩散模型等)都是在无监督或自监督的方式下训练的,即它们只使用未标记的数据来学习数据的潜在结构。
- 无监督学习不全是生成模型:一些无监督学习方法(如K均值聚类、主成分分析 PCA)并不生成新的数据样本,而是专注于发现数据的结构或进行降维,因此它们不是生成模型。
9.1 Introduction¶
给定训练数据,生成模型的目标是从相同的数据分布中生成新的样本。
生成模型的目标是学习一个概率分布 \(p_{model}(x)\),使其尽可能接近真实数据的分布 \(p_{data}(x)\)。密度估计是无监督学习中的一个核心问题,即从数据中估计出其潜在的概率分布,而密度估计有两种不同的方法,大致可以分为 显式密度估计(Explicit Density Estimation)和 隐式密度估计(Implicit Density Estimation)
-
显式密度估计是直接定义并求解模型的概率分布 \(p_{model}(x)\)。比如说 PixelRNN/PixelCNN,VAE。优点是可以直接计算和采样,理论清晰。缺点是有时难以精确建模复杂的高维分布
-
隐式密度估计是学习一个模型,让它能够从 \(p_{model}(x)\) 中采样,但不需要明确地定义这个分布。比如说生成对抗网络(GAN)、扩散模型(Diffusion Models)。优点是可以建模非常复杂的分布,生成高质量的样本。
生成模型的应用
-
生成逼真的样本用于艺术创作、超分辨率、着色等。e.g. 通过生成模型,可以从低分辨率图像中生成高分辨率图像,恢复细节,提升图像质量。
-
时间序列数据的生成模型可用于模拟和规划。e.g. 在金融领域,生成模型可以模拟未来的市场走势,帮助投资者做出更明智的决策。
- 训练生成模型还可以推断潜在表示,这些表示可用作通用特征
9.2 PixelRNN/CNN¶
这个生成模型采用的方法是显式密度估计
对于一个图像 \(x\),其像素值可以看作是一个随机变量序列 \((x_1,x_2,...,x_n)\),其中 \(n\) 是像素总数。通过链式法则,我们可以将图像的联合概率分布 \(p(x)\) 分解为各个像素值的条件概率的乘积。
通过最大化训练数据的似然性来训练模型,即找到一组参数,使得训练数据出现的概率最大。
PixelRNN¶
从角落开始生成图片,每一个像素的生成依赖于前面的像素,通过 RNN (LSTM) 进行生成。

但是它有一个缺点就是生成的速度太慢了
PixelCNN¶
同样是从角落开始生成图片,不过这次是通过 CNN 的方式进行生成
计算概率的时候不是需要前面所有像素的信息吗,CNN不是只能看到感受野部分的信息吗?
单层 CNN 只能看到局部区域。但是多层的累计就可以让其看到前面所有像素的信息了,这里我们使用一个技术 Masked Convolutions,设置两种掩码,让其有效地只观察到前面的像素
这个方法的训练速度比 PixelRNN 快,因为我们可以并行地训练每一个像素,但是在生成的时候依然很慢,需要顺序地生成
9.3 Variational Autoencoders (VAE)¶
VAE 引入了一个隐藏层来估计密度方程
但是上面这个估计方式我们并不能直接优化,而是用过优化下界的方式来进行的【这在后面会介绍】
Autoencoders¶
我们通过一些神经网络从一张图片中提取到了一些特征,那么我们是否可以根据这些特征来重构原始图像呢?

在整个过程中我们并没有用到原始数据的标签信息,所以这是一个无监督的模型
VAE¶
变分自编码器(Variational Autoencoder, VAE)是一种基于概率建模的生成模型,旨在从数据中学习潜在表示,并能生成与训练样本相似的新数据。其核心思想是将传统自编码器的概率化,通过引入潜在变量 \(z\) 和概率分布,实现从数据生成的角度理解输入。
在VAE中,假设每个观测数据 \(x\)(如图像)由一个未观测的潜在变量 \(z\) 生成。潜在变量 \(z\) 的先验分布被设定为标准高斯分布 \(p_θ(z)=N(0,I)\),这是人为固定的,便于后续从模型中随机采样生成新样本。然而,每个具体样本 \(x\) 对应的 \(z\) 并非直接采自该先验,而是通过编码器学习一个后验分布 \(q_ϕ(z∣x)\),其均值和方差由神经网络从训练数据中学习得到,从而实现对数据的有效编码。
解码器则定义了条件分布 \(p_θ(x∣z)\),通常为以 \(z\) 为输入、输出图像均值的高斯分布。这表示:给定一个潜在编码 \(z\),模型可以生成符合该分布的图像 \(x\)。因此,解码器不仅是一个映射函数,更是一个“分布生成器”,使模型具备生成多样样本的能力。
VAE的目标是让模型生成的数据分布接近真实数据分布。这通过最大化数据的边缘似然:
实现,即让真实样本 \(x\) 在模型下的概率尽可能高。
但由于该积分难以直接计算,VAE采用变分推断,引入证据下界(ELBO)作为优化目标
KL term
KL 散度(Kullback-Leibler Divergence),也叫相对熵(Relative Entropy),是用来衡量:
一个概率分布 \(q(x)\) 与另一个概率分布 \(p(x)\) 之间的差异程度。
它回答的问题是:
“如果我用分布 $ q $ 来近似真实分布 \(p\),我会损失多少信息?”
数学定义(连续情况)
对于两个连续概率分布 \(p(x)\) 和 \(q(x)\),KL 散度定义为:
离散情况(更直观)
如果 \(x\) 是离散的,KL 散度为:
关键性质
性质 | 说明 |
---|---|
✅ 非负性 | \(D_{\text{KL}}(q \parallel p) \geq 0\),当且仅当 \(q = p\) 时等于 0 |
❌ 不对称性 | \(D_{\text{KL}}(q \parallel p) \neq D_{\text{KL}}(p \parallel q)\),所以不是距离 |
📌 方向性 | \(D_{\text{KL}}(q \parallel p)\) 表示:用 \(p\) 近似 \(q\) 的代价 |
直观理解
-
如果 \(q(x)\) 在某个地方有高概率,而 \(p(x)\) 很低 → \(\log \frac{q(x)}{p(x)}\) 很大 → KL 值大
-
如果 \(q(x) \approx p(x)\) 处处成立 → \(\log \frac{q(x)}{p(x)} \approx 0\) → KL 值接近 0
所以 KL 散度越小,说明两个分布越相似。
一句话总结
KL 散度 \(D_{\text{KL}}(q \parallel p) = \int q(x) \log \frac{q(x)}{p(x)} dx\) 衡量的是:用分布 \(p\) 来近似分布 \(q\) 时的信息损失,值越小表示两个分布越接近。
于是需要训练的目标是 ELBO,得到相应的参数 \(\theta^*, \phi^*\)
一个基本训练路线如下所示
详细可以参考
那么我们的生成方式就是利用解码器对高斯分布随机选取的 z 进行解码得到新的图像

我们也可以改变 z 的一些变量的值,可以发现生成的图片的特征也发生了相应的变化

9.4 Generative Adversarial Networks (GAN)¶
GAN 是一种基于博弈论的生成模型,它通过两个神经网络之间的“对抗”来学习数据分布并生成新的样本。这两个网络分别是:
-
生成器(Generator, G*G*):负责从随机噪声中生成尽可能逼真的样本。
-
判别器(Discriminator, D*D*):负责区分生成的样本和真实的数据样本。
GAN 的核心思想是让生成器和判别器进行一个“猫鼠游戏”,在这个游戏中:
- 生成器试图生成越来越逼真的样本以欺骗判别器。
- 判别器则试图提高自己的能力,准确地区分生成的样本和真实的数据样本。
最终目标是达到一个平衡点,在这个点上生成器生成的样本足以“欺骗”判别器,使得判别器无法区分生成的样本和真实的数据样本。
我们需要完成的损失函数优化如下:
-
Discriminator (\(θ_d\) ) wants to maximize objective such that \(D(x)\) is close to 1 (real) and \(D(G(z))\) is close to 0 (fake)
-
Generator (\(θ_g\) ) wants to minimize objective such that \(D(G(z))\) is close to 1 (discriminator is fooled into thinking generated \(G(z)\) is real)
我们整个训练过程就像是两个棋手在博弈,交替训练 discriminator 和 generator
- Gradient ascent on discriminator
- Gradient descent on generator
但是在实践过程中我们发现对 generator 的优化做的并不是那么好,

我们可以发现
- 当 \(D(G(z))\) 接近于 0 时(即生成样本明显为假),损失函数 \(\log(1−D(G(z))\) 的曲线非常平坦。
- 曲线平坦意味着梯度较小,这会导致生成器参数更新缓慢,学习过程变慢。
于是我们使用 \(\log(D(G(z)))\) 作为生成器的损失函数,训练生成器的时候采用梯度上升的方式
这样我们在开始的时候就可以获得较大的梯度,在实践中的结果很好

Note
同时训练两个网络是具有挑战性的,可能会不稳定。选择具有更好损失地形的目标函数有助于训练。
训练算法的代码大致如下:
可以看到实践上我们有时候会更多地训练 discriminator。这就是实践上的 trick 了
在训练结束之后,我们就可以利用生成器来产生新的图片了。将生成器的网络改为 CNN 之后,得到的结果相当好!
深入到 GANS 内部,我们尝试理解 z 特征的含义
我们随机选择两个 z ,然后对两者进行插值,将中间的结果放入生成器中生成相应的结果
可以看到中间的结果在视觉上也是一种插值的结果
z 值甚至可以做加减
GANs 是截止2017最好的结果了,基础版本的不足之处在于难以训练,后续提出了很多 GANs 的不同版本,如 Wasserstein GAN, LSGAN 等等,还有很多其他的 GANS,可以参考