引:这篇由 William Peebles 和 Saining Xie 提出的工作,将 latent diffusion 中常用的 U-Net 去噪主干替换成了 Transformer,形成 Diffusion Transformer,也就是 DiT。文章最值得关注的部分,是它如何把带噪 latent、扩散时间步和生成条件接入一个接近标准 ViT 的结构,并通过系统实验说明:增加模型规模,以及增加参与计算的 token 数,都能改善生成质量。

为了阅读任何与diffusion有关的文章,先学习一些前置知识或者了解一下有关diffusion models的发展脉络是很有助益的。在此推荐大神Lilian Weng的这篇博客。

背景

在本文提出时,图像扩散模型通常使用 U-Net 作为去噪网络。它把带噪图像或 latent 输入网络,通过逐层下采样、上采样和跨层连接来预测去噪所需的信息。这样的网络并不只有卷积,很多扩散 U-Net 也会在部分分辨率下插入 attention,但整体上仍然沿用多尺度的编码、解码结构。

另一方面,Transformer 已经在语言和视觉任务上展示了较好的扩展能力。那么,对于扩散模型而言,U-Net 的这套结构究竟是不是必需的?能不能像 ViT 一样,把输入切成一组 patch,再交给一个结构相对统一的 Transformer 处理?

这个替换还有一个需要解决的问题:普通 ViT 主要根据图像内容提取特征,而扩散模型还必须知道当前处于哪个噪声时间步,以及希望生成什么内容。这些条件怎样进入 Transformer,会直接影响它的去噪效果。

所以,本文主要围绕两个问题展开:

  1. 如何设计一个适合条件扩散的 Transformer,尤其是如何注入时间步和类别条件;
  2. 当模型变深、变宽,或者输入的 token 变多时,生成效果怎样变化。

方法

从图像到 latent diffusion

DiT 沿用 Latent Diffusion Models 的框架。我们先看它处理的对象是什么。

设真实图像为 x0x_0,作者使用一个预训练的 VAE 将它编码成 latent z0z_0:

z0=E(x0),x0≈D(z0)z_0=\mathcal{E}(x_0),\qquad x_0\approx\mathcal{D}(z_0)

其中,E\mathcal{E} 和 D\mathcal{D} 分别是 VAE 的编码器和解码器。对一张 256×256×3256\times256\times3 的 RGB 图像,本文使用的 VAE 会将其压缩成 32×32×432\times32\times4 的特征,也就是空间分辨率缩小到原来的八分之一。

之后,扩散过程就在这个较小的 latent 上进行。训练 DiT 时,VAE 保持冻结,模型学习的是这些 latent 的分布。生成时先得到一份新的 latent,再用 VAE Decoder 将它还原成图像。

这里的 latent 仍然有二维空间布局,每个位置包含若干通道的连续特征。它既不是单个全局向量,也不是离散的图像 token 编号。后面切 patch 时,切的就是这张二维特征图。

DiT的训练预测目标

作者沿用 DDPM 的加噪与去噪设定。给干净的 latent z0z_0 加入高斯噪声,可以得到时间步 tt 对应的输入:

zt=αˉt z0+1−αˉt ϵ,ϵ∼N(0,I)z_t=\sqrt{\bar{\alpha}_t}\,z_0+ \sqrt{1-\bar{\alpha}_t}\,\epsilon, \qquad \epsilon\sim\mathcal{N}(0,I)

这里 αˉt\bar{\alpha}_t 由预先设定的噪声时间表决定。简单地说,这个式子在控制干净信号和噪声的比例,模型根据 tt 知道当前输入被破坏到了什么程度。

对类别条件生成,我们还会给模型一个标签 yy。DiT 的任务就是接收 ztz_t、tt 和 yy,预测其中的噪声,以及反向扩散分布所需的方差参数。反向过程可以写成:

pθ(zt−1∣zt,y)=N ⁣(μθ(zt,t,y),Σθ(zt,t,y))p_\theta(z_{t-1}\mid z_t,y)= \mathcal{N}\!\left( \mu_\theta(z_t,t,y),\Sigma_\theta(z_t,t,y) \right)

其中,均值 μθ\mu_\theta 可以由模型预测的噪声和已知噪声时间表计算出来;Σθ\Sigma_\theta 则控制这一步反向采样的不确定性。也就是说,DiT 提供每一步去噪需要的信息,再由扩散采样器更新 latent。

DiT 整体结构及条件注入方式

右侧展示了另外两种条件注入方式。本文选择了adaLN-Zero这种注入方式,后文会解释理由。

从 latent 到 token

现在我们有了一张带噪的 latent 特征图,要怎样把它交给 Transformer 呢?作者采用的方式和 ViT 很接近:切 patch,再做线性映射。

设 latent 的大小为 I×I×CI\times I\times C,patch 大小为 p×pp\times p,那么它会被划分成:

N=(Ip)2N=\left(\frac{I}{p}\right)^2

个 patch。每个 patch 展平后有 p2Cp^2C 个数,再通过线性层映射成一个 dd 维 token。这里,NN 是 token 数量,dd 是 Transformer 的隐藏维度。

举个例子,对前面 32×32×432\times32\times4 的 latent,如果使用 p=2p=2,我们就会得到 16×16=25616\times16=256 个 patch。每个 patch 包含 2×2×4=162\times2\times4=16 个数,这 16 个数经过同一个线性映射后,成为一个高维 token。在 DiT-XL 中,隐藏维度为 1152,所以输入形状的变化可以整理为:

32×32×4  ⟶  256×16  ⟶  256×115232\times32\times4 \;\longrightarrow\; 256\times16 \;\longrightarrow\; 256\times1152

这些 token 还会加上固定的二维正弦、余弦位置编码,告诉模型各个 patch 原本位于什么位置。之后,所有 token 进入一系列 DiT blocks,通过 self-attention 和前馈网络交换、更新信息。

这里的 self-attention 可以访问全部图像 token。在同一个扩散时间步中,模型会一起处理整张 latent,而不是按照从左到右的顺序逐个生成 patch。

对同一张 32×3232\times32 的 latent,不同 patch size 会产生不同长度的序列:

Latent patch size p Token 数量 N
8 16
4 64
2 256

可以看到,patch 边长减半,token 数量就会变成原来的四倍。模型因此会用更多 token 参与信息交互,但这并没有改变 latent 本身的分辨率。

从计算量来看,标准 Transformer block 中,线性投影和前馈网络大致包含 O(Nd2)O(Nd^2) 的开销,attention 中的位置对交互则包含 O(N2d)O(N^2d) 的开销。所以 token 变多时,计算量会明显增加;而主干的权重在不同 token 间共享,参数量不会随 token 数量同比增加。增加 token,是一种基本不增加主干参数、却能增加模型计算量的扩展方式。 后面的实验会专门比较这一点。

条件注入

我们已经知道 latent token 怎样产生,但只输入它们还不够。模型还要知道时间步 tt 和类别标签 yy:前者告诉它当前的噪声状态,后者告诉它希望生成哪一类图像。

作者为时间步构造正弦、余弦 embedding,再通过 MLP 映射到隐藏维度;类别标签则通过一个可学习的 embedding 表得到向量。对于 adaLN 系列的 block,两者相加形成条件向量:

c=et(t)+ey(y),c∈Rdc=e_t(t)+e_y(y),\qquad c\in\mathbb{R}^d

接下来,关键就是这个条件向量怎样影响图像 token。作者比较了四种设计:

条件注入方式 具体做法
In-context conditioning 将时间步和类别 embedding 作为两个额外 token,与图像 token 一起做 self-attention;最后移除这两个条件 token
Cross-attention 将两个条件 embedding 组成独立序列,在 self-attention 之后增加一层 cross-attention,由图像 token 读取条件
adaLN 根据时间步与类别的组合条件,动态生成 LayerNorm 后的缩放、平移参数
adaLN-Zero 在 adaLN 基础上,再控制残差分支的输出幅度,并将 block 初始化为恒等映射

实验中效果最好的是 adaLN-Zero。下面重点介绍它怎样工作。

Adaptive LayerNorm(adaLN)

普通 LayerNorm 会对每个 token 的特征做归一化,再使用可学习的缩放和平移参数调节结果,这样的参数在训练完成后是固定的。而adaLN 的想法是在这些参数上做条件注入,我们可以将它表示为:

adaLN⁡(hi,c)=(1+s(c))⊙LN⁡(hi)+b(c)\operatorname{adaLN}(h_i,c)= \left(1+s(c)\right)\odot\operatorname{LN}(h_i)+b(c)

这里 hih_i 是第 ii 个 token 的特征,s(c)s(c) 和 b(c)b(c) 是根据条件预测出来的两个 dd 维向量,⊙\odot 表示逐元素相乘。对于同一个样本、同一个 block,这组条件参数会被广播到全部 token。

adaLN-Zero

Zero 指的是通过零初始化,使每个残差 block 从恒等映射开始训练,从而改善深层网络的优化。这是对于ResNet和扩散U-Net的做法的保留。

一个标准的残差更新可以写成 h′=h+F(h)h'=h+F(h)。如果训练开始时,残差分支 FF 的贡献为零,那么这个 block 就先执行 h′=hh'=h,随后再逐步学习怎样修改输入。作者将这种初始化方式用到了 DiT 中。

具体来说,每个 adaLN-Zero block 会根据条件向量 cc 生成六个 dd 维向量:attention 分支的缩放 s1s_1、平移 b1b_1 和残差门控 a1a_1,以及前馈分支对应的 s2,b2,a2s_2,b_2,a_2。一个 block 可以写成:

u=h+a1(c)⊙MSA⁡ ⁣((1+s1(c))⊙LN⁡(h)+b1(c))u=h+a_1(c)\odot \operatorname{MSA}\!\left( \left(1+s_1(c)\right)\odot\operatorname{LN}(h)+b_1(c) \right)

h′=u+a2(c)⊙FFN⁡ ⁣((1+s2(c))⊙LN⁡(u)+b2(c))h'=u+a_2(c)\odot \operatorname{FFN}\!\left( \left(1+s_2(c)\right)\odot\operatorname{LN}(u)+b_2(c) \right)

作者将生成这些调制参数的 MLP 的最后一个线性层初始化为零,因此两条残差分支暂时都不改变输入,整个 block 满足 h′=hh'=h。attention 和 FFN 的权重仍然采用正常初始化,并没有被全部置零。

从 token 恢复噪声预测

经过多个 DiT blocks 后,每个 token 仍然是一个 dd 维特征。为了得到空间上的预测,作者在最后进行条件归一化,再用线性层将每个 token 映射成 p2⋅2Cp^2\cdot2C 个数。其中C个通道用于预测噪声,另外C个用于计算反向过程的方差。

至此,一次 DiT 前向计算就完成了:

zt  →patchify  tokens  →DiT blocks conditioned on t,y  features  →linear + unpatchify  ϵ^θ, vθz_t \;\xrightarrow{\text{patchify}}\; \text{tokens} \;\xrightarrow{\text{DiT blocks conditioned on }t,y}\; \text{features} \;\xrightarrow{\text{linear + unpatchify}}\; \hat{\epsilon}_\theta,\ v_\theta

其中 vθv_\theta 表示用于计算方差的输出参数。求出这两项之后就能得到最终的zt−1z_{t-1}了,也就是完成一次去噪。

Note

读到这里,我们可能会产生疑问:难道模型不需要直接输出对于均值的预测?其实从DDPM的原理出发,已知噪声和方差,我们可以求出均值。公式如下:

μθ=1αt(zt−βt1−αˉtϵ^θ(zt,t,y))\boxed{\mu_\theta = \frac{1}{\sqrt{\alpha_t}} \left( z_t- \frac{\beta_t}{\sqrt{1-\bar\alpha_t}} \hat\epsilon_\theta(z_t,t,y) \right) }

这个式子的推导很关键,日后会做一篇文章出来单独记录和Diffusion Models有关的数学推导。

有了以上的这个公式,就可以推导出最后的zt−1z_{t-1}的公式了:

zt−1=1αt(zt−βt1−αˉtϵ^θ(zt,t,y))⏟根据预测噪声计算中心位置+σθ(zt,t,y)⊙ξ⏟按预测方差加入随机扰动\boxed{ z_{t-1} = \underbrace{ \frac{1}{\sqrt{\alpha_t}} \left( z_t- \frac{\beta_t}{\sqrt{1-\bar\alpha_t}} \hat\epsilon_\theta(z_t,t,y) \right) }_{\text{根据预测噪声计算中心位置}} + \underbrace{ \sigma_\theta(z_t,t,y)\odot\xi }_{\text{按预测方差加入随机扰动}} }

训练

训练时,我们已经有真实图像,也知道它的类别,所以可以直接构造监督。具体过程为:

  1. 使用冻结的 VAE Encoder,将图像转换成 latent z0z_0;
  2. 随机采样时间步 tt 和高斯噪声 ϵ\epsilon,按前面的加噪公式构造 ztz_t;
  3. 将 zt,t,yz_t,t,y 输入 DiT,得到噪声预测及方差参数;
  4. 根据预测和已知噪声计算损失,更新 DiT。

噪声预测使用均方误差:

Lnoise=Ez0,t,y,ϵ[∥ϵ−ϵ^θ(zt,t,y)∥22]\mathcal{L}_{\mathrm{noise}}= \mathbb{E}_{z_0,t,y,\epsilon} \left[\left\| \epsilon-\hat{\epsilon}_\theta(z_t,t,y) \right\|_2^2\right]

这个监督很直接:噪声是我们自己加入的,所以它的真实值已知。对于协方差预测,作者沿用 Improved DDPM / ADM 的做法,使用变分目标中的对应项进行训练。官方实现计算这一项时,会对噪声预测部分停止梯度,方差预测则参与该项的优化。

实现细节:官方 PyTorch 训练代码从 VAE 的后验分布采样 latent,并乘以 0.18215 进行缩放;最终送入 VAE Decoder 前再还原这个尺度。本文公式中的 zz 可以理解为已经按该约定处理后的扩散输入。

此外,为了支持后面的 Classifier-Free Guidance(CFG),训练中会随机将一部分样本的类别标签替换为可学习的空条件 embedding。官方实现默认的类别丢弃概率为 10%。这样,同一个 DiT 既学会给定类别时怎样去噪,也学会没有类别条件时怎样去噪。

推理与 Classifier-Free Guidance

推理时没有真实图像,模型从高斯噪声 latent 开始生成。给定类别 yy,在每个采样时间步,我们可以分别计算有类别条件和空条件下的噪声预测,再组合成:

ϵ^cfg(zt,t,y)=ϵ^θ(zt,t,∅)+s[ϵ^θ(zt,t,y)−ϵ^θ(zt,t,∅)]\hat{\epsilon}_{\mathrm{cfg}}(z_t,t,y)= \hat{\epsilon}_\theta(z_t,t,\varnothing) +s\left[ \hat{\epsilon}_\theta(z_t,t,y)- \hat{\epsilon}_\theta(z_t,t,\varnothing) \right]

其中 ss 是 guidance scale。当 s=1s=1 时,这个式子就是普通的有条件噪声预测;当 s>1s>1 时,它沿着有条件与无条件预测的差异进一步外推,加强类别条件的作用。

整个生成过程可以整理为:

  1. 采样一张与目标 latent 同形状的高斯噪声 zTz_T;
  2. 在当前时间步输入 latent、时间步与类别条件,计算 DiT 的预测;
  3. 使用 CFG 组合噪声预测,并由噪声时间表和模型输出确定反向采样所需的均值、方差;
  4. 采样得到噪声更少的 latent,沿选定的时间步序列重复这一过程;
  5. 得到最终 latent 后,用 VAE Decoder 还原成图像。

本文训练采用 1000 个离散扩散时间步,主要的 FID 对比使用重采样时间表后的 250 步 DDPM 采样。模型每一步都处理全部 latent token,生成一张图仍然需要多次前向计算。

实验

数据与基本设定

作者在 ImageNet 上训练类别条件图像生成模型,分别生成 256×256256\times256 和 512×512512\times512 的图像。VAE 使用 Stable Diffusion 的预训练模型,DiT 本身从头训练。

为了分析扩展性,作者设置了四种模型规模。下面摘自原论文 Table 1;这一列 Gflops 的计算条件统一为 latent 大小 32×3232\times32、patch size p=4p=4:

模型 Block 数量 隐藏维度 dd Attention heads 单次前向 Gflops(p=4p=4)
DiT-S 12 384 6 1.4
DiT-B 12 768 12 5.6
DiT-L 24 1024 16 19.7
DiT-XL 28 1152 16 29.1

每种规模又分别使用 8、4、2 三种 patch size,共形成 12 个配置。例如,DiT-XL/2 就表示 XL 规模、latent patch size 为 2;在 256×256256\times256 图像生成中,它约有 6.75 亿参数,单次前向计算量为 118.6 Gflops。

所有配置使用相同的训练超参数:AdamW、固定学习率 10−410^{-4}、batch size 256、weight decay 为零,采用水平翻转作为数据增强,并使用衰减系数为 0.9999 的 EMA 参数进行评估。原论文的实验使用 JAX,在 TPU-v3 上训练;官方另外提供了 PyTorch 实现。

评价主要使用 FID-50K,也就是从模型中生成 50,000 张图像,在 Inception 特征空间比较生成数据与真实数据的分布差异,数值越低越好。论文还报告 IS、sFID 和 Precision / Recall 等指标。

条件注入:为什么选择 adaLN-Zero?

作者固定 XL/2 的主体规模,分别训练前面介绍的四种条件注入结构。原论文 Fig. 5 比较了它们训练到 400K,也就是 40 万步时的 FID 曲线。

结果中,adaLN-Zero 在各个评估阶段都优于 cross-attention 和 in-context conditioning,也明显优于普通 adaLN。在 40 万步时,它的 FID 约为 in-context 方案的一半。

计算量方面,adaLN 和 adaLN-Zero 都为 118.6 Gflops,in-context 为 119.4 Gflops,而 cross-attention 达到 137.6 Gflops。因此,adaLN-Zero 在这个比较里同时得到了更好的生成质量和较小的额外计算开销。

这组实验接回了前面的结构设计:条件怎样进入网络,以及残差分支从什么状态开始学习,都对最后的效果有明显影响。 后续的 scaling 实验因此统一采用 adaLN-Zero。

模型变大、token 变多,会发生什么?

模型规模和 patch size 对 FID 的影响

上排固定 patch size,比较模型规模;下排固定模型规模,比较 patch size。

先固定 patch size,只增加 Transformer 的深度和宽度。图中可以看到,更大的模型在训练过程中通常能得到更低的 FID。再固定主干规模,将 patch size 从 8 减到 4、再减到 2,同样能得到明显改善。

后者尤其值得关注,因为它基本没有增加 Transformer 主干的参数,却增加了 token 数量与计算量。对这组模型来说,仅用参数量描述模型规模,并不足以说明它实际处理了多少信息交互。

作者进一步在原论文 Fig. 8 中,将 12 个配置在 40 万步时的 FID 与单次前向 Gflops 对照,观察到较强的负相关关系:即使深度、宽度和 patch size 的组合不同,计算量接近的模型也可能取得接近的 FID。

另外,固定训练步数并不等于固定训练成本。作者在 Fig. 9 中又按总训练计算量比较,估计方式为:

Ctrain≈FLOPs⁡forward×B×K×3C_{\mathrm{train}}\approx \operatorname{FLOPs}_{\mathrm{forward}} \times B\times K\times3

其中 BB 是 batch size,KK 是训练步数,系数 3 将一次前向和近似为两次前向开销的反向传播合在一起。在论文考察的预算范围内,一些较大模型即使训练步数更少,也比训练更久的小模型更有效地利用计算量。

所以,扩展模型时需要一起考虑深度、宽度和 token 数,再看给定训练预算下的生成效果。这也是标题中 Scalable 所对应的主要实验内容。

最终生成效果

在确定结构之后,作者继续训练 DiT-XL/2。256×256256\times256 模型训练到 7M,也就是 700 万步;512×512512\times512 则单独训练了一个模型,训练到 3M 步。下面的最终成绩与前面 40 万步的消融、scaling 比较属于不同训练阶段。

下表选自原论文 Table 2,展示 ImageNet 256×256256\times256 下的结果:

方法 CFG scale FID-50K ↓ Precision ↑ Recall ↑
LDM-4 不使用 10.56 0.71 0.62
LDM-4-G 1.50 3.60 0.87 0.48
DiT-XL/2 不使用 9.62 0.67 0.67
DiT-XL/2-G 1.25 3.22 0.76 0.62
DiT-XL/2-G 1.50 2.27 0.83 0.57

DiT-XL/2 在 CFG scale 为 1.50 时取得 2.27 的 FID。表中同时可以看到,guidance 的作用很大:同一个模型在无 guidance 时的 FID 为 9.62;随着 guidance 增强,生成结果更集中于条件要求,Precision 提高,Recall 则下降。这对应生成样本质量与分布覆盖之间的取舍。

在 512×512512\times512 下,原论文 Table 3 中 DiT-XL/2-G 在相同 CFG scale 下的 FID 为 3.04,优于表中此前的扩散模型。不过该表中的 StyleGAN-XL 为 2.41,仍然更低,所以这一分辨率下的结论应限定为当时比较的扩散模型。

分辨率变化也能直接接回前面的 token 分析:512×512512\times512 图像对应 64×64×464\times64\times4 的 latent,使用 p=2p=2 时共有 1024 个 token,是 256×256256\times256 情况的四倍。同一 XL/2 配置的单次前向计算量因此从 118.6 增加到 524.6 Gflops。

小模型能不能靠多采样几步补回来?

扩散模型有一个特殊之处:训练完成后,还可以通过增加采样步数,让每张图像使用更多计算。那么,一个小 DiT 多去噪几次,能不能达到大模型的效果呢?

作者在原论文 Sec. 5.2 / Fig. 10 中,对训练了 40 万步的 12 个模型分别使用 16、32、64、128、256 和 1000 个采样步,比较 FID-10K 与采样计算量。

其中一个例子是,DiT-L/2 使用 1000 步时,每张图约需 80.7 Tflops,FID-10K 为 25.9;DiT-XL/2 使用 128 步时,每张图约需 15.2 Tflops,FID-10K 为 23.7。后者计算量约为前者的五分之一,生成效果却更好。

这个实验说明,在本文考察的模型和采样设置中,增加小模型的采样次数,并不能直接替代提高单步模型的能力。一次前向计算能做多好的去噪,同样影响最终结果。

核心点和不足

值得关注

这篇文章将图像扩散的去噪问题,整理成了一组空间 token 在时间步与类别条件下更新的问题。patchify 负责把 latent 接入 Transformer,adaLN-Zero 负责注入条件、组织残差更新,线性输出头再把 token 还原成去噪所需的空间预测。整体结构比较统一,也便于分别调整深度、宽度和 token 数。

它提出的一个有用视角是,生成模型的规模应结合实际计算方式来理解。两个参数量接近的模型,可以因为 patch size 不同而有完全不同的 token 数量、计算量和生成效果。进一步看,模型变大与采样步数变多,也是两种不同的计算投入,需要分别比较。

这也能帮助我们理解 Nexus 中的 DiT 模块:先把当前要生成的对象转换为 token,让时间步和任务条件参与特征更新,再将输出映射回目标表示。具体 token 可以来自图像 latent、八叉树的 occupancy pattern 或逐顶点特征;使用什么训练目标、怎样解读输出,则由各自的生成任务决定。

仍然存在的问题

首先,更小的 patch 会带来更长的序列。前面 256×256256\times256 到 512×512512\times512 的例子已经说明,即使模型的深度和宽度保持一致,token 数也会让计算量明显上升。对于更高分辨率的输入,怎样更有效地组织这些 token 的交互,仍然是需要继续处理的问题。

其次,latent diffusion 的结果也受预训练 VAE 的影响。DiT 学习的是编码后的分布,最终图像要经过 Decoder 还原;压缩过程中没有保留下来的细节,会对最终结果形成限制。

另外,本文主要验证的是 ImageNet 类别条件生成,时间步与类别可以组合成一个条件向量。若要处理文本描述、空间布局等更复杂的条件,还需要考虑怎样保留条件内部的多个信息单元,以及它们与图像 token 怎样交互。原论文也将文本到图像作为后续可以探索的方向。

总结

DiT 的主要过程可以归纳为:

  • 将带噪 latent 切成 patch,并映射为带位置编码的 token;
  • 用 adaLN-Zero 将时间步和类别条件注入 Transformer,更新全部 token;
  • 将输出重新拼成噪声和方差参数,经过多步采样得到 latent,再用 VAE 解码成图像。

其核心是用一个接近标准 ViT 的结构完成条件去噪,并把扩展模型的途径分解为增加主干规模和增加 token 数量。

从这篇文章出发,可以继续读 Latent Diffusion,了解预训练 VAE 怎样建立这个连续图像空间;也可以回看 Improved DDPM / ADM 中的方差学习和条件归一化设计。之后再读使用 DiT 的工作,就可以重点追踪:它把什么对象做成了 token,条件怎样进入网络,以及训练目标和输出表示发生了什么变化。

参考