有人用魔法棒画图,有人用钢笔写字——而真正的高手,知道什么时候该用哪支笔。
AI 画图,现在所有人都在讲扩散模型。但今天这个故事里,那个模型根本不懂扩散——它只是像写字一样,一行一行,一个像素一个像素地,把画"写"出来。
单元1 | 一个被当成"过时"的思路
先问你一个问题:AI 是怎么学会画图的?
大概率你脑子里蹦出来的词是:扩散。输入一句"画一只猫",几秒钟,一张高清图出来了。这是过去三年最火的路线。
但你知道在这条路线火起来之前,还有一种更古老的玩法吗?
它叫自回归生成。听起来很学术,翻译成人话就是:像写字一样画图。
你写一篇作文,是一个字一个字往外蹦的——先写第一个字,再看一眼,写第二个字,再看一眼,写第三个字。画图也是一样:先画左上角那个像素,根据它猜右边那个,再根据这两个猜第三个……直到整张图被"写"完。
这思路放在今天,绝大多数人会嗤之以鼻:都什么年代了,还玩像素自回归?扩散模型不香吗?
但我偏偏想试试——不是因为怀旧,是因为我有一个执念:当一个模型能理解"行列",它就同时理解了"位置",而位置,是一切画面的骨架。
于是我用 373 张真实照片,从零开始,训了一个专门"写字画画"的模型。今天的这个故事,就是它的完整成长记录。
不过在讲它之前,我得先给你看看,这个模型在训练的时候,偷偷干了一件多离谱的事。
单元2 | 基础设定:让模型学会"坐标语言"
先交代一下实验的舞台。
数据:373 张真实照片,灰度的,64×64 分辨率,64 级灰度。很小,对吧?但恰恰因为小,你能把每一个细节都看清。
我要做的,是教模型"读懂"图像的结构。怎么教?给它一门"坐标语言"。
这是这个项目最妙的设计之一。模型的世界里没有"图"这个概念,只有一串令牌:start,表示开始;一个数字,表示"接下来我要从第 3 行开始写";再一个数字,“从第 7 列开始”;然后是灰度的具体值……
整张图,被翻译成了一门只有 194 个词的小语言。而模型的任务,就是把这门语言说得越来越准。
但只从左往右写,有一个致命的问题:你永远只能看到左边的东西,看不到上面的。
想象拼一幅拼图,你只看左边一块、不看上面一块,经常拼错。而画面里的信息,横着和竖着是两种完全不同的规律——横着看是渐变,竖着看是轮廓。
所以这个模型做了一个关键决策:不走单行道,走双向。它同时派出了两个"探路专家"——一个沿着行从左往右读,一个沿着列从上往下读。两个专家的判断放在一起,相乘、归一化,得出最终答案。
注意,是相乘,不是平均。这个细节,是后面所有故事的地基。
光有行列两个专家还不够。接下来,模型给自己加人手了。
单元3 | 四位专家,一场"辩论":48.4M 参数的成长之路
从最基础的版本开始,这个模型一共经历了 7 次升级。我给每个版本都配了一个"专家":
第一个专家,行专家——从左往右读。
第二个专家,列专家——从上往下读。
第三个专家,局部专家——像放大镜,盯着周围一圈的像素细节,而且是多尺度的,小圈、中圈、大圈一起看。
第四个专家,2D 专家——它不是看一条线,而是看整个二维平面,用二维递归的方式,把"左上"的区域整体记在心里。
到最后一个版本,四位专家全部到齐:行、列、多尺度局部、2D,参数量 48.4M,四条路同时推理。
这套架构最狠的地方在于:一次训练,全员上岗。训练的时候四位专家一起练,用到的时候,可以按任务只挑其中几位上场,其他人在旁边休息。
这就好像……你组了一支乐队,吉他、贝斯、鼓、键盘全练了同一首曲子。但演出的时候,你完全可以只让吉他和贝斯上——因为这场演唱会,可能只需要他们。
好,舞台搭好了,演员就位了。接下来是重头戏:演员排练的时候,作弊了。
单元4 | 五个坑,最扎心的那个:你的模型一直在作弊
这个项目的工程部分,踩了五个大坑。前四个,都是普通的坑。
比如:数据格式不对,得先转置再展开;读取存档的时候文件反复打开,导致内存损坏;训练和生成用了两套实现,结果有微小的浮点差异——这些,都还好。
真正让我脊背发凉的,是第一个坑。
项目里用了一种"因果卷积"。名字很拗口,你只需要知道:它负责让模型在预测当前位置时,只能看到过去,不能偷看未来——这是自回归的铁律。
我实现的时候,把卷积核的"未来部分"直接设成了 0,想着这样不就挡住了嘛。
但梯度,根本不认识 0。
权重是 0 不代表梯度过不去——反向传播的时候,误差照样沿着那个位置往回传。也就是说:训练的时候,模型其实一直在偷看未来,而我,完全没发现。
更恐怖的是,之前所有版本存下来的模型权重,全都带着这个"作弊缺陷"。这意味着我之前测试得到的成绩单,全部作废。
发现的那一刻,我盯着屏幕看了很久。你能想象吗?你辛苦养大的孩子,考试一直考 100 分,你以为是天赋——结果你发现,他一直在偷看答案。
而这个 bug 的修复方法,讽刺地简单:每次更新完权重,重新把"未来的位置"遮上就行。
但这句话说出来只需要一秒,发现它,我用了不知道多少个深夜。
修好这个作弊 bug 之后,四个版本重新赛跑——然后,出现了最戏剧性的一幕。
单元5 | 重新赛跑:四路夺冠,但藏着一个"魔咒"
修好作弊之后,我把四个主要版本全部重新训练、重新测试。任务有三类:修复图像中心缺失的部分、续写下半张、续写右半张,还有最难的一档——从零开始凭空画一张。
成绩按"±1 级命中率"来算,留出的测试图,不打小抄。
第一版,两路专家:中心修复 32.4%——但这个数字是侥幸,靠一次运气爆棚的采样,真实水平要打个折扣;右半续写只有 8%;凭空生成大约 26%。而且生成一张图要 42 分钟,够你看一部电影了。
第二版,加多尺度局部专家,修好作弊 bug 之后:中心修复 29.4%,右半 18%,生成 14.5%,但速度起飞,35 秒一张。
第三版,三路专家:中心 22.9%,右半 19.6%,生成 21.5%,97 秒。
第四版,四路全开:中心只有 16.9%,但右半续写直接飙到 46.7%,凭空生成 50.5%,而且只要 43 秒。
看出来了吗?四路模型在"中心修复"上,成绩反而垫底。但在右半续写和凭空生成上,直接碾压全场。
同一个模型,同一个测试环境——换了任务,排名就天翻地覆。
这不是巧合。它指向了一个反直觉的真相,也是这个项目最重要的发现。
别急,我马上把这张"神秘配方表"念给你听。
单元6 | 猪队友与灵魂:同一个模型,三种任务三套配方
我把四路模型请出来,在留出的测试图上,把五位专家组合全部跑了一遍,每个任务都用最优的组合。
结果是这样的:
任务一,中心修复。最优组合:只上行列两路。命中 17.7%。你可能会问,四路全开不是更聪明吗?不——加任何一位专家,成绩都变差。
任务二,下半续写。同样,只上行列。加人必输。
任务三,右半续写。最优组合变了:行列之外,加上局部专家。因为左半是已知的,局部专家可以借力打力,命中率干到 27.9%。
任务四,凭空生成。最优组合又变了:行列 + 局部 + 2D,三路——但列专家反而多余了。最好成绩 55.5%。想快点?行列 + 2D 就行,53.3%。
听出规律了吗?
修复类的任务,是"证据驱动"的——已知信息就在那儿,专家宁缺毋滥,最朴素的行列交叉就够了,越加人越乱。
续写类的任务,是"借力驱动"的——已知部分越丰富,越能抱对大腿,该上局部就上局部。
而凭空生成,是"想象力驱动"的——这时候,最"锐利"的局部专家和最"大局观"的 2D 专家,才是灵魂。
同一个模型,一次训练,三种任务,三套最优配方。
这是最让我着迷的地方。那些在修复任务里拖后腿的专家——局部、2D——我一度想骂它们是"猪队友":又尖锐又容易出错,一上场就把乘积给绑架了。
结果到了凭空生成的赛场上,它们直接封神:多样性、全局结构,全靠它们撑起来。
猪队友和灵魂,之间只差一个任务。
单元7 | 泼冷水:64×64 的玩具,但它教会了我一件事
现在,该有人泼冷水了。
冷静地说:这个模型只是个玩具。64×64,64 级灰度,373 张照片,从零生成的命中率也就五成半。距离"AI 画家",还有十万八千里。
它的工程上也有不完美的地方:生成要手动维护状态缓存,和训练时的 cuDNN 库存在微小的浮点分歧;存储模型权重时,打开文件的方式不对还会损坏数据——这些坑我都记在了文档里。
但这个故事的价值,不在成绩单上,而在那一张"配方表"上。
它告诉我们:专家的价值,从来不是绝对的。同一个专家,这个任务里是猪队友,换个任务就是灵魂。你在网上看到的那些"加了这个模块就变强"的经验帖,可能只是因为它恰好换了个任务。
它也告诉我们:修复和创造,用的是两套完全不同的能力。修补一张图,你需要的是一双挑剔的眼睛;凭空画一张图,你需要的是敢想的脑子。以后谁再说"会修图就会画画",你可以把这份数据甩给他。
最后,它还告诉我们一件事,关于怎么和代码相处:你的模型可能一直在骗你——而你,得有勇气把它的成绩单作废,从头再来。
结尾
写这个项目的时候,我一直在想一个问题:为什么我要用"写字"的方式画图?
后来我想明白了。扩散模型像一个魔法师,一挥魔杖,画面从天而降——但你永远不知道它在想什么。自回归模型像一个匠人,一笔一笔,每一笔都有迹可循——你能看着它的思路,理解它为什么会这样画。
而当你给匠人配上四位各怀绝技的助手,你还能看明白:什么时候该让谁上场。
这大概就是工程师的浪漫吧——别人看模型,看的是分数;我们看模型,看的是它怎么思考。
373 张照片,194 个词的"坐标语言",48.4M 参数,7 次架构迭代,5 个工程大坑,和一句最值钱的结论:
猪队友和灵魂,之间只差一个任务。
如果你也在折腾自己的小模型,或者正被某个"加了反而变差"的模块折磨——别急着删它,换个任务试试,它可能只是还没等到属于它的舞台。
评论区聊聊:你手里的模型,有没有那种"换了个场景就封神"的模块?
https://github.com/dfytensor/RCL2