从零造一个 DALL·E 2:AI 绘画背后的秘密,我一口气讲清楚
你有没有想过当你输入“一只穿着宇航服的柴犬在火星上自拍”AI 是怎么在几秒钟内就画出一张像模像样的图的它真的理解“柴犬”、“宇航服”、“火星”这些词吗它脑子里到底装了什么东西今天我就把 DALL·E 2 的整个工作原理像剥洋葱一样一层一层剥给你看。不用任何数学公式不贴一行代码只用大白话。读完这篇文章你不仅能跟朋友吹牛甚至能自己动手搭一个迷你版。准备好了吗我们开始。注结尾附完整代码地址下载一、先搞懂地基扩散模型到底是啥要理解 DALL·E 2必须先理解一个概念扩散模型。这个名字听起来像物理课其实它比煮泡面还简单。1.1 你亲手做一次“扩散”想象你有一张偶像的签名照干净、清晰。你把它放在桌子上然后你拿了一张半透明的硫酸纸盖在上面用铅笔乱涂一通。现在照片变得模糊了一点。你再盖第二张纸再涂。重复五十次、一百次。到最后你什么都看不清了只剩下一团灰色的乱线。这个过程就叫“正向扩散”——把图像一步一步变成噪声。现在反过来你教会一个 AI让它看着那团乱线一步一步地“反涂”把每一层铅笔痕擦掉最后还原出签名照。这就是“逆向去噪”。DALL·E 2 画画的方式就是从一个完全随机的“乱线图”开始然后几百步地去噪每一步都让图像更清晰一点最后刚好变成你描述的那个画面。1.2 为什么用“步”而不是一步到位你可能会想为什么不能一步就把噪声变干净因为一步太难了。就像让你从一堆拼图碎片直接看出完整图案那几乎不可能。但如果你每次只拼两三个碎片拼几百次就简单多了。扩散模型就是这种“化整为零”的思路把大问题拆成上千个小问题每个小问题都很简单——只是“稍微去掉一点点噪声”。而且这种多步的方法还有一个巨大好处你可以随时喊停。比如你不想要完全清晰的图像只想要一个朦胧的草稿那走到一半就可以输出。这让 AI 变得非常灵活。二、DALL·E 2 不是一个人它的三个钢铁队友DALL·E 2 不是单个 AI而是三个模型串在一起工作。你可以把它想象成一家高级餐厅的后厨一个负责翻译菜单一个负责设计菜谱一个负责炒菜。2.1 队友一号CLIP——会翻译的“双语天才”CLIP 是 OpenAI 的另一个明星模型。它的本事是什么呢它看过 4 亿张“图片—文字”配对。比如看过一张猫的图片旁边配着文字“一只猫”看过一张车的图片配着“一辆红色跑车”。看得多了它就学会了一种能力把任意图片变成一串数字图像嵌入也把任意文字变成另一串数字文本嵌入并且让意思相近的图片和文字的数字串也相近。举个例子你给 CLIP 看一张柯基的图片它输出一串数字 A。你输入文字“短腿小狗”它输出一串数字 B。A 和 B 在数学上离得很近。你输入“宇宙飞船”它输出 CA 和 C 就隔得很远。CLIP 就像是给图片和文字都贴上了同一种“语义标签”。CLIP 的三层结构它其实由两部分组成——一个图像编码器一般是 Vision Transformer 或 ResNet和一个文本编码器Transformer。图像编码器把像素变成嵌入文本编码器把单词变成嵌入。然后 CLIP 对比这两个嵌入让配对的图文嵌入靠近不配对的远离。聊一个关键点CLIP 训练完成后在后面的任务中彻底“冻结”。什么叫冻结就是它的参数再也不变了不再学习新东西只负责干活。为什么因为一旦 CLIP 继续学习它输出的嵌入就会飘忽不定后面两个队友会疯掉。所以 DALL·E 2 的训练顺序是先独立训练好 CLIP然后冻住它再也不改。2.2 队友二号先验模型——听了上句猜出下句的“预言家”现在CLIP 已经可以输出文本嵌入了。但是真正要生成图像最方便的方式是用图像嵌入。因为图像嵌入里直接包含了像素级别的统计信息解码器更容易用。可是我们手上只有文本嵌入啊怎么办这就需要第二位队友先验模型。它的任务说出来很简单你给我一段文字我还你一个对应的 CLIP 图像嵌入。也就是说它听了“一只猫”就在脑子里想象出猫的“图像指纹”。你可能要问了CLIP 的文本嵌入和图像嵌入不是已经对齐了吗直接拿文本嵌入不能用吗能用但效果差一点。因为 CLIP 只保证了它们“相近”但没有保证它们“一模一样”。真实的世界里一句“一只狗”可能对应无数种狗的图像嵌入——金毛的、柯基的、哈士奇的。先验模型的任务就是根据文本从这无数种可能性中采样出一个最合理的图像嵌入。先验模型长什么样它使用的是一种叫 Decoder-Only Transformer 的结构跟 GPT 是一家人。但它吃的不是文字而是六样东西拼起来的“大杂烩”。这六样是原始的文字标题比如“一只猫”。CLIP 给出的文本嵌入。当前时间步的嵌入告诉模型现在进行到第几步去噪了。加了噪声的图像嵌入训练时故意添加的让模型学会去噪推理时就用纯噪声代替。一个可学习的嵌入相当于模型的一个“草稿本”。因果注意力掩码确保模型只能看到当前和之前的输入不能偷看未来这是 Decoder-Only 的特点。这六样东西排成一排送进 Transformer 里算来算去最后模型输出一个预测的图像嵌入。训练先验模型时学的东西很特别一般的扩散模型学的是预测“噪声”但 DALL·E 2 的先验模型直接学预测“干净的图像嵌入”。为什么因为论文作者发现直接预测目标比预测噪声收敛更快效果也更好。损失函数就是预测嵌入和真实嵌入之间的“均方误差”——通俗讲就是看两个数字串有多像越像越好。推理时的一个小聪明先验模型在真正使用时会一次生成两个候选的图像嵌入然后分别跟文本嵌入计算“点积”可以理解为相似度选那个更相似的作为最终输出。为什么要多此一举因为随机采样可能有坏运气生成两次选好的能显著提升质量。这叫做“重采样技巧”。2.3 队友三号解码器——真正的“神笔马良”最后一棒也是最累的一棒叫解码器。它拿到先验模型给出的图像嵌入然后从纯噪声开始一步一步地画图。解码器用的是一种叫做UNet的架构。UNet 是什么它是一个长得像 U 形的神经网络左边一层一层往下采样压缩图像提取特征右边一层一层往上采样恢复分辨率画细节中间还有“跳跃连接”把左边的细节直接送到右边防止信息丢失。这个结构在图像分割、生成领域已经被证明非常强大。解码器的两大法宝残差块和注意力块解码器不是简单的一堆卷积堆叠。它里面有两种精密的“积木块”残差块负责学习图像的局部特征比如边缘、纹理、颜色。每个残差块内部有两层卷积中间夹着激活函数和归一化。特别的是残差块会用一种“缩放与偏移”的方式把条件信息比如图像嵌入和时间步嵌入融入进去先对特征做缩放乘以一个数再加一个偏移量。这比直接把条件信息加上去效果更好。残差块最后还会把输入直接加到输出上就是“残差连接”这样能防止网络太深导致训练困难。注意力块负责学习图像中不同位置之间的长距离关系。比如画一张脸左眼和右眼距离很远但它们的纹理、颜色应该相似。普通的卷积很难捕捉这种远距离依赖但注意力机制可以。DALL·E 2 的注意力块还做了一件聪明事它不仅让图像内部的像素互相对齐还把文本编码也加进来作为额外的“键”和“值”。这样一来图像在生成时就能不断参考文字描述——比如你说“红色的鼻子”模型就会让鼻子区域的红色更突出。解码器里的时间步信息时间步是扩散模型的生命线。因为模型在早期步噪声很大和晚期步噪声很小需要做完全不同的事情。为了让模型知道现在是第几步解码器会把时间步也编码成一个嵌入然后加到条件信息里。这个时间步编码用的是正弦位置编码——跟 Transformer 里的位置编码一模一样只不过这里编码的不是位置而是时间。解码器的训练训练解码器时CLIP 和先验模型都已经被冻住了。训练数据里我们有一张清晰图像和一个文字描述。首先随机选一个时间步 t给图像加上 t 步的噪声。然后把噪声图像、时间步 t、以及先验模型预测的图像嵌入从文字描述得来一起送进解码器。解码器输出预测的噪声。损失函数就是预测噪声和真实噪声之间的均方误差。反复训练后解码器就越来越擅长去噪了。三、把三块拼起来DALL·E 2 的一整个工作流程现在你知道了三个队友各自的看家本领把它们串起来就是完整的 DALL·E 2。3.1 训练阶段教会 AI第一步训练 CLIP。这是最独立的一步。你只需要海量的图文对比如网上随便爬的图片和它的 alt 标签。CLIP 学会之后就把它冻在冰箱里。第二步训练先验模型。你现在有了冻好的 CLIP。还是用那些图文对但这次你要用 CLIP 提取出文本嵌入和图像嵌入。然后对图像嵌入随机加噪声让先验模型学会从加噪的嵌入中预测原始嵌入。训练完成后冻住先验模型。第三步训练解码器。此时 CLIP 和先验模型都冻住了。你拿一张清晰图加噪声然后把文字描述通过 CLIP 和先验模型得到图像嵌入作为条件让解码器预测噪声。反复练。这三步是顺序进行的必须等前面的训练好并冻结才能训练后面。3.2 推理阶段AI 真正干活假设你已经训练好了三个模型现在用户输入一句提示词“一只柴犬坐在冲浪板上”。第一步这句话被送进 CLIP 的文本编码器得到一个文本嵌入。第二步这个文本嵌入加上一个全零的噪声图像嵌入因为推理时没有真实图像再加上最大时间步比如 1000的嵌入一起送进先验模型。先验模型输出两个候选的图像嵌入分别与文本嵌入算相似度选相似度高的那个作为最终图像嵌入。第三步解码器拿到这个图像嵌入然后开始循环当前图像初始化为纯高斯噪声。从时间步 t 999 往下到 0根据当前图像、时间步 t、以及条件嵌入图像嵌入时间步嵌入融合而成让 UNet 预测当前步的噪声。从当前图像中减去一部分预测噪声减去多少由一个调度系数决定如果还没到最后一步就再加一点随机噪声保证多样性。把图像数值限制在合理范围比如 -1 到 1。循环结束后当前图像就是最终生成的图像。第四步输出这幅图。你就看到了“柴犬冲浪”。这个循环通常要做 1000 步每一步计算量都不小但现代 GPU 可以在几秒内完成。而且实际应用中可以用更少的步数比如 250 步来加速图像质量下降不多。四、那些你想不到的细节DALL·E 2 的隐藏智慧4.1 为什么用余弦调度而不是线性调度在扩散模型里每一步加多少噪声是由一个“方差调度”决定的。最早 DDPM 论文用的是线性调度噪声量随 t 均匀增加。但后来发现当图像分辨率不高时比如 32x32线性调度会在后期加太多噪声导致图像太早变成纯噪声模型学不到东西。于是有人提出了余弦调度——噪声量在中间步增加得慢两头增加得快。这样能让模型在中等噪声区域有更多学习机会表现更好。4.2 为什么对 CLIP 图像嵌入加噪声而不是对原始图像加噪声在先验模型里我们是对“CLIP 图像嵌入”加噪声而不是对原始像素图加噪声。这是一个容易搞混的点。因为先验模型处理的对象是嵌入向量一个一维数组不是二维图像。所以“加噪声”就是在这个向量上加随机数很简单。同理解码器才是对原始像素图像加噪声。4.3 那个“可学习嵌入”是什么鬼在先验模型的输入里有一项叫“可学习嵌入”。它本质上是一个随机初始化的小向量随着模型一起训练。它的作用是什么呢相当于给 Transformer 预留了一个“草稿位”。Transformer 在处理完前面的输入后最终在这个位置上输出结果。这是一种常用的技巧你想让模型输出某个东西就在输入序列里留一个空位让模型自己去填。4.4 为什么解码器要额外编码文本而不是只用图像嵌入解码器的条件信息中除了先验模型给的图像嵌入还会把原始文本再次经过一个文本编码器一个小型 Transformer后得到文本编码然后拼接到注意力层的键和值上。为什么不完全依赖图像嵌入因为论文作者发现这能帮助模型学习到 CLIP 没有完美捕捉到的自然语言细节。虽然实际效果提升有限但加了也没坏处。五、总结DALL·E 2 到底牛在哪现在我们把整个故事串一遍底层原理扩散模型——正向一步步加噪声逆向一步步去噪。三个模型CLIP图文对齐输出文本嵌入和图像嵌入冻住。先验模型Decoder-Only Transformer从文本嵌入预测图像嵌入。解码器UNet从图像嵌入和噪声图开始迭代去噪生成最终图像。创新点用先验模型作为桥梁把文本和图像嵌入解耦让训练更稳定用余弦调度提升小图生成质量用双采样选优提升推理效果。局限性对空间关系“左边”“右边”经常搞错生成复杂场景时可能出现奇怪的结构对罕见物体的生成容易变形。DALL·E 2 的诞生不仅仅是技术的进步更是让普通人也能拥有“想象力变现”的能力。现在当你再看到一张 AI 绘画的杰作时你应该能想象得到背后有一个 CLIP 在翻译一个先验模型在猜图像指纹一个解码器在一遍遍地洗掉噪声最终从混沌中创造出秩序。这就是 DALL·E 2 —— 一个从噪声中诞生的魔法师。完整代码下载https://pan.baidu.com/s/1RpaWuLQXLLyRTSCqEMQkvA?pwdvv2i