跨模态 · 这一章不教任何新模型

一套机制,四种模态

上一章《生成模型家族图谱》刚选完五条路线。但它们只在文字上有用吗?
把同一套零件摊开、逐个拨到另外三种模态上看一遍,答案是: 真正要重写的只有四个零件,其中 tokenizer 最吃领域知识。 它们为什么非改不可,背后是归纳偏置这条线—— 机器对数据先做的那点假设:假设少,通用但学得贵;假设多,省数据但只对这一种数据好使。

1

我学的这些,换个模态还管用吗

这门课从头到尾讲的是同一台机器:把一串向量变得有用。 注意力、残差、LayerNorm、反向传播、AdamW、扩散、训练循环—— 但你可能已经发现,这些章的例子几乎全是文字。 那么换成像素、换成波形、换成帧,这台机器还转不转?

这个问题的答案是让人喘一口气的,而且它本身就值一条第一性原理: 核心机制大部分是通用的。这不是巧合——因为它们本来就只处理「一串向量」, 从不关心那串向量是从哪儿来的。

🎯 类比

同一套厨房设备做中餐和做西餐:灶、火候控制、尝味调整全都一样用。 真正要换的只有两样——刀工(怎么把食材切成能被加工的小块) 和最后装盘的样子(端出来的是什么)。
这一章要做的就是:把四个灶台并排摆开,让你亲眼看见哪几个零件根本没动。

?为什么这一章不做「模态目录」 范围判断▾

读完前面这些章,你可能会觉得缺了 TTS(语音合成)、ASR(语音识别)、音乐生成、视频生成。 缺是真的缺:把 Stanford 四年制 AI 本科的课程表从头翻到尾, 没有一门 TTS、ASR 或音乐生成的必修课;生图倒是已经有四章了(扩散、 DiT、流匹配、一致性模型), 真正没有的只有音频与视频。

但补成几个目录章是错的选择:这门课选的是机制深度(引擎怎么转), 不是模态广度(市面上有哪些车)。 所以这一章只做一件事:教你「同一套机制怎么换模态」。它不讲任何新模型。

2

模态切换器:哪里断了、哪里没变

下面这张数据流图从头到尾只有一张。点上面的四个按钮切换模态—— 绿框四种模态一字不改, 粉框必须换掉, 琥珀框介于两者之间。 点任意一个格子,下面会摊开它在四种模态下分别是什么。

互动 · 拨到不同模态,看哪里断了、哪里没变

互动 · 打开四种模态:到底有几个零件必须换

💡 这一章只记一句

同一台机器四种模态共用:注意力、残差 + LayerNorm、训练循环; 扩散和重建损失在图像 / 音频 / 视频上共用,到了文本要换一条路(离散的字没法直接加噪声,见第 4 节)。 换模态要动的只有四个零件:tokenizer(怎么切)、输出头(吐出来是什么)、 位置编码(1D / 2D / 3D)和评测指标。

变的是零件,不变的是零件之间的接法。 节点本身没变,但同一套注意力撞上的序列长度差了几十倍—— 这笔账在数学一节、第 7 节和最后一节都会回来算。

3

为什么注意力不用改

注意力只回答一个问题:「谁该看谁」。 它不关心被看的东西是字、是像素、还是波形——只要每个位置都已经被写成了一个向量, 它就能算。所以下面这些热力图(一张表,格子越亮就越关注那个位置),是同一段代码跑出来的。

每个位置都有三串数:Q(我想找什么)、 K(我挂出来什么)、V(我携带的内容)。 Q 和 K 逐个做点积,点积越大 = 越像 = 越该看它; softmax 把这些分数压成「加起来正好等于 1」的配比, 再按这个配比把大家的 V 混起来——所以「加权平均」平均的就是 V。 整段流程里没有一个地方提到过「字」或「像素」,完整式子在数学一节那张卡里。 (这里让 Q 和 K 共用同一张投影表,只是为了直接看相似度——投影就是乘一张表, 把一串数换成另一串数;真实注意力里 Q、K、V 各有各的可学投影表。)

互动 · 同一段注意力代码,四种真实输入

互动 · 为什么必须除以 √dk:不除,softmax 会一直很硬

💡 四张图为什么长得不一样

四张热力图来自同一个函数:每种模态先切块,每块压成一串数(这里用的是降采样 + 一张随机投影表),再算相似度。 结果是文本和音频很尖(一行最大权重平均 0.70 / 0.66,「自己」所在的对角线最亮);图像和视频摊得很开(0.32 / 0.34)。 差别不在算法,在数据自带的结构。

4

连续的数,扩散也不用改

扩散只做一件事:把信号一步步加噪,再一步步去噪。 它不关心信号是图像的一行、一段波形、还是视频里的一条时间切片—— 只要它是连续的数,公式就一个字都不用改。

前向:把原信号 x0 和一份高斯噪声 ε 按比例混起来,混合比例由第几步决定 (这条曲线叫余弦调度:按一条余弦曲线决定每一步保留多少信号—— 扩散那一章讲过)。
反向:ε 是训练时我们自己加进去的,所以已知;生成时它是网络猜出来的—— 「倒过来解」就是用猜到的 ε 从 xt 解回 x0。 所以整个扩散的灵魂只有一个问题:怎么把 ε 猜准。 而那跟模态无关,只跟「这个模态的数据长什么样」有关。

互动 · 真的加噪、真的去噪

👆 悬停公式,滑块会亮

把鼠标移到上面那张卡里的 t 或 ε 符号上——这两个滑块会分别亮起来。
t 是「第几步」,ε 是模型要猜的那份噪声。

互动 · ε 猜得准不准,四种模态的还原误差一模一样吗

⚠️ 这里的诚实边界

「扩散不变」有个前提:信号得是连续的数。 文本的第一个反应是不同意——词是离散的,加高斯噪声加不出一个「半懂不懂的词」。
所以文本走的是另外两条路:① 先查嵌入表把词变成向量,在向量空间里加噪; ② 干脆改用离散扩散(那是另一条线,见 扩散语言模型)。
这一格是这套机制上唯一一个「到了文本就得换」的裂缝——记住它, 第 5 节里它和 tokenizer 一起构成了模态之间最不通用的一环。

M

数学 · 同一行公式,四种形状

上一节说「注意力不用改、连续信号上的扩散也不用改」。这句话在数学上可以再压缩成一个字母:n。
不管喂进去的东西是字、是像素、还是波形,到了这一步永远是一个 n × d 的矩阵 ——d = 每个 token 被压成的那串数的长度(四种模态可以取同一个值)—— 算子一模一样,只有 n 不一样。而注意力要建的那张表是 n × n: 模态之间真正的数学差别,就是这个 n 带来的账。
公式里还会出现 dk:那是 Q / K 的长度——多头注意力里常取 d 除以头数; 本页的演示取 dk = d。

互动 · 四种模态的 n 和注意力矩阵,随「内容时长」一起变

同一套数据流,量纲全在 n 上

输入 (n, d) Q、K、V 都由它投影出来 n 由切法定 d = token 长度 算子(同一份代码) 注意力 + 残差 + LN 里面没有一处提到「模态」 输出 (n, d) 形状和输入一样 所以能一层层叠下去 代价藏在中间:要建一张 n × n 的表,n 一涨它按平方涨

互动 · 公式里每个符号,就是图上的一块

同一套机制,代价却是平方。下面四条曲线就是四种模态的 token 数: 横轴是内容时长,纵轴是 token 数。视频那条一路上扬,文本几乎趴在地上。

注意力这个算子对模态一无所知——它只认 n(序列多长)和 d(每个 token 的向量长度)。 所以「一套机制四种模态」在数学上就是一句话:同一个函数,喂不同的 n。 这句话的另一面是代价:函数没变,但 n 一变,算它的账就换了量纲—— 第 7 节那条 62 GB 的视频账,根就在这里。

互动 · 位置编码:1D / 2D / 3D 到底差在哪

5

最难换的零件:tokenizer

前面两节都在说「不用改」。这一节说必须改、而且最贵的那一环。 原因一句话:四个零件里,tokenizer 最需要「懂这个领域」。 它决定的是「什么算一个单位」——这是一个关于世界的问题,不是关于算法的问题。

先补一句音频的底:声音在电脑里是每秒 16000 个数(采样率 16 kHz); 频谱帧是把每 25 毫秒切一小段、看这一小段里各个音高有多响,每 10 毫秒切一次—— 换算下来每秒 100 帧。后面的「帧」和「码」指的都是这种切出来的单位。

模态怎么切切法是谁定的切错了会怎样
文本BPE / 子词 从数据里统计出来(哪些字常一起出现就合并) 还能纠回来——切碎了模型照样能从上下文猜出词
图像16×16 的块(patch) 人定死的(一个网格,和内容无关) 相邻像素被拦腰截断;网格一挪,同一个块里的内容就换了
音频频谱帧 时间和采样率定死的(25 ms 窗 / 10 ms 跳) 「帧」和时间强绑定:10 秒就是 1000 帧,压缩不了就是算不动
视频时空块 人定死的(时间 × 空间一起切) 一刀切下去,帧与帧之间的运动只能靠模型自己补

一个自然会问的问题:图像和视频的切法是「人定死的」,那有没有人像 BPE 那样从数据里学切法? 有——按内容自适应切块的方法一直有人做,但主流仍是固定网格:它便宜,而且和硬件的对齐方式一致。

互动 ① · 文本的切法,真的切一遍

改这句话试试。下面用的是真的贪心最长匹配(BPE 的最朴素形式): 它在词表里找「能匹配上的最长片段」,匹配不上就退到单字符。

互动 ② · 拖一个位移:patch 序列立刻面目全非

下面是一条真实的 1-D 信号(128 个点)。绿色的线是卷积的输出, 粉色的线是切块(每 8 个点取平均 = 一个最朴素的 patch)的输出。 拖动位移,看两条线分别对「挪一点点」有多敏感。

互动 ③ · 二维的切块:网格线一挪,块里装的东西全变了

互动 ④ · 音频为什么必须先压缩:采样点 → 帧 → 码

卷积的归纳偏置是「平移等变」:把信号挪 3 个点,输出也跟着挪 3 个点, 数值一模一样。所以它不关心你从哪开始切。
切块没有这个性质——它默默假设「第 0 个点、第 8 个点、第 16 个点……是天然的分界」, 而这条分界是切的人规定的,不是世界规定的。 这也解释了 ViT 那个著名的麻烦:换输入分辨率就得给位置编码做插值, 因为网格线挪了。

6

四种模态并排摆开

把四种模态并排放在一起(图像和视频合成一列——它们共用同一套视觉主干)。 这张表就是这一章的骨架——请横向读「…变了吗」那三行。

互动 · 把上面那张表画成一张热力图

点画布上任意一格:这里会说明那个零件在该模态上是「换 / 半换 / 没变」。

注意力里唯一要动的开关:要不要遮住「未来」

文本 / 自回归音频:因果掩码 图像 / 视频扩散:不加因果掩码 看不见未来 整张一次看 同一份注意力代码,差别只有这一个开关:遮不遮住「未来」
零件文本图像 / 视频音频
怎么切 token BPE / 子词(~10 万词表) 16×16 的 patch;视频再乘时间块 25 ms / 10 ms 的频谱帧;或神经编解码器
主流架构 decoder-only Transformer DiT(扩散)/ U-Net;视频加时序注意力 自回归 + 声码器;或 encoder-decoder
损失函数 交叉熵(预测下一个 token) 重建(MSE / LPIPS)或扩散的 ε-MSE;视频再加光流 重建(mel L1)+ 对抗;识别用 CTC / 交叉熵
评测指标 困惑度 / 准确率 FID / CLIP score / IS(图);FVD(视频) WER(识别)/ MOS(合成)/ FAD
位置编码 1D(第几个词) 2D(图)/ 3D(帧 + 行 + 列) 1D(时间)
注意力变了吗 —(它就是基准) 没变 没变
扩散变了吗 要换(离散 → 走 embedding 或离散扩散) 没变 没变
重建损失变了吗 文本没有「重建」(除非用自编码目标) 没变 没变
代表工作 GPT / Llama ViT / DiT / Stable Diffusion;Sora 一类的时空 DiT Whisper / AudioLM / EnCodec

「注意力没变」指的是那个算子(缩放点积 + softmax):换成模态,变的只是 要不要加因果掩码——文本和自回归音频要(不能偷看未来),图像与视频扩散不要, 不加因果掩码就是每个位置都能看到所有位置。
表里那排缩写,一个一句:LPIPS 比图像的感知相似度;mel L1 是频谱上的绝对误差; CTC 是语音识别的对齐损失;CLIP score / IS 是图文匹配分 / 生成图的多样性与清晰度; WER 错字率;MOS 人类打分;FAD / FVD 是把 FID 搬到音频 / 视频上; 光流是相邻两帧之间每个像素怎么移动;声码器是把频谱或编码还原成声音波形的模块。

顺带说清这一章和下一章的分工:这一章讲的是 接上之后哪些零件根本没动;而 多模态模型 那一章讲的是「怎么把视觉接进语言模型」——它讲接口,这一章讲复用。

7

三个必须点破的边界

「机制通用」是真的,但它不等于「换模态很轻松」。下面三件事是这一章必须留下的诚实标注。

互动 · 同样「10 秒的内容」,token 数差多少个数量级

拖「内容时长」:下面每种模态的 token 数、以及 n×n 那张表的显存,都会跟着重算。

互动 · 视频不是「图像的堆叠」:时序一致性

边界为什么它是独立的难题
① 视频不是「图像的堆叠」 把 300 张图分别生成、再拼起来,你会得到 300 张互不相干的图: 同一个人的脸在第 1 帧和在第 2 帧会变成两个人。 时序一致性(temporal consistency)是一个独立的难题—— 它要求模型记住「上一帧是什么」,而这一点在单张图的任务里根本不存在。 这也是 FVD 这个指标存在的原因:FID 只看单帧,看不出画面在抖。
② 音频的序列长得离谱 10 秒、16 kHz = 160,000 个采样点。 这段内容写成文字可能只有 30 个词,序列长度差三个多数量级; 而这 160,000 个点要先被压成 1,000 帧才喂给注意力(上面那个互动), 但注意力的代价随长度平方增长。所以音频必须靠 「切帧 + 神经编解码器压缩」先把长度砍下来, 「怎么砍」本身就是一个研究领域(EnCodec / SoundStream 那一类)。
③ 指标之间不可比 困惑度、FID、WER、MOS、FVD——它们连量纲都不是一回事。 FID 是「两组特征分布的距离」,WER 是「错字率」, MOS 是「人类打分」。所以「哪个模态更难」这个问题 不能靠比数字回答,只能靠比「离可用还差多少」—— 判断「做成了没有」,看这个模态自己的指标有没有接近人类水平,或者超过原有的专用方法。
⚠️ 还有一个不在表里的差异:数据量

文本有整个互联网(数万亿 token);图像有数十亿张带标注的图; 音频的高质量配对数据(音频 + 转写)大概几十万小时——Whisper 用的是 68 万小时弱标注数据; 而视频带动作 / 声音标注的公开集要少近两个数量级(AudioSet 约 5,800 小时)。 六条暗线(拆一个方法时该问的六个问题)里,C 是参数账本:在文本上问的是「算力烧多少」, 到了音频与视频就变成「数据从哪来」——这是模态之间最现实的一道墙。

8

小结

这一章属于七条线里的第二条——而且它是那条线最实用的一次应用。

它对应哪条线 ② 没有免费午餐 → 必须有归纳偏置—— 想少付先验的钱,就得付通用的钱。这一章把「先验」逼到了最吃它的那个位置:tokenizer。 注意力、残差、LayerNorm、训练循环里一点领域知识都没有, 所以它们才能跨模态复用;而 tokenizer 里全是领域知识 (「什么算一个单位」),所以它一处也复用不了。
一句话 这门课教你的不是「语言的模型」,而是 「把一串向量变得有用的机器」。 模态只决定这串向量从哪来、长什么样——它不决定机器怎么转。
它牺牲了什么 通用是要还债的。因为注意力对谁都不偏心,它必须假设 「任意两个位置都可能相关」——于是它丢掉了「近的比远的更重要」这条先验, 代价是每一步都要把所有位置互相比一遍(n²,回扣暗线 B)。 而 tokenizer 那一环无法通用,意味着每换一个模态,都要重新付一次 「设计切法」的设计费——这是这套机制通用的代价单。

它在暗线里站在哪

暗线这一章的回答
A 信息流动 四种模态最终都塌缩成同一个形状 n × d。 差别全在「n 是怎么来的」:文本的 n 由内容决定(可变、可逆), 图像/音频/视频的 n 由分辨率、采样率、帧率决定(固定、不可逆)。 图像:H×W×3 → (H/p)·(W/p) × d; 音频:16000·s / hop × d; 视频:fps·s/2·(H/p)·(W/p) × d(每 2 帧一组)。 这里 p 是块的边长、hop 是每次往前跳多少个采样点、fps 是每秒多少帧。 这也解释了上下文窗口为什么在文本上是「能塞多少字」, 到了视频上会直接变成「显存够不够」。
B 什么被牺牲了 先验被榨到了极限。为了让引擎通用,把它里面所有领域知识都删掉了—— 代价是它必须假设「所有位置都可能相关」,于是复杂度变成 O(n²), 序列一长就崩(第 7 节那张账本就是它)。
而删掉的那点先验并没有消失,只是被挪到了 tokenizer 里,变成一笔人工设计费。
C 参数账本 同一套注意力,四种模态的代表性输入:文本 512 个 token(一章文字的典型输入)、 一张图 196 个、10 秒音频 1,000 帧、10 秒视频 29,400 个(每 2 帧一组)。
注意力矩阵是 n²:从 0.5 MB(文本)一路到 1.7 GB(视频;fp16 = 每个数 2 字节,单头 = 只算一个注意力头)。拉到 1 分钟,这张表就装不下了 (第 7 节那张账本是这个数)——这时候真正的约束不是参数,是显存。 真跑视频的模型靠两件事把它压下来:FlashAttention 不把整张表算出来存下,再加上把视频压进潜空间、按时间分块。

这一章只验证了四种模态。往外推要谨慎:换到图结构(点云、分子)这类没有网格的输入, 「位置」就不是 1D / 2D / 3D 能编下的了——第五个要换的零件可能就在这时冒出来。

🎯 前后钩子

它接住了上一章的什么:《生成模型家族图谱》刚选完五条路线, 换个模态还成立吗—— ViT给了「图像能不能当序列」的第一个证据, 注意力给了那个唯一的共用算子, 扩散与DiT给了「同一套加噪去噪也能画图」, 分词给了文本侧的切法。

它给下一章留了什么:这里核对的是「哪些零件能复用」,还有一个接口问题没回答: 两套各自练好的模型,怎么接在一起? 下一章(《多模态模型》)接着做这件事—— 让只会读字的模型,长出一双眼睛。

一句话带走「一套机制,四种模态」

换模态时:注意力、残差 + LayerNorm、训练循环四种模态完全共用; 扩散和重建损失在图像 / 音频 / 视频上共用,到了文本要换一条路—— 真正要重写的只有 tokenizer(怎么切)、 输出头(吐出来是什么)、位置编码(1D / 2D / 3D)和评测指标。
所以呢:这一章的价值不是「又教了三个模态」,而是让你知道自己学的那些东西 值多少钱——你一路学下来的引擎,是通用的; 最需要每次重学的,是「这个领域里,什么算一个单位」。 而那恰好也是最没法从通用规律里推出来的那件事。

9

拓展阅读

上面讲的都是「够用」的版本。想往下挖,这里有三个入口—— 它们不是必修内容,是给想再往前走一步的读者准备的。

📄 这一章的说法从哪来

💻 工业界怎么写

∑ 更严格的形式