想象你走进一间电影剪辑室。导演没有剪辑任何实拍素材,他面对的只有一团不断抖动的“雪花噪点”。他的任务,是从这团雪花中“擦”出一段流畅的电影:一条金鱼在玻璃缸里游,阳光穿过水面,水草轻轻摆动。这不是魔法,这正是 OpenAI Sora 的工作方式。Sora 的核心是一个叫 DiT(Diffusion Transformer)的架构:它先把视频拆成一个个“时空乐高积木”(时空 Patch),再由一个超级剪辑师(Transformer)在噪声中反复打磨,最终把纯噪声还原成一段视频。这篇文章用“电影制片厂”的比喻,带你从零看懂 Sora 的 DiT 视频扩散架构。

岗位关联

理解 DiT 视频扩散,等于拿到了视频生成模型的“主心骨图纸”。无论你以后做应用、做研究还是面试,都能更快看清 Sora 这代模型的本质,以及下一代视频模型会往哪里走。

目录
  1. 可视化演示
  2. 视频生成原理
  3. 时空Patch化
  4. DiT架构核心
  5. 时空注意力机制
  6. 文本条件控制
  7. 图像扩展到视频
  8. 训练与推理
  9. Sora全景
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

交互式展示Sora核心DiT视频扩散架构:架构模式展示文本条件→时空Patch化→Transformer去噪→视频生成的完整流程,扩散模式展示从纯噪声逐步去噪生成视频帧的扩散过程,切换模式对比两种核心机制。

本节配有交互动效(进入视口后自动加载,约 3KB)。

DiT架构数据流 文本经CLIP编码为条件向量,视频帧经时空Patch化转为token序列 token序列进入Transformer blocks进行去噪,输出预测噪声并迭代去噪 ε_θ(x_t, t, c_text) DiT:条件引导的噪声预测网络

视频生成原理

剪辑室里,导演拿到一段 10 秒的成品电影。他做的第一件事,不是欣赏,而是“毁掉”它:一帧一帧往上撒噪声,撒到第 1000 步时,电影完全变成一盒“雪花”。这个把电影变雪花的过程,就是扩散模型的前向过程。Sora 的训练,正是让模型先看“从干净视频到纯噪声”的全过程,然后学会它的逆操作:从纯噪声一步一步擦出干净视频。你一旦理解了“先毁掉、再还原”的套路,Sora 就不再神秘。

这种“逐步加噪”不是一次性泼一桶颜料,而是小心翼翼地走很多小步。每一步都只加入一点高斯噪声,并且每一步混入的噪声强度由参数 $\beta_t$ 控制:

实际训练时,Sora 不会真的走完 1000 步再反向走 1000 步,而是用数学技巧一次采样出“第 $t$ 步的噪声画面”,然后让 DiT 模型去预测刚刚加入的噪声。这样做,既省时间又让模型学会在不同噪声水平下都能“擦桌子”。回到比喻:导演并不需要真的把电影毁掉 1000 次,他只要看几个“毁到一半”的瞬间,就能学会如何把雪花擦回电影。这就是视频扩散生成的第一性原理。

q(xt∣xt−1)=N(xt;1−βt xt−1, βtI)q(x_t \mid x_{t-1}) = \mathcal{N}\left(x_t; \sqrt{1-\beta_t}\,x_{t-1},\ \beta_t \mathbf{I}\right)
这个公式描述“从清晰的前一帧走到更模糊的后一帧”的随机规律:画面被轻微缩放,再叠加上一层高斯噪声。
  1. 条件概率$q(x_t \mid x_{t-1})$ 表示给定上一时刻的视频,当前时刻视频会变成什么样,这是一个随机过程。
    q(xt∣xt−1)q(x_t \mid x_{t-1})
  2. 高斯分布$\mathcal{N}$ 表示这个随机过程服从高斯分布,$\beta_t \mathbf{I}$ 是噪声的方差项,控制每步添加噪声的多少。
    N(xt;1−βt xt−1, βtI)\mathcal{N}\left(x_t; \sqrt{1-\beta_t}\,x_{t-1},\ \beta_t \mathbf{I}\right)
  3. 均值缩放$\sqrt{1-\beta_t}\,x_{t-1}$ 代表旧画面在每一步都会被轻微缩小,防止信号越积越大。
    1−βt xt−1\sqrt{1-\beta_t}\,x_{t-1}
  4. 噪声计划$\beta_t$ 随 $t$ 增大而增大,所以越靠后的步骤,画面越接近纯噪声。训练时就是随机抽取某个 $t$ 让模型学“此刻该去掉多少噪声”。
    βt∈(0,1)\beta_t \in (0,1)

时空Patch化

要把电影交给超级剪辑师处理,不能直接扔给他几百万个像素点,那样信息太多、太碎。制片厂的做法是:把电影胶片切成一颗颗“乐高积木”。每一块积木不仅覆盖画面的一个小区域,还覆盖了连续几帧的同一区域——这就是“时空 Patch”。一颗乐高积木里同时装着空间信息(在画面哪个位置)和时间信息(在哪个时间段),所以它天然保留了视频的“运动感”。

在 DiT 中,视频是一个四维张量:帧数 $T$、高度 $H$、宽度 $W$、通道数 $C$。时空 Patch 化就是把它切成许多 3D 小块,再把每块拉成一个向量,也就是 Transformer 里的一个 token:

与传统逐帧切 2D patch 不同,Sora 的时空 Patch 是“有厚度的积木”:它一次包住好几帧。导演只要扫一眼积木堆,就能同时知道“画面里有什么”和“画面在怎么动”。这也是 Sora 能把视频当作一个整体来生成,而不是一帧一帧拼起来的关键。

z=Patchify3D(x),x∈RT×H×W×C→z∈RN×D\mathbf{z} = \text{Patchify}_{3D}(\mathbf{x}), \quad \mathbf{x} \in \mathbb{R}^{T \times H \times W \times C} \to \mathbf{z} \in \mathbb{R}^{N \times D}
这段公式的意思是:把原始视频压成一张“乐高积木清单”,每个积木是一个向量,Transformer 直接处理这批向量。
  1. 视频表示$\mathbf{x}$ 是带了时间维度的原始视频,$T$ 决定“这部片子有多少帧”。
    x∈RT×H×W×C\mathbf{x} \in \mathbb{R}^{T \times H \times W \times C}
  2. Patchify 操作$\text{Patchify}_{3D}$ 沿着时间、高、宽三个方向切块,把视频变成一堆小块。
    Patchify3D(x)\text{Patchify}_{3D}(\mathbf{x})
  3. Token 数量$N$ 是总积木数,等于时间方向块数 $\times$ 高度方向块数 $\times$ 宽度方向块数。
    N=Tpt×Hph×WpwN = \frac{T}{p_t} \times \frac{H}{p_h} \times \frac{W}{p_w}
  4. 嵌入维度$D$ 是每块积木被拉成的向量长度,也就是 Transformer 内部使用的特征宽度。
    z∈RN×D\mathbf{z} \in \mathbb{R}^{N \times D}

DiT架构核心

积木准备好了,真正的“超级剪辑师”登场——DiT,即 Diffusion Transformer。过去的扩散模型常用 UNet 这类卷积网络做主干,而 DiT 直接把 Transformer 搬过来当主力。Transformer 的优势是“全员同时开会”:任何一块积木都能和另外所有积木通信,从而捕捉全局关系。剪辑师看着整堆乐高积木,不需要按顺序一帧一帧看,而能一眼掌握全局。

DiT 的输入不是一个完整视频,而是带噪声的 token 序列。它要做的事很简单:告诉制片厂 “刚才被加进去的噪声长什么样”。换句话说,它预测的不是视频本身,而是“脏东西”。这个目标用均方误差来度量:

DiT 内部还会用 AdaLN(自适应层归一化)把时间步 $t$ 和文本条件 $c$ 注入到每一层 Transformer 块中。这就像是剪辑师每看一段素材,旁边都有导演的小纸条提醒:“这是第 50 步去噪,请按‘金鱼游动’的风格处理”。正因如此,DiT 既能掌握全局结构,又能接受细粒度的外部指令,成为 Sora 的架构核心。

L=Et,ϵ[∥ϵ−ϵθ(zt,t,c)∥2]\mathcal{L} = \mathbb{E}_{t,\epsilon}\left[\left\lVert \epsilon - \epsilon_\theta\left(\mathbf{z}_t, t, c\right) \right\rVert^2\right]
DiT 的学习目标:看到加了噪声的积木堆,准确找出哪些地方是被噪声污染过的,并预测出噪声向量。
  1. 期望符号$\mathbb{E}_{t,\epsilon}$ 表示不断随机抽取时间步 $t$ 和真实噪声 $\epsilon$,对所有情况求平均损失。
    Et,ϵ\mathbb{E}_{t,\epsilon}
  2. 真实噪声$\epsilon$ 是训练时真正撒进去的噪声,相当于考卷上的标准答案。
    ϵ∼N(0,I)\epsilon \sim \mathcal{N}(0, \mathbf{I})
  3. 预测噪声$\epsilon_\theta(\mathbf{z}_t, t, c)$ 是 DiT 看到噪声积木堆 $\mathbf{z}_t$ 后给出的预测,$t$ 告诉它当前噪声程度,$c$ 是文本条件。
    ϵθ(zt,t,c)\epsilon_\theta\left(\mathbf{z}_t, t, c\right)
  4. 均方误差$\lVert \cdot \rVert^2$ 计算预测噪声和真实噪声的差,差距越小,说明剪辑师“擦除噪声”的本事越高。
    ∥ϵ−ϵθ∥2\left\lVert \epsilon - \epsilon_\theta \right\rVert^2

时空注意力机制

超级剪辑师有两只眼睛。一只眼睛盯着单帧画面:鱼缸里的气泡、水草的边缘、玻璃上的反光,这些属于“空间注意力”,负责把每一帧内部的积木拼成完整构图。另一只眼睛专门盯着时间轴:前一秒金鱼在左边,下一秒应该到中间,不能瞬移,这属于“时间注意力”。在视频 DiT 里,这两只眼睛被拆成两个注意力模块,分工明确。

空间注意力把注意力局限在同一帧内的 patch 之间,时间注意力则让不同帧之间同一位置的 patch 互相通信。二者相加,就得到完整视频注意力:

如果只有空间注意力,视频会变成一堆彼此无关的漂亮单帧照片,动起来像幻灯片;如果只有时间注意力,画面内部又会失去细节。两只眼睛缺一不可,这正是 DiT 视频生成能够做到“既有清晰画面、又有流畅运动”的核心秘密。

VideoAttn(z)=Attns(z)+Attnt(z)\text{VideoAttn}(\mathbf{z}) = \text{Attn}_s(\mathbf{z}) + \text{Attn}_t(\mathbf{z})
视频注意力 = 单帧构图的注意力 + 跨帧连贯的注意力。这一步是视频 DiT 与图像 DiT 最本质的区别之一。
  1. 空间注意力$\text{Attn}_s$ 让同一帧内的不同 patch 互相交换信息,负责理解“这一帧画的是什么”。
    Attns(z)\text{Attn}_s(\mathbf{z})
  2. 时间注意力$\text{Attn}_t$ 让同一空间位置在不同帧之间交换信息,负责理解“物体是怎么动的”,避免闪烁和跳变。
    Attnt(z)\text{Attn}_t(\mathbf{z})
  3. 相加融合两个注意力输出直接相加,相当于把“单帧理解”和“运动理解”结合成最终特征。
    VideoAttn(z)=Attns(z)+Attnt(z)\text{VideoAttn}(\mathbf{z}) = \text{Attn}_s(\mathbf{z}) + \text{Attn}_t(\mathbf{z})

文本条件控制

制片厂的导演从不亲自动手,他只递上剧本:“一只金鱼在玻璃缸里游动,阳光从左侧射入”。Sora 里的文本编码器会把这句话变成一组向量,相当于导演的“意图说明书”。但这个说明书不能扔在剪辑师桌上就完事,必须精确注人到每一步去噪过程中,模型才知道该往哪个方向“擦噪声”。

最常用的控制方法叫无分类器引导(Classifier-Free Guidance)。它的思路是:让模型分别预测“没有剧本时的噪声”和“有剧本时的噪声”,然后把两者的差值放大,让剧本的影响力更突出:

导演的剧本还可以是画面、语音甚至 3D 运动轨迹。Sora 的文本条件设计让它成为一个“多模态对齐中心”:只要是能编码成向量的信息,都能注入 DiT 的生成过程。可以说,Sora 之所以能“听懂人话”,全靠这套把文本变成注意力信号的注入机制。

ϵ^θ(zt,c)=ϵθ(zt,∅)+w[ϵθ(zt,c)−ϵθ(zt,∅)]\hat{\epsilon}_\theta(\mathbf{z}_t, c) = \epsilon_\theta(\mathbf{z}_t, \varnothing) + w\left[\epsilon_\theta(\mathbf{z}_t, c) - \epsilon_\theta(\mathbf{z}_t, \varnothing)\right]
当 $w>1$ 时,生成结果更严格遵循文本描述;当 $w=0$ 时,相当于完全忽略剧本。Sora 在训练时会让模型随机“看不到剧本”,从而学会有条件和无条件两种预测。
  1. 无条件预测$\epsilon_\theta(\mathbf{z}_t, \varnothing)$ 表示模型在没有任何文本提示时预测的噪声,相当于剪辑师凭借经验自由发挥。
    ϵθ(zt,∅)\epsilon_\theta(\mathbf{z}_t, \varnothing)
  2. 条件差值$\epsilon_\theta(\mathbf{z}_t, c) - \epsilon_\theta(\mathbf{z}_t, \varnothing)$ 是“有剧本”和“没剧本”之间的差异,差值越大说明文本对生成的影响越强。
    ϵθ(zt,c)−ϵθ(zt,∅)\epsilon_\theta(\mathbf{z}_t, c) - \epsilon_\theta(\mathbf{z}_t, \varnothing)
  3. 引导强度$w$ 是放大倍数,$w$ 越大,画面越忠于文本,但多样性会下降;实际使用中需要取一个平衡点。
    w>1w > 1

图像扩展到视频

图像 DiT 像是拍一张照片的剪辑师;视频 DiT 则是拍电影的剪辑师。从图像到视频,多出的不只是“几帧画面”,而是一个完整的时间维度。图像 patch 是 $p_h \times p_w$ 的二维方块,视频 patch 则是 $p_t \times p_h \times p_w$ 的三维积木,多了一个厚度:

从图像扩展到视频,不只是把“1 张图”变成“10 张图”,还需要增加时间注意力、引入视频级数据、把 2D 卷积升级为 3D 卷积或分解卷积。计算量也水涨船高——这也是为什么 Sora 训练和推理都需要成千上万张 GPU。类比制片厂:拍一张照片只需一台相机,拍一部电影则需要整个摄影棚、灯光组、录音组和后期机房。

Patchimage=ph×pw,Patchvideo=pt×ph×pw\text{Patch}_{\text{image}} = p_h \times p_w, \qquad \text{Patch}_{\text{video}} = p_t \times p_h \times p_w
视频 patch 比图像 patch 多了一个时间厚度 $p_t$。它把连续几帧打包在一起,让模型天然感知运动趋势。
  1. 图像Patch图像 DiT 只在高度和宽度两个方向切块,每个 patch 是平面方块。
    ph×pwp_h \times p_w
  2. 视频Patch视频 DiT 额外在时间方向切块,每个 patch 是一个“小立方体”。
    pt×ph×pwp_t \times p_h \times p_w
  3. Token数对比当视频总帧数为 $T$ 时,视频 token 数量大约是图像的 $T$ 倍,所以视频模型要处理的数据量大得多。
    Nvideo=Nimage×TptN_{\text{video}} = N_{\text{image}} \times \frac{T}{p_t}

训练与推理

训练阶段,制片厂会给剪辑师看几百万小时的真实视频,每段视频都配上文字描述。剪辑师的学习方式是:拿一段真实视频,随机加入噪声,然后尝试预测“噪声是多少”,再和真实噪声对比、更新参数。推理阶段则完全反过来:剪辑师拿到一段纯噪声视频,用学到的本领一步一步去噪,最终把噪声“显影”成新视频。这个反向过程的每一步可以写成 DDPM 采样公式:

Sora 并没有直接在原始像素上做这些运算,而是先用 3D 变分自编码器(VAE)把视频压缩到 latent 空间,在更小的张量上完成加噪、去噪,最后再由解码器把 latent 还原成像素画面。这就像剪辑师先在草图上规划镜头,最后才冲印成正式胶片。训练和推理的对称性,让 DiT 既是“学生”又是“创作者”:它在训练时看过无数电影,在推理时就能自己拍出新电影。

zt−1=1αt(zt−1−αt1−αˉt ϵ^t)+σtu\mathbf{z}_{t-1} = \frac{1}{\sqrt{\alpha_t}}\left(\mathbf{z}_t - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\,\hat{\epsilon}_t\right) + \sigma_t \mathbf{u}
这是“去噪一步”的具体操作:先根据预测噪声估算出干净画面的大致方向,再添加一点随机扰动,避免每次都生成一模一样的结果。
  1. 去噪估计括号内用当前噪声画面 $\mathbf{z}_t$ 减去按比例放大的预测噪声 $\hat{\epsilon}_t$,得到当前步骤的“净化版本”。
    1αt(zt−1−αt1−αˉt ϵ^t)\frac{1}{\sqrt{\alpha_t}}\left(\mathbf{z}_t - \frac{1-\alpha_t}{\sqrt{1-\bar{\alpha}_t}}\,\hat{\epsilon}_t\right)
  2. 随机扰动$\sigma_t \mathbf{u}$ 是刻意加入的新噪声,$\mathbf{u}$ 是标准高斯噪声,它保证每次生成结果都略有不同。
    σtu,u∼N(0,I)\sigma_t \mathbf{u}, \quad \mathbf{u} \sim \mathcal{N}(0, \mathbf{I})
  3. 重复迭代从 $t=T$ 到 $t=0$ 反复执行这个步骤,视频从纯噪声逐步变得清晰。
    T→0T \to 0

Sora全景

现在把整个制片厂俯拍一遍:导演递上剧本;制片主任把剧本编码成条件向量;剪辑师拿到的原材料是纯噪声;他把噪声视频交给 3D VAE 编码器压缩到 latent 空间;DiT 在这个低维空间里逐层做时空 Patch 化、注入文本条件、执行时空注意力、预测噪声;经过几十步去噪后,解码器把 latent 还原成像素画面。整条流水线可以浓缩为一个端到端公式:

Sora 的核心创新,就是把这套“编码-切块-Transformer 去噪-解码”的流水线做到极高的质量和规模。它的 60 秒连贯视频让人惊叹,但也要看到:它并没有内置物理引擎,杯子被碰倒后会不会碎、重物是否受重力影响,这些规律都是从海量视频中“猜”出来的,因此仍有翻车风险。理解了全景,你就能明白:Sora 不是魔法,而是一个把扩散模型、Transformer 和视频理解组合到极致的系统工程。

video=D(DiT(Patchify(E(videonoise)),c))\text{video} = \mathcal{D}\left(\text{DiT}\left(\text{Patchify}\left(\mathcal{E}\left(\text{video}_{\text{noise}}\right)\right), c\right)\right)
Sora 的完整生成链路:编码压缩 → 时空Patch化 → DiT条件去噪 → 解码回像素。每一步都像电影制片厂里的一道工序。
  1. 视频编码$\mathcal{E}$ 把像素级的噪声视频压缩进 latent 空间,大幅降低计算复杂度。
    E(videonoise)\mathcal{E}(\text{video}_{\text{noise}})
  2. 时空Patch化$\text{Patchify}$ 把压缩后的表示切成时空 token,就像把胶片剪成乐高积木。
    Patchify(⋅)\text{Patchify}(\cdot)
  3. DiT去噪$\text{DiT}$ 在文本条件 $c$ 的引导下反复去噪,输出干净的 latent 视频表示。
    DiT(⋅,c)\text{DiT}(\cdot, c)
  4. 解码器还原$\mathcal{D}$ 把 latent 空间的数据还原成可以观看的像素视频。
    D(⋅)\mathcal{D}(\cdot)

AI 应用场景

短视频广告自动生成

阶段:AIGC 内容生成 / 文本到视频

解决的问题:传统短视频广告拍摄成本高、周期长。过去品牌方想出一条 15 秒创意要先写脚本、租场地、请演员、后期剪辑,至少要一周。现在可以用 Sora 这类 DiT 视频模型,把一句话产品文案直接变成视频素材。模型先在 latent 空间去噪,再逐步“显影”出与文案匹配的画面,几分钟就能得到多条候选片子。

具体案例:某饮品品牌输入“夏日海滩上,一瓶冰镇柠檬茶放在木桌上,海风吹动吸管上的小旗子”,Sora 生成三段不同机位的视频,运营团队挑选最合适的片段直接投放到信息流广告。整个创意验证周期从 7 天缩短到 1 天。

影视预演分镜

阶段:视频生成 / 多模态条件控制

解决的问题:导演在正式拍摄前需要快速验证剧情节奏和运镜方式。传统方法需要找分镜师画几百张分镜图,或者做 3D 预演,耗时又昂贵。利用 DiT 视频扩散,导演可以把文字分镜描述转成动态视频,快速看到“金鱼从鱼缸左边游到右边”这类关键动作是否流畅。

具体案例:一部动画短片的导演把 12 个镜头脚本输入系统,系统分别生成 3 秒左右的预览视频。导演发现第 6 个镜头中角色转身的动作节奏不对,于是修改提示词重新生成,两天内完成了原本需要两周的分镜预演。

在线教育动态课件

阶段:跨模态生成 / 文本到视频

解决的问题:传统课件以静态图文为主,讲解“洋流运动”这类动态过程时缺乏直观性。用文本到视频的 DiT 模型,老师可以把一段讲解文字直接转成 10 秒科普动画,帮助学生在短时记忆窗口内理解抽象概念。

具体案例:一位地理老师输入“大西洋暖流从赤道向北流动,遇到寒流后形成 fog”,系统生成一段蓝色与橙色水流交汇的动画视频,并自动保持水流的时空连贯性。学生观看后对洋流路径的记忆正确率明显提升。

Python 演示

python69 行
import torchimport torch.nn as nnimport torch.nn.functional as F  class VideoDiT(nn.Module):    def __init__(self, T, H, W, p=2, d=32, heads=2):        super().__init__()        self.p = p        self.d = d        self.n_tokens = (T * (H // p) * (W // p))        self.patchify = nn.Conv3d(1, d, kernel_size=(1, p, p), stride=(1, p, p))        self.pos = nn.Parameter(torch.randn(1, self.n_tokens + 1, d) * 0.02)        self.attn = nn.MultiheadAttention(d, heads, batch_first=True)        self.norm1 = nn.LayerNorm(d)        self.ffn = nn.Sequential(nn.Linear(d, d * 2), nn.GELU(), nn.Linear(d * 2, d))        self.norm2 = nn.LayerNorm(d)        self.head = nn.Linear(d, p * p)        self.cls = nn.Parameter(torch.randn(1, 1, d) * 0.02)        self.text_proj = nn.Linear(d, d)     def forward(self, video, text_feat, timestep):        z = self.patchify(video)        z = z.flatten(2).transpose(1, 2)        B = z.size(0)        scale = torch.sigmoid(timestep / 100.0).view(B, 1, 1)        t_emb = torch.randn(B, 1, self.d, device=video.device) * scale        t_emb = t_emb * scale        cls = self.cls.expand(B, -1, -1) + self.text_proj(text_feat).unsqueeze(1) + t_emb        z = torch.cat([cls, z], dim=1) + self.pos        h = self.norm1(z)        a, _ = self.attn(h, h, h)        z = z + a        z = z + self.ffn(self.norm2(z))        pred = self.head(z[:, 1:])        return pred  def make_video(B, T, H, W):    video = torch.zeros(B, 1, T, H, W)    for t in range(T):        x0 = int(2 + t * 2)        video[:, 0, t, x0:x0 + 4, 6:10] = 1.0    return video  def main():    torch.manual_seed(0)    T, H, W, p = 3, 16, 16, 2    model = VideoDiT(T=T, H=H, W=W, p=p)    opt = torch.optim.AdamW(model.parameters(), lr=5e-3)    video = make_video(4, T, H, W)    for step in range(300):        noise = torch.randn_like(video)        noisy = video + 0.5 * noise        text_feat = torch.randn(4, model.d)        ts = torch.randint(0, 100, (4,)).float()        pred = model(noisy, text_feat, ts)        target = noise.view(4, -1, p * p)        loss = F.mse_loss(pred, target)        opt.zero_grad()        loss.backward()        opt.step()        if step % 50 == 0:            print("step", step, "loss", round(loss.item(), 4))  if __name__ == "__main__":    main()
目的:演示 DiT 的核心思想——把视频变成时空 Patch token,用 Transformer 预测噪声,并展示训练 loss 逐步下降的过程。
  1. self.patchify = nn.Conv3d(1, d, kernel_size=(1, p, p), stride=(1, p, p))用三维卷积实现时空 Patch 化,把 T×H×W 的视频切成 token。
  2. z = z.flatten(2).transpose(1, 2)把 [B, d, token_t, token_h, token_w] 展平成 [B, N, d],得到 Transformer 的标准输入。
  3. t_emb = torch.randn(B, 1, self.d, device=video.device) * scale用时间步生成一个缩放过的条件向量,模拟 DiT 中的时间步条件注入。
  4. cls = self.cls.expand(B, -1, -1) + self.text_proj(text_feat).unsqueeze(1) + t_emb把文本条件向量和时间条件加到 CLS token 上,模拟 AdaLN 的条件注入思路。
  5. pred = self.head(z[:, 1:])每个 token 预测自己对应 patch 里的噪声,后续用均方误差和真实噪声对比。

常见误区

误区很多人以为视频生成就像视频剪辑软件一样,先让模型生成第 1 帧,再生成第 2 帧,最后把 60 帧拼成视频。这是一种“逐帧动画”的直觉。

正解Sora 不是逐帧生成。它把所有帧切成时空 Patch,组成一个完整的 token 序列,然后用 DiT 对整个序列同时进行扩散去噪。每一帧的 token 都能互相通信,所以生成出的视频天然具有帧间一致性,不会像逐帧拼接那样闪烁、跳跃。

为何常见:人类对视频的直觉是“连续的图像序列”,而扩散模型的工作方式隐藏在 latent 空间里,看不见、摸不着,很容易被误解成“画完一帧再画下一帧”。

误区有人觉得 DiT 只是把 Transformer 层数从 12 层加到 48 层,所以效果变好了。

正解DiT 的关键不是“层数更深”,而是把扩散模型的主干从 UNet 换成 Transformer,并围绕“去噪”这一目标设计了一整套条件注入机制:时间步、文本、潜变量通过 AdaLN 或 cross-attention 注入每一层。视频 DiT 还要额外处理时空 Patch 和时空注意力,架构层面的变化远大于“堆层数”。

为何常见:Transformer 在语言模型中被广泛认知为“大力出奇迹”,于是容易把一切功劳归于规模和层数。

误区初学者常认为把文本向量和视频 token “接在一起”就能让模型理解提示词。

正解直接拼接的信息融合方式很弱。Sora 使用文本编码器提取语义向量后,会通过 AdaLN 对每层特征做缩放和偏移,或通过 cross-attention 让视频 token “查看”文本 token,同时用 classifier-free guidance 控制文本影响力。只有这样才能让“一只金鱼在玻璃缸里游”精确地指导每一处细节去噪。

为何常见:拼(concat) 是深度学习里最常见的融合操作,容易被下意识当成万能方案。

误区看到“从噪声生成视频”的示意图,不少人以为 Sora 是在 1920×1080 的原始像素上直接加噪、去噪。

正解Sora 先用 3D VAE 把视频压缩到 latent 空间,再在低分辨率的潜空间里完成扩散过程,最后用解码器还原像素。这样可以把计算量降低数十倍,也让 Transformer 能处理更长的视频。DiT 扩散的是 latent,而不是像素。

为何常见:公开的示意图大多画成“噪声块直接变成视频块”,忽略了中间的编码器与解码器,容易误导。

误区看到 Sora 生成的视频中影子方向正确、水花四溅,很多人认为模型内置了物理引擎,理解了真实世界规律。

正解Sora 没有任何物理引擎,它只是在海量视频中隐式学习到了某些统计规律。“物体受重力下落”这类表现,本质是数据分布中的常见模式。一旦遇到罕见场景,模型就会产生不符合物理常识的结果,比如杯子穿过桌面、人手多出一根手指。

为何常见:视频画面高度逼真,人类大脑会自动把视觉经验归因为“真实物理法则”,很难接受模型其实只是在做统计生成。

面试题

Q1. Sora 的视频生成架构以什么为主干?

单选题 · easy

  • A.扩散Transformer(DiT)← 正确答案
  • B.循环神经网络(RNN)
  • C.变分自编码器(VAE)
  • D.生成对抗网络(GAN)

答案:A。Sora 的核心是 DiT,即 Diffusion Transformer。它用 Transformer 作为扩散模型主干来预测噪声,RNN、VAE、GAN 都不是 Sora 的主干架构。

Q2. 时空Patch化相比图像Patch化,多处理了哪个维度?

单选题 · easy

  • A.时间维度← 正确答案
  • B.色彩维度
  • C.音频维度
  • D.文本维度

答案:A。时空 Patch 是三维积木,包含时间、高、宽三个维度。图像 Patch 只有高、宽两个维度,因此时间维度是视频与图像处理最本质的差异。

Q3. 扩散模型的前向过程主要做什么?

单选题 · mid

  • A.逐步给视频加噪声直到变成高斯噪声← 正确答案
  • B.直接从噪声生成一段新视频
  • C.压缩视频的编码率并减少存储
  • D.预测视频下一帧的像素内容

答案:A。前向过程是加噪过程,把干净视频逐步破坏成纯噪声;任务描述的是扩散模型的反向过程,C、D 分别是压缩和预测任务,与扩散生成无关。

Q4. 相比图像 DiT,Sora 视频 DiT 做了哪些扩展?

多选题 · mid

  • A.在 patch 中增加时间维度← 正确答案
  • B.增加时间注意力模块← 正确答案
  • C.使用视频级数据集训练← 正确答案
  • D.完全去掉空间注意力

答案:ABC。Video DiT 把 2D patch 变成 3D 时空 patch,增设时间注意力,并使用文本-视频对训练。空间注意力依然保留,不能去掉,否则单帧构图会崩坏。

Q5. DiT 中的噪声预测网络直接输出什么?

单选题 · mid

  • A.预测的噪声向量← 正确答案
  • B.预测的视频第一帧
  • C.预测的视频文本描述
  • D.预测的模型梯度

答案:A。DiT 通过 $\epsilon_\theta(z_t, t, c)$ 预测的是“被加入的噪声”,而不是输出画面或文本。视频画面要靠逐步去噪和 VAE 解码器还原。

Q6. Classifier-free guidance 中的 w 参数主要控制什么?

单选题 · mid

  • A.文本条件强度与生成多样性的平衡← 正确答案
  • B.视频画面的分辨率高低
  • C.扩散模型训练时的学习率
  • D.时空 Patch 的块大小

答案:A。w 会放大“有条件噪声预测”与“无条件噪声预测”的差值,w 越大越遵从提示词,同时也牺牲多样性。

Q7. 关于 Sora 的训练与推理流程,下列说法正确的有哪些?

多选题 · hard

  • A.先把视频编码到 latent 空间再做扩散← 正确答案
  • B.推理时从纯噪声开始逐步去噪← 正确答案
  • C.使用文本对视频生成做条件控制← 正确答案
  • D.推理过程完全不需要视频解码器

答案:ABC。Sora 训练与推理都在 latent 空间进行,推理从纯噪声开始按 DDPM 逐步去噪,并受文本条件控制。推理结束必须通过解码器还原像素,因此 D 错误。

Q8. 时空注意力中的“时间注意力”主要解决什么问题?

单选题 · hard

  • A.保证帧与帧之间的动作连贯性← 正确答案
  • B.提高单帧图像的边缘清晰度
  • C.缩短视频 VAE 的压缩时间
  • D.降低文本编码器的参数量

答案:A。时间注意力让不同帧同一位置的 patch 互相通信,确保物体运动轨迹连贯,这正是视频生成不闪烁、不跳变的关键。

Q9. 为什么 Sora 生成的视频有时会违反物理规律?

单选题 · extreme

  • A.模型没有内置物理引擎,物理规律只是从数据中隐式学到的← 正确答案
  • B.模型训练数据里完全没有物理过程的视频
  • C.视频的分辨率太低导致画面细节丢失
  • D.文本提示中包含了语法错误

答案:A。Sora 本质是统计生成模型,不运行物理仿真。它从海量视频中隐式学到一些物理现象的表现,但缺乏可靠的世界模型常识,因此面对罕见场景会“翻车”。

Q10. 把视频从像素空间压缩到 latent 空间的主要目的是什么?

单选题 · mid

  • A.减少计算量,让 Transformer 能处理长视频← 正确答案
  • B.让视频变成一帧静态图片
  • C.使视频模型不再需要文本条件
  • D.强制提高输出视频的帧率

答案:A。3D VAE 把高分辨率像素视频压缩成低维 latent,计算成本大幅下降,Transformer 才能处理更长的视频片段。它不会把视频变成单帧,也不需要去掉文本条件,更不能提高帧率。