跳到主要内容

生成式深度学习 — 从潜在空间里采样

这一章讲五件事: 文本怎么一个词一个词地生出来(温度); DeepDream 的迷幻图是怎么来的;风格迁移为什么只是「纹理迁移」; VAE 怎么让「编辑图像」变成「在潜在空间里做加减法」;GAN 为什么逼真又难训。 前面十一章都是「看懂世界」(识别),这一章是「生成世界」—— 作者 2014 年就预言 AI 会大量参与文化内容创作,当时没人信1

1. 顶层全景

这一章的五个技术,其实是同一个动作的五种形态:从模型学到的统计结构里采样

文本生成 从「下一词元的概率分布」里采样,逐个词元滚下去
DeepDream 反向用网络:改输入图,让某些层的激活越来越大
风格迁移 改输入图,让「内容损失 + 风格损失」越来越小
VAE 把图像压成潜在空间里的分布,从分布里采样再解码
GAN 从噪声里采样,生成器负责骗过判别器

图说:前三种是「优化输入」,后两种是「学一个可采样的空间」。

本章的主走查有两条:一条是温度——同一个训练好的语言模型、同一句提示词 (你先写下的那半句话,模型接着它往下续;这个词今天在各家聊天工具里天天出现, 英文是 prompt)「this movie」,五个温度五段完全不同的文字;另一条是 VAE—— 一张手写「4」怎么被编码成两个数 (z_mean, z_log_var),加一个随机 epsilon, 再解码回一张「4」,以及为什么这个流程让整个潜在空间变得连续。

2. 文本生成:预测下一词元,然后掷骰子

2.1 语言模型与采样循环

用深度学习生成序列的通用方法:给定前面的词元,训练模型预测下一个词元。 能对「下一词元的概率」建模的网络,就叫语言模型—— 它捕捉到的是语言的统计结构(哪些词接哪些词)2

训练好之后,生成靠一个循环:给一段开头(条件数据)→ 模型输出下一词元的概率分布 → 从中采样一个词元接上 → 把加长后的文本再喂回去 → 重复。 书里还解释了一个工程改进:不做「给 N 个词预测第 N+1 个」, 而做序列到序列——用因果掩码一次训练 N 个重叠的预测问题(第 11 章的机关), 否则提示词必须凑满 N 个词,而且大量子序列被重复编码3

2.2 回到温度:主走查第 ① 步

有了概率分布,怎么挑下一个词?贪婪采样(永远挑概率最大的)会得到重复、 可预测、甚至死循环的文字——它等价于「最大那个词概率为 1」的退化采样。 随机采样(按概率掷骰子)有创造性,但随机性的大小没法控制4

softmax 温度就是控制随机性大小的旋钮:把原分布取对数、除以温度、 再取指数归一——温度小于 1,分布变尖(更保守);大于 1,分布变平(更疯狂)5

书里的演示:同一个在 IMDB 影评上训练的 Transformer 语言模型(训练 200 轮), 提示词都是「this movie」,每轮用五个温度各生成 50 个词6:

温度这一档吐出来的样子从书里印的样本里取的几个词
0.2无聊、重复,直接陷进循环「a good movie it is a good movie」——同一句自己咬自己的尾巴
0.5通顺,但全是烂大街的套话「this movie is a waste of time and money」
0.7有趣、出人意料,又还立得住结构——本例的最佳点「this movie is fun to watch」;另一段里冒出「young people up on a small boat」——它开始编场景了,而不是套话
1.0句子还在,但开始松散、开始自相矛盾「the plot line was loud and touching」——「响亮的剧情线」,读得通,想不通
1.5局部结构瓦解,接近随机「as weird insightful actors like barker movies」——单词都认识,连不成句

右边这一列每条只取了三到八个词,书里印的样本比这长得多; 放它们在这里,是因为光看左边那一列形容词,你只知道「有区别」,看不见区别长什么样。 特别是 0.7 那一档:它和 0.5 的差别不是「更好」,是从「说套话」变成了「敢往下编」6

2.3 作者的冷水:语言模型只有形式

书里紧接着给了一段非常重要的定性,值得整段记住7:

不要期待模型能够生成任何有意义的文本…… 语言模型只有形式,没有实质内容。 它不能交流(没有什么可交流的,也没有人可交流), 不能对世界采取行动,不能社交,也没有任何思想要用语言来表达。

语言模型捕捉的是「人类使用语言时留下的可观察制品(书、影评、推文)的统计结构」。 这段话写在 2021 年、GPT-3 刚上头条之后——作者对「语言模型能做什么」的边界判断, 和第 14 章的「局部泛化」完全同构。

3. DeepDream:把滤波器可视化开到最大档

DeepDream(2015 年谷歌)的原理,你在第 09 章已经学过:反向运行卷积网络, 对输入图做梯度上升,把某层的激活值最大化——就是滤波器可视化,只有三点不同8:

  1. 最大化的是整个层的全部滤波器(不是一个),于是大量特征同时涌现;
  2. 不从噪声图开始,而从一张真实照片开始——已有的视觉模式被扭曲放大;
  3. 在多个尺度(书里叫八度)上依次处理:先小图做梦,放大 1.4 倍, 把放大时丢失的细节重新注入,再做一轮——画面因此清晰不糊9

选哪些层进损失,决定梦的风格:靠近底部的层给出几何图案, 靠近顶部的层给出可辨认的东西——狗眼睛、鸟羽毛(ImageNet 里狗和鸟特别多, 所以 DeepDream 的图里全是它们)10

4. 神经风格迁移:两个损失函数的最小化

神经风格迁移(2015 年 Gatys 等人)的目标:保留照片 A 的内容, 套上图片 B(比如梵高《星月夜》)的风格。它和所有深度学习共用一个思想: 把目标写成损失函数,然后最小化它11:

loss = distance(style(B) − style(生成图)) + distance(content(A) − content(生成图))

图说:迭代的对象是生成图的每一个像素——和第 3 节一样,网络权重不动,动的是输入。

关键是 style 和 content 怎么定义,Gatys 的发现是预训练卷积网络可以直接充当这两个函数12:

  • 内容 = 靠近顶部的层激活。顶层看到的是全局、抽象的「图里有什么」—— 两张图在这一层的激活越像,内容越一致;
  • 风格 = 多个层激活的格拉姆矩阵。格拉姆矩阵是某层特征图的内积, 记录「这层各特征之间的相互关系」——经验上,这正好抓住该尺度上的纹理外观。 在从低到高多个层上都让格拉姆矩阵对齐,各种尺度的纹理就都像了。

再加一项总变差损失(惩罚相邻像素的突变,防马赛克),三项加权, 用 SGD 迭代 4000 次,旧金山照片就换上了《星月夜》的笔触13

但作者给的定性很克制,也值得记住14:

这种技术只能改变图像纹理,即纹理迁移。 它无法实现抽象的迁移 (比如把一幅肖像的「风格」搬到另一幅肖像),更接近经典信号处理,而不是人工智能。

另一个工程结论:这个算法很慢(每张图 4000 次迭代)。 要快,就让它离线生成一大批「原图 → 风格图」的训练对, 再训练一个小型前馈网络学会这个变换——之后做一次前向传播就能出图15

5. VAE:把图像编码成分布,让潜在空间连续

5.1 潜在空间与概念向量

图像生成的关键思想:学一个低维潜在空间,空间里的任意一点, 都能被解码成一张「看起来像真的」的图——新图像是训练图像之间的插值16

这样的空间一旦到手,图像编辑就变成了向量加减法:找到「微笑向量」s, 人脸的潜在点 z 加上 s,解码出来就是同一张脸在微笑。同理还有「加墨镜」 「男性变女性」——每个有意义的方向,书里叫概念向量17

5.2 回到那张「4」:主走查第 ② 步

经典自编码器把图像压成一个固定的潜在向量再解码回去, 但它的潜在空间没有良好结构——大多数点解码出来是噪声。 变分自编码器(VAE) 的关键改动是一步:不编码成点,编码成分布的参数18

① 编码器:输入一张「4」,输出两个向量 z_mean 和 z_log_var(各 2 维)
── 它不说「这张图在这个点」,而说「这张图在这个分布里」
② 采样:z = z_mean + exp(0.5 × z_log_var) × epsilon
── epsilon 是每次现抽的随机小噪声
③ 解码器:把 z 还原成一张 28×28 的图,和原图比对算重构损失

图说:训练用两个损失——重构损失(解码得像)+ KL 散度正则项
(分布别长得太怪,向标准正态靠拢)。

那一点随机性是全部奥妙:既然 z 是抽样来的, 那么 z_mean 附近的一小片点都必须能解码成「4」—— 这迫使潜在空间里相邻的点都解码出相似的图,空间因此连续。 连续 + 低维,又让空间里每个方向都恰好对应数据里一个有意义的变化轴—— 概念向量就是这么来的19

书里把潜在空间压到 2 维,在二维网格上采样解码,画出一张 30×30 的数字墙: 沿着空间走,一个数字逐渐变形为另一个数字,全程连续20

6. GAN:伪造者与鉴定人的博弈

6.1 机制

GAN(2014 年 Goodfellow 等人)是学潜在空间的另一条路。 书里的比喻:伪造者造假画,艺术商人鉴定,商人告诉他哪里不像, 伪造者回去改——两个都越练越强,最后赝品乱真21

两个网络各司其职22:

  • 生成器:吃一个随机向量(潜在空间里的一点),吐出一张合成图;
  • 判别器:吃一张图(真的或合成的),猜它是真是假。

训练交替进行:判别器拿「真假混合图 + 真假标签」当普通分类器训; 生成器的训练信号来自判别器——往「让判别器把假图判真」的方向调。 注意一个漂亮的事实:生成器从头到尾没见过一张真图, 它关于真实世界的一切知识,都是从判别器的反馈里二手得来的23

6.2 为什么 GAN 极难训练

书里一句话点破了 GAN 和所有其他模型的本质区别24:

通常来说,梯度下降是「沿着静态的损失地形滚下山坡」。 但对于 GAN,每下山一步,都会使整个地形发生一些变化。 这是一个动态系统,优化过程寻找的不是一个最小值,而是两股力量之间的平衡。

判别器变强,生成器的损失地形就变;生成器变强,判别器的也变—— 没有静态的最小值可以收敛到。所以 GAN 的训练是一堆炼金术技巧的集合: 步幅代替汇聚(理由就是第 09 章那一条:最大汇聚会抹掉「这个特征在窗口里的哪个位置」, 而生成图像恰恰要求每个像素落在对的地方——一张脸的眼睛差两格就毁了)、 正态分布采样、给判别器的标签加随机噪声、 用 LeakyReLU 代替 relu(防梯度稀疏)、内核尺寸被步幅整除(防棋盘伪影)、 判别器里加 dropout……书里的原话:「更像是炼金术而不是科学」25

训练失衡的样子也要认得:判别器损失趋零、生成器损失暴涨 = 判别器彻底支配了生成器——对策是减小判别器的学习率、加大它的 dropout26

6.3 VAE 和 GAN 怎么选

VAEGAN
潜在空间结构良好、连续——能做概念向量编辑不一定有结构、不连续
图像逼真度一般非常逼真
训练稳定动态博弈,极难调

书里的结论:图像的大多数实际应用(编辑、动画)基于 VAE; GAN 单图逼真,在学术圈一直很受欢迎27

7. 作者的判断与证据

实测证据: 五个温度的生成样本(原书照录)、DeepDream 与风格迁移的图像、 VAE 的二维数字墙、GAN 30 轮的人脸——全是代码产物;

作者的立场声明(要当立场读,别当事实读): 「语言模型只有形式,没有实质内容」—— 这是 2021 年的作者判断,也是他整个理论框架(第 14 章)的一部分; 「风格迁移只是纹理迁移」同理,是他给这项技术划的边界;

利益相关提示: 作者 2014 年就是「AI 参与创作」的早期鼓吹者, DeepDream、Graves 的序列生成给了他做 Keras 的灵感—— 这一章他既是叙述者也是这段历史的参与者28

8. 边界与局限

  • 这一章写于扩散模型爆发之前。 它的做法一句话讲得完:先拿一张真图,一步步往上加噪点,加到最后整张变成雪花; 再训练一个网络学会「把这一步的噪点去掉」。生成时就反着来——从一张纯雪花开始, 让这个网络一步步去噪,几十步之后雪花里浮出一张图 (这个名字和这段说明不在书里,来自通用知识);

判断(我们的,不是书里的): 这一章的五项技术,概念地基照旧成立、具体架构基本都换代了。 「生成 = 从学到的统计结构里采样」这句总纲今天一个字都不用改; 但图像生成的主力已经从本章的 VAE 和 GAN 换成了上面那个扩散模型, 文本生成的主力换成了大得多的预训练 Transformer。 换代的理由和本章讲的机制是连着的: GAN 难训的根子在 §6.2—— 它的损失地形每走一步都在变;扩散模型没有这个毛病,它训的是一个普通的去噪任务, 损失地形是静态的。所以这不是「新东西更时髦」,是本章亲手指出的那个缺陷被绕开了如果错,会错在: 如果 GAN 一路的训练稳定性后来被别的办法解决了、 而它单图更逼真的优势重新占上风,那「换代」就该改说成「分工」。 我们没有引用任何具体的模型或论文作为证据,这条判断只靠对这两年公开产品形态的观察。

  • 文本生成示例是玩具级(15000 词表、训练 200 轮)——作者自己说, GPT-3 和它是同一类东西,只是更大、语料更多;
  • GAN 一节是最简 DCGAN;StyleGAN2 这类先进架构,原书明说超出范围;
  • 概念向量编辑在 GAN 空间不一定成立(空间不连续)。

9. 可带走的

  1. 生成 = 从模型学到的统计结构里采样;五种技术是这个动作的五种形态;
  2. 语言模型 = 对下一词元概率建模;生成靠「采样 → 回喂」循环;
  3. 贪婪采样复读,纯随机发疯;softmax 温度在中间调,本例最佳约 0.7;
  4. 「语言模型只有形式,没有实质内容」——作者的边界判断;
  5. DeepDream = 多尺度的滤波器可视化;放大时把丢失细节重新注入;
  6. 风格迁移 = 内容(顶层激活)+ 风格(多层格拉姆矩阵)双损失最小化;它只是纹理迁移;
  7. 慢算法可以蒸馏:先生成训练对,再训一个小前馈网络;
  8. VAE 的关键一步:编码成分布参数(z_mean, z_log_var),采样引入 epsilon—— 随机性迫使潜在空间连续,连续空间让「微笑向量」这类概念向量存在;
  9. GAN = 伪造者与鉴定人;生成器从未见过真图;它的损失地形每步都在变,所以极难训;
  10. 选型:要可编辑的连续空间用 VAE,要单图逼真用 GAN

10. 原文地图

主题原书章原文位置
作者 2014 预言与简史生成式深度学习text/19-ch12.txt:12(搜「创造性活动」) · text/19-ch12.txt:57(搜「Douglas Eck」)
语言模型与采样循环生成式深度学习text/19-ch12.txt:81(搜「接下来的一个或多个词元」) · text/19-ch12.txt:86(搜「条件数据」)
采样策略与温度生成式深度学习text/19-ch12.txt:104(搜「贪婪采样」) · text/19-ch12.txt:125(搜「softmax 温度」)
五温度生成结果生成式深度学习text/19-ch12.txt:386(搜「陷入循环」) · text/19-ch12.txt:388(搜「0.7 左右」)
「只有形式」生成式深度学习text/19-ch12.txt:396(搜「只有形式」) · text/19-ch12.txt:401(搜「操作系统」)
DeepDream 三区别与八度生成式深度学习text/19-ch12.txt:431(搜「几乎相同」) · text/19-ch12.txt:438(搜「八度」) · text/19-ch12.txt:555(搜「重新注入」)
风格迁移两损失生成式深度学习text/19-ch12.txt:668(搜「损失函数」) · text/19-ch12.txt:695(搜「格拉姆矩阵」)
纹理迁移与蒸馏生成式深度学习text/19-ch12.txt:911(搜「纹理迁移」) · text/19-ch12.txt:917(搜「前馈」)
潜在空间与概念向量生成式深度学习text/19-ch12.txt:943(搜「潜在空间」) · text/19-ch12.txt:970(搜「微笑向量」)
VAE 采样机制生成式深度学习text/19-ch12.txt:1026(搜「z_mean」) · text/19-ch12.txt:1029(搜「epsilon」) · text/19-ch12.txt:1033(搜「接近的每个点」)
KL 正则与二维网格生成式深度学习text/19-ch12.txt:1052(搜「Kullback」) · text/19-ch12.txt:1268(搜「完全连续」)
GAN 伪造者比喻生成式深度学习text/19-ch12.txt:1290(搜「伪造者」) · text/19-ch12.txt:1296(搜「打败对方」)
动态系统与技巧生成式深度学习text/19-ch12.txt:1326(搜「动态系统」) · text/19-ch12.txt:1357(搜「炼金术」) · text/19-ch12.txt:1371(搜「棋盘」)
训练失衡生成式深度学习text/19-ch12.txt:1645(搜「支配」)
VAE vs GAN生成式深度学习text/19-ch12.txt:1283(搜「连续性也不强」)

Footnotes

  1. 出处:「生成式深度学习」第 12 段(text/19-ch12.txt:12,搜「创造性活动」)与第 14 段(text/19-ch12.txt:14,搜「完全不相信」)。

  2. 出处:「生成式深度学习」第 81 段(text/19-ch12.txt:81,搜「接下来的一个或多个词元」)与第 73 段(text/19-ch12.txt:73,搜「语言模型」)。

  3. 出处:「生成式深度学习」第 240 段(text/19-ch12.txt:240,搜「序列到序列模型」)与第 241 段(text/19-ch12.txt:241,搜「因果掩码」)。

  4. 出处:「生成式深度学习」第 104 段(text/19-ch12.txt:104,搜「贪婪采样」)与第 107 段(text/19-ch12.txt:107,搜「随机采样」)。

  5. 出处:「生成式深度学习」第 125 段(text/19-ch12.txt:125,搜「softmax 温度」)与代码清单 12-1(第 130 段)。

  6. 出处:「生成式深度学习」第 349 段(text/19-ch12.txt:349,搜「temperature=0.2」)至第 388 段(text/19-ch12.txt:388,搜「0.7 左右」)。 2

  7. 出处:「生成式深度学习」第 395 段(text/19-ch12.txt:395,搜「统计模型」)与第 396 段(text/19-ch12.txt:396,搜「只有形式」)。

  8. 出处:「生成式深度学习」第 431 段(text/19-ch12.txt:431,搜「几乎相同」)与第 434 段(text/19-ch12.txt:434,搜「整个层」)。

  9. 出处:「生成式深度学习」第 438 段(text/19-ch12.txt:438,搜「八度」)与第 555 段(text/19-ch12.txt:555,搜「重新注入」)。

  10. 出处:「生成式深度学习」第 636 段(text/19-ch12.txt:636,搜「几何图形」)与第 422 段(text/19-ch12.txt:422,搜「狗的眼睛」)。

  11. 出处:「生成式深度学习」第 651 段(text/19-ch12.txt:651,搜「Gatys」)与第 668 段(text/19-ch12.txt:668,搜「损失函数」)。

  12. 出处:「生成式深度学习」第 432 段(text/19-ch12.txt:432,搜「靠近顶部」)与第 695 段(text/19-ch12.txt:695,搜「格拉姆矩阵」)。

  13. 出处:「生成式深度学习」第 807 段(text/19-ch12.txt:807,搜「总变差损失」)与第 870 段(text/19-ch12.txt:870,搜「L-BFGS」)。

  14. 出处:「生成式深度学习」第 911 段(text/19-ch12.txt:911,搜「纹理迁移」)。

  15. 出处:「生成式深度学习」第 917 段(text/19-ch12.txt:917,搜「前馈」)。

  16. 出处:「生成式深度学习」第 943 段(text/19-ch12.txt:943,搜「潜在空间」)与第 949 段(text/19-ch12.txt:949,搜「插值」)。

  17. 出处:「生成式深度学习」第 970 段(text/19-ch12.txt:970,搜「微笑向量」)。

  18. 出处:「生成式深度学习」第 1003 段(text/19-ch12.txt:1003,搜「良好结构」)与第 1007 段(text/19-ch12.txt:1007,搜「统计分布的参数」)。

  19. 出处:「生成式深度学习」第 1026 段(text/19-ch12.txt:1026,搜「z_mean」)、第 1033 段(text/19-ch12.txt:1033,搜「接近的每个点」)与第 1035 段(text/19-ch12.txt:1035,搜「有意义的变化轴」)。

  20. 出处:「生成式深度学习」第 1268 段(text/19-ch12.txt:1268,搜「完全连续」)。

  21. 出处:「生成式深度学习」第 1290 段(text/19-ch12.txt:1290,搜「伪造者」)。

  22. 出处:「生成式深度学习」第 1298 段(text/19-ch12.txt:1298,搜「生成器网络」)与第 1300 段(text/19-ch12.txt:1300,搜「判别器网络」)。

  23. 出处:「生成式深度学习」第 1654 段(text/19-ch12.txt:1654,搜「不会直接查看」)。

  24. 出处:「生成式深度学习」第 1324 段(text/19-ch12.txt:1324,搜「优化最小值」)与第 1326 段(text/19-ch12.txt:1326,搜「动态系统」)。

  25. 出处:「生成式深度学习」第 1355 段(text/19-ch12.txt:1355,搜「诸多技巧」)、第 1357 段(text/19-ch12.txt:1357,搜「炼金术」)与第 1371 段(text/19-ch12.txt:1371,搜「棋盘」)。

  26. 出处:「生成式深度学习」第 1645 段(text/19-ch12.txt:1645,搜「支配」)。

  27. 出处:「生成式深度学习」第 1283 段(text/19-ch12.txt:1283,搜「连续性也不强」)与第 1284 段(text/19-ch12.txt:1284,搜「学术研究领域」)。

  28. 出处:「生成式深度学习」第 64 段(text/19-ch12.txt:64,搜「Alex Graves」)与第 67 段(text/19-ch12.txt:67,搜「Keras」)。