图像生成是怎么工作的
从纯噪声开始,一遍遍去掉一点点。扩散模型和文本生成的机制不同,而正是这个不同解释了那些可调参数。
第 0 步:纯噪声。模型还什么都没去掉。
文本生成是往前一步步搭出来的,一次一个 token。图像生成完全不是这么回事。
它从纯随机噪声开始,在你的 prompt 引导下一遍遍抹掉一点点,直到图像浮现出来。二十到五十遍,每一遍都比上一遍干净一点。
训练上的巧思
巧妙的地方在于这种模型是怎么训练出来的,它把问题倒了过来。
拿一张真实图像,加一点噪声,训练一个网络去预测你加进去的噪声。在很多个噪声水平上重复这件事——从几乎看不出来,到全是雪花。
这个网络就成了一个噪声预测器。而噪声预测器就是去噪器:减掉它预测出来的东西,你就得到更干净的结果。
生成就是把这个过程反过来跑。从纯噪声开始,问网络它看到了什么噪声,减掉一部分,重复。因为网络是在真实图像上学的这件事,从噪声里浮现出来的东西看起来就像真图。
每一步都是一个微小、容易的预测。难度被摊到很多步里,而不是压在某一步——思维链对语言模型有效的道理也是这样,只不过是从完全不同的方向撞上的。
prompt 从哪里进来
去噪器以文本为条件。你的 prompt 被编码成 embedding,网络在每一步通过交叉注意力去关注它们。
所以网络回答的问题不是「这里有什么噪声」,而是「在结果应该是一张猫趴在窗台上的照片这个前提下,这里有什么噪声」。每一步去噪都被推向更符合那段描述的方向。
**无分类器引导(classifier-free guidance)**把这件事放大。每一步把网络跑两遍——一次带 prompt,一次不带——然后朝远离无条件预测的方向推。引导强度(guidance scale)控制推得有多狠。值低,对 prompt 的遵循松,画面自然;值高,跟得很凶,最后会显得过饱和、怪异。这是最重要的一个旋钮,也是文本里 temperature 的直接对应物。
潜空间扩散
在全像素分辨率上去噪很贵。主流的优化是改在一个压缩过的空间里做。
一个自编码器把图像压缩成小得多的潜表示。扩散在那里发生。解码器再把最终的潜表示还原成像素。
省下来的量很大——一张 512×512 的图可能在 64×64 的潜表示里完成扩散——正是它让高分辨率生成在普通硬件上变得可行。它也解释了一类瑕疵:精细细节是解码器重建出来的,不是直接扩散出来的,这也是小字和精细纹理经常糊掉的部分原因。
那些可调参数
**步数。**去噪遍数更多,打磨更细。收益很快递减,过了某个点,多出来的步数只是多花时间。
**引导强度。**对 prompt 的遵循度与自然度的取舍,如上一节所述。
**随机种子。**初始的噪声。同一个种子加同样的 prompt 加同样的设置,会复现出同一张图——迭代之所以可能,就靠这个。
**负面 prompt。**一个用来躲开的第二条件。机制上它替换了引导里的无条件预测,这才是它居然管用的原因。
**图生图。**从一张加了部分噪声的真实图像开始,而不是纯噪声。加多少噪声,决定结果离原图漂多远。
**局部重绘(inpainting)。**只对遮罩区域去噪,其余保持不动。
它不擅长什么
它的失败很有特点,而且大多是结构性的。
**图里的文字。**在变好,历史上很糟。模型没有「字母是离散符号」这个概念,而潜空间压缩会破坏细笔画。
计数和数量。「三只猫」不可靠,原因和视觉模型数不清数一样——没有任何东西把物体一个个区分开。
**手和人体结构。**这类结构变化极大却有很强的约束,而一个全局工作、不按骨架工作的流程很难表示它。
组合关系。「蓝色球体上面放一个红色立方体」经常把颜色搞反。引导是以整张图为条件的,而不是以「物体-属性」绑定对为条件。
**精确遵循指令。**prompt 是一个摊在每一步里的柔性推动,不是一份规格说明。
关于 transformer 的一点补充
近来的系统越来越多地把老的卷积去噪器换成在潜空间方块上工作的 transformer——就是模型怎么看图像里那个「方块当 token」的思路。扩散过程没变,变的只是去噪器的架构。它的扩展性表现更好,这也是这次转向发生的理由。
要点回顾
- 扩散从噪声开始,一遍遍去掉噪声,通常 20-50 步——不像文本那样一个 token 一个 token 地生成。
- 训练教网络预测加进去的噪声;生成把这个过程反过来跑。
- prompt 在每一步都起作用;引导强度在遵循度与自然度之间做取舍。
- 潜空间扩散先去噪前压缩,这让它变得实用,也解释了精细细节上的瑕疵。
- 在文字、计数、人体结构,以及把属性和物体绑定这几方面很弱。
下一篇: 多模态 embedding