[论文速通]drifting-生成模型新范式
(本文自己写了草稿,格式和数学公式,以及部分逻辑错误由gpt辅助完成)
早就听说了 Drifting 的大名,组里的学长左 Drifting 右 Drifting 的。
终于,在回想起自己还是一个没毕业的硕士研究生之后,
想起来要拜读一下这篇文章。
好家伙,不读不知道,一读吓一跳,这篇文章居然是 2026 年提出的。
Kaiming He,终于是在生成模型里开宗立派了。
一步生成,还是牛的。
那就进入正题,介绍一下自己读 Drifting 的心路历程吧。
主要是脸滚键盘自己记录,如果能够帮到一些人理解 Drifting,那就更好了。
---
# 0. 写在前面:生成模型到底在干什么?
首先,什么是生成模型呢?
自从神经网络开始发展,人们就一直想让机器帮助人类产生内容:
画画、写作、生成声音,balabala。
写成数学语言,其实就是:
> **让一个简单分布,通过某种函数或者映射,变成我们想要的数据分布。**
比如从一个高斯噪声:
$$
\epsilon \sim p_\epsilon
$$
经过一个生成器:
$$
x=f(\epsilon)
$$
最终希望生成结果服从真实数据分布:
$$
q=f_{\#}p_\epsilon \approx p_{\text{data}}
$$
其中:
$$
f_{\#}p_\epsilon
$$
就是所谓的 **pushforward distribution,推前分布**。
人话来说:
> 一大堆噪声经过同一个函数 $f$ 之后,会形成一个新的分布 $q$。
> 生成模型的目标,就是想办法让 $q$ 长得和真实数据分布 $p_{\text{data}}$ 一样。
---
## 0.1 从“直接生成”开始
一种非常直观的生成思路就是:
**根据已经生成的内容,继续预测接下来的内容。**
比如图像里面:
知道前面的像素,然后预测后面的像素。
PixelRNN 就是这种自回归生成方法的典型代表。
这种思路很好理解,但是生成过程必须一个接一个地进行:
$$
x_1 \rightarrow x_2 \rightarrow x_3 \rightarrow \cdots
$$
效率自然不会特别高。
---
## 0.2 VAE:去一个更紧凑的空间里生成
后来出现了 VAE。
它引入了一个 latent space,也就是潜在空间。
大致来说:
$$
x
\xrightarrow{\text{Encoder}}
z
\xrightarrow{\text{Decoder}}
\hat{x}
$$
模型不一定非要直接在高维像素空间里面硬啃整个生成问题,而是可以先得到一个更加紧凑的 latent representation,再从 latent 中生成数据。
今天很多生成模型里的 VAE,实际上也主要承担一个 **tokenizer / 压缩器** 的角色:
$$
\text{Image}
\rightarrow
\text{Latent}
\rightarrow
\text{Image}
$$
---
## 0.3 GAN:既然不知道生成得好不好,那找个人来骂它
然后就是大名鼎鼎的 GAN,对抗生成网络。
GAN 的思路很有意思:
既然我们不知道该怎么直接评价生成器生成得好不好,
那就再训练一个判别器。
一个负责生成:
$$
G(z)
$$
一个负责判断真假:
$$
D(x)
$$
生成器想办法骗过判别器,判别器想办法识破生成器。
两个网络互相对抗:
> 你生成假的,我就把你揪出来;
> 那我就生成得更像真的;
> 那我就继续提高鉴别能力……
最终,生成器被逼着越来越接近真实数据分布。
GAN 非常巧妙地解决了一个问题:
> **怎么判断生成结果到底好不好?**
但是代价也很明显:
**两个网络一起训练,而且还是对抗训练。**
训练稳定性就成了一个大问题。
---
## 0.4 Diffusion:一步太难,那我走很多步
接下来进入 Diffusion 和 Flow Matching 的时代。
它们都面对一个非常现实的问题:
> 从一个完全随机的噪声,一步变成真实图片,实在太难学了。
既然一步太难:
那就分很多步。
首先是 Diffusion。
Diffusion 把生成过程看成一个逐步去噪的过程。
先人为设计一个加噪过程:
$$
x_0
\rightarrow
x_1
\rightarrow
x_2
\rightarrow
\cdots
\rightarrow
x_T
$$
最终把真实图片逐渐变成接近纯高斯噪声的东西。
然后反过来训练神经网络,让它学习:
$$
x_T
\rightarrow
x_{T-1}
\rightarrow
\cdots
\rightarrow
x_0
$$
于是生成的时候:
从一团噪声开始,
一点一点去噪,
最终生成一张图片。
但是——
**病来如山倒,病去如抽丝。**
加噪容易,去噪难。
想从纯噪声恢复出一张高质量图片,往往需要反复调用网络很多次。
---
## 0.5 Flow Matching:与其学去噪,不如直接告诉你往哪走
于是 Flow Matching 登场了。
Flow Matching 换了一个角度:
> 与其不断问“这里有多少噪声”,
> 不如直接告诉当前样本:“你现在应该往哪里移动”。
于是它学习一个速度场:
$$
\frac{dx_t}{dt}=v_\theta(x_t,t)
$$
其中:
$$
v_\theta(x_t,t)
$$
告诉当前位置 $x_t$:
**在当前时刻应该朝哪个方向移动。**
从而让整个分布逐渐从噪声分布流向真实数据分布:
$$
p_0
\rightarrow
p_t
\rightarrow
p_1
$$
但是标准 Flow Matching 在推理的时候,依然要通过 ODE Solver 反复调用神经网络:
$$
x_{t+\Delta t}
=
x_t
+
v_\theta(x_t,t)\Delta t
$$
也就是说:
虽然我们换了一种更加优雅的方式描述“分布怎么移动”,
**推理过程依然是多步的。**
于是就有了很多针对一步 / 少步生成的研究:
蒸馏、Consistency、增大步长、MeanFlow……
而 Drifting,也是在尝试解决这个问题。
不过它走了一条和 Diffusion / Flow Matching 很不一样的路。
---
# 1. Drifting 的直观理解
很多人,包括我,第一次看 Drifting 都是站在 Flow Matching 的基础上看的。
于是看到:
$$
V_{p,q}(x)
$$
再看到“drifting field,漂移场”几个字,
很容易条件反射:
> 哦,这是不是又一个 velocity field?
是不是又训练一个网络:
$$
V_\theta(x)
$$
告诉噪声下一步应该往哪里移动?
**其实完全不是。**
这是我第一次读这篇论文时最大的误区。
---
Drifting 真正训练的网络只有生成器:
$$
x=f_\theta(\epsilon)
$$
而漂移场:
$$
V_{p,q}(x)
$$
**不是训练出来的。**
它是根据:
- 真实数据分布 $p$
- 当前生成分布 $q$
**计算出来的。**
它的作用就是告诉当前生成样本:
> **你现在应该往哪个方向移动,才能让整个生成分布更接近真实分布。**
所以 Drifting 的核心流程其实非常简单:
$$
q_\theta
\rightarrow
V_{p,q_\theta}
\rightarrow
\text{Loss}
\rightarrow
\theta\text{ 更新}
\rightarrow
q_{\theta'}
$$
不断循环。
最终希望:
$$
q_\theta \approx p_{\text{data}}
$$
---
换句话说:
**Drifting 回到了生成模型最朴素的问题:拟合分布。**
Diffusion / Flow Matching 的思路是:
> 推理的时候,一步一步把噪声分布搬运到真实分布。
而 Drifting 的思路是:
> 反正训练神经网络本来就要 SGD 一步一步更新,那我干脆利用训练本身的迭代过程,让生成分布在训练阶段一步一步漂到真实分布。
最后训练完之后:
$$
\epsilon
\xrightarrow{f_\theta}
x
$$
一次前向传播结束。
**1-NFE。**
我觉得这是整篇论文最漂亮的地方。
---
# 2. Drifting 的核心推导
好了,人话说完了。
该直面数学了。
其实 Drifting 的数学本身并不算特别难,但是论文的叙述顺序很容易让第一次读的人绕进去。
所以这里我不完全按照论文的顺序,而是按照我自己理解它的顺序来讲。
---
## 2.1 首先,什么是漂移场 $V$?
神经网络训练本身就是一个不断更新参数的过程。
假设第 $i$ 次训练迭代的时候,网络是:
$$
f_i
$$
对于同一个噪声:
$$
\epsilon
$$
它生成:
$$
x_i=f_i(\epsilon)
$$
下一次参数更新以后,网络变成:
$$
f_{i+1}
$$
同一个噪声现在生成:
$$
x_{i+1}=f_{i+1}(\epsilon)
$$
所以两次训练迭代之间,生成样本自然会发生变化:
$$
x_{i+1}=x_i+\Delta x_i
$$
其中:
$$
\Delta x_i
=
f_{i+1}(\epsilon)-f_i(\epsilon)
$$
这个 $\Delta x_i$ 就是:
> **参数更新以后,当前生成样本实际发生了多少变化。**
---
Drifting 的核心想法来了:
既然训练神经网络的时候,本来就会产生:
$$
\Delta x_i
$$
那为什么不人为设计一个:
> **“正确的 $\Delta x$”**
来指导神经网络更新呢?
也就是说:
不要让生成样本瞎漂,
而是让它朝着有利于生成分布接近真实分布的方向漂。
于是定义漂移场:
$$
V_{p,q}(x)
$$
使得理想情况下:
$$
x_{i+1}
=
x_i+V_{p,q_i}(x_i)
$$
也就是说:
$$
\Delta x_i
\approx
V_{p,q_i}(x_i)
$$
这里一定要区分两个东西:
### 实际发生的变化
$$
\Delta x_i
=
f_{i+1}(\epsilon)-f_i(\epsilon)
$$
### 我们希望它发生的变化
$$
V_{p,q_i}(x_i)
$$
所以:
> **$V$ 可以理解成作者人为设计出来的“目标 $\Delta x$”。**
这一步搞明白以后,Drifting 基本就通了一半。
---
## 2.2 什么样的 $V$ 才算好?
我们最终希望:
$$
q=p
$$
也就是:
生成分布已经和真实分布完全一样。
这个时候显然就不应该继续移动了。
所以希望:
$$
q=p
\Rightarrow
V_{p,q}(x)=0
$$
论文进一步要求漂移场具有反对称性:
$$
V_{p,q}(x)
=
-V_{q,p}(x)
$$
这样当:
$$
p=q
$$
的时候:
$$
V_{p,p}(x)
=
-V_{p,p}(x)
$$
于是:
$$
V_{p,p}(x)=0
$$
非常漂亮。
但是这里有一个小坑:
论文只能严格保证:
$$
p=q
\Rightarrow
V=0
$$
反过来:
$$
V=0
\Rightarrow
p=q
$$
对于任意 $V$ 并不一定成立。
作者后面针对自己设计的 kernelized drifting field 给了一些理论上的条件和经验上的验证。
简单来说就是:
> **一般情况下,$V$ 越接近 0,生成分布越接近真实分布。**
但不能把它理解成无条件成立的数学等价关系。
---
# 3. $V$ 到底怎么算?
这么好的一个工具,该如何计算呢?
根据我们的惯性思维,第一反应可能是:
> 那再训练一个奇奇怪怪的网络,用它判断生成样本应该往哪移动?
类似 GAN:
再整一个判别器。
但是这样明显就复杂了。
本来想做一个简单的一步生成器,
结果又开始同时训练两个网络。
于是 Drifting 提出了一种非常有意思的办法:
> **不用额外训练一个网络,直接利用真实样本和生成样本计算 $V$。**
也就是:
**正样本吸,负样本推。**
---
## 3.1 先写一个最一般的形式
定义:
$$
V_{p,q}(x)
=
\mathbb{E}_{y^+\sim p}
\mathbb{E}_{y^-\sim q}
\left[
K(x,y^+,y^-)
\right]
$$
这里:
- $x$:当前需要计算漂移方向的生成样本
- $y^+$:从真实数据分布 $p$ 中采样的真实样本
- $y^-$:从当前生成分布 $q$ 中采样的生成样本
- $K(x,y^+,y^-)$:描述三个样本之间相互作用的函数
注意:
$$
y^-
$$
**不是上一次训练生成的样本。**
它只是当前生成分布:
$$
q
$$
中的一个负样本。
实际训练的时候,会一次生成一个 batch:
$$
x_1,x_2,\cdots,x_N
$$
这些生成样本本身就可以拿来作为:
$$
y^-
$$
所以工程上并没有额外再运行很多次网络。
---
前面有两个期望:
$$
\mathbb{E}_{y^+\sim p}
\mathbb{E}_{y^-\sim q}
$$
本质上可以理解成一个二重积分:
$$
V_{p,q}(x)
=
\iint
K(x,y^+,y^-)
p(y^+)q(y^-)
\,dy^+dy^-
$$
当然训练的时候不可能真去算这个积分。
实际做法就是:
> **采一批真实样本,再采一批生成样本,用 batch 平均去近似这个期望。**
也就是经典的 Monte Carlo 估计。
---
# 4. 引力与斥力
好了,最有意思的地方来了。
作者具体设计了两个场。
首先是真实数据产生的“吸引力”:
$$
V_p^+(x)
=
\frac{1}{Z_p(x)}
\mathbb{E}_{y^+\sim p}
\left[
k(x,y^+)(y^+-x)
\right]
$$
然后是生成数据产生的“排斥项”:
$$
V_q^-(x)
=
\frac{1}{Z_q(x)}
\mathbb{E}_{y^-\sim q}
\left[
k(x,y^-)(y^--x)
\right]
$$
其中:
$$
Z_p(x)
=
\mathbb{E}_{y^+\sim p}
[k(x,y^+)]
$$
以及:
$$
Z_q(x)
=
\mathbb{E}_{y^-\sim q}
[k(x,y^-)]
$$
用来做归一化。
然后最终定义:
$$
V_{p,q}(x)
=
V_p^+(x)-V_q^-(x)
$$
人话来说:
> **真实样本吸引 $x$,生成样本排斥 $x$。**
---
## 4.1 核函数是干什么的?
这里出现了一个:
$$
k(x,y)
$$
可以简单理解成:
> **衡量两个样本有多相似。**
论文采用:
$$
k(x,y)
=
\exp
\left(
-\frac{1}{\tau}
\|x-y\|_2
\right)
$$
其中:
$$
\|x-y\|_2
$$
就是欧氏距离。
当两个样本很接近:
$$
\|x-y\|\rightarrow 0
$$
那么:
$$
k(x,y)\rightarrow 1
$$
权重大。
如果两个样本离得特别远:
$$
\|x-y\|\rightarrow\infty
$$
那么:
$$
k(x,y)\rightarrow 0
$$
它对当前样本产生的影响就越来越小。
所以可以非常粗暴地理解成:
> **离我越近的人,说话声音越大。**
---
## 4.2 为什么最后会变成两个核乘一个方向?
前面的式子是:
$$
V_{p,q}(x)
=
V_p^+(x)-V_q^-(x)
$$
把它们展开以后:
$$
V_p^+(x)
=
\frac{
\mathbb{E}_{p}[k(x,y^+)y^+]
}{
Z_p
}
-x
$$
以及:
$$
V_q^-(x)
=
\frac{
\mathbb{E}_{q}[k(x,y^-)y^-]
}{
Z_q
}
-x
$$
两者相减:
$$
V_{p,q}(x)
=
V_p^+(x)-V_q^-(x)
$$
后面的两个:
$$
-x
$$
正好互相消掉。
于是:
$$
V_{p,q}(x)
=
\frac{
\mathbb{E}_{p}[k(x,y^+)y^+]
}{
Z_p
}
-
\frac{
\mathbb{E}_{q}[k(x,y^-)y^-]
}{
Z_q
}
$$
再把两个期望合成一个双重期望,得到:
$$
V_{p,q}(x)
=
\frac{1}{Z_pZ_q}
\mathbb{E}_{p,q}
\left[
k(x,y^+)
k(x,y^-)
(y^+-y^-)
\right]
$$
终于得到论文中的核心公式。
这个式子其实非常直观:
$$
\underbrace{k(x,y^+)}_{\text{x与真实样本的相似度}}
\cdot
\underbrace{k(x,y^-)}_{\text{x与生成样本的相似度}}
\cdot
\underbrace{(y^+-y^-)}_{\text{移动方向}}
$$
也就是说:
> **前两个核决定“推多大”,最后的 $y^+-y^-$ 决定“往哪推”。**
而且这个设计天然具有反对称性。
交换:
$$
p\leftrightarrow q
$$
等价于:
$$
y^+\leftrightarrow y^-
$$
两个 kernel 的乘积不变:
$$
k(x,y^+)k(x,y^-)
$$
但是:
$$
y^+-y^-
$$
会变成:
$$
y^--y^+
=
-(y^+-y^-)
$$
所以:
$$
V_{p,q}
=
-V_{q,p}
$$
刚好满足前面对漂移场的要求。
这里我觉得是论文数学设计里面非常漂亮的一笔。
---
# 5. Softmax:实际代码里面怎么做?
前面的归一化 kernel 可以写成:
$$
\tilde{k}(x,y)
=
\frac{1}{Z}k(x,y)
$$
实际工程里面,作者并不会手动计算这个 $Z$。
对于一个固定的 $x$,batch 里面有:
$$
y_1,y_2,\cdots,y_N
$$
先计算:
$$
l_j
=
-\frac{1}{\tau}
\|x-y_j\|
$$
然后直接做:
$$
\tilde{k}(x,y_j)
=
\operatorname{softmax}_j(l_j)
$$
也就是:
$$
\tilde{k}(x,y_j)
=
\frac{
\exp(-\|x-y_j\|/\tau)
}{
\sum_k
\exp(-\|x-y_k\|/\tau)
}
$$
这样所有 $y$ 对当前 $x$ 的权重加起来正好等于 1。
所以:
> **softmax 没有改变 kernel 的核心思想,只是顺手完成了归一化。**
论文还额外在 batch 中对 $x$ 这个维度再做了一次 softmax normalization。
实验发现会略微提高性能。
---
# 6. 有了 $V$,怎么训练生成器?
到这里我们终于把:
$$
V
$$
算出来了。
那么接下来:
**怎么用它训练生成器?**
这其实是整个 Drifting 最关键的最后一环。
当前生成器输出:
$$
x=f_\theta(\epsilon)
$$
漂移场告诉它:
你应该移动:
$$
V_{p,q_\theta}(x)
$$
所以自然可以构造一个目标:
$$
x_{\text{target}}
=
x+V_{p,q_\theta}(x)
$$
也就是说:
> 当前你生成的是 $x$,
> 但是根据真实分布和生成分布算出来,你下一步最好生成 $x+V$。
于是作者构造:
$$
\mathcal{L}
=
\mathbb{E}_{\epsilon}
\left[
\left\|
f_\theta(\epsilon)
-
\operatorname{stopgrad}
\left(
f_\theta(\epsilon)
+
V_{p,q_\theta}
(f_\theta(\epsilon))
\right)
\right\|_2^2
\right]
$$
乍一看有点吓人。
其实非常简单。
左边:
$$
f_\theta(\epsilon)
$$
是:
> **当前网络预测。**
右边:
$$
f_\theta(\epsilon)+V
$$
是:
> **当前网络应该追的目标。**
所以整个 loss 就是在做:
$$
x
\rightarrow
x+V
$$
---
## 6.1 为什么要 stop-gradient?
注意目标外面有一个:
$$
\operatorname{stopgrad}(\cdot)
$$
意思就是:
> 计算这个目标的时候可以正常算数值,但是反向传播的时候不要穿过它。
也就是说:
$$
x+V
$$
在这一轮训练里面被当成一个**冻结的 target**。
于是网络只需要:
> 修改自己的参数,让下一次输出更加靠近这个 target。
所以整个训练可以理解成:
$$
x_i
\rightarrow
x_i+V_{p,q_i}(x_i)
$$
参数更新以后,希望实际产生:
$$
\Delta x_i
=
f_{i+1}(\epsilon)-f_i(\epsilon)
$$
并且:
$$
\Delta x_i
\approx
V_{p,q_i}(x_i)
$$
到这里,前面所有东西终于闭环了。
---
## 6.2 Loss 不就是 $\|V\|^2$ 吗?
从数值上看:
$$
x-(x+V)=-V
$$
所以:
$$
\mathcal{L}
=
\mathbb{E}
\left[
\|V\|_2^2
\right]
$$
没错。
**loss 的数值确实等于漂移场的平方范数。**
但是有一个非常重要的细节:
因为:
$$
x+V
$$
被 stop-gradient 了,
所以反向传播并不是:
> 对 $\|V(\theta)\|^2$ 里面的 $V$ 求梯度。
而是:
> 把 $x+V$ 当成冻结的监督目标,只通过左边的 $f_\theta(\epsilon)$ 更新生成器。
所以 Drifting 并没有在训练 $V$。
再次强调:
> **$V$ 不训练。**
训练的是:
$$
f_\theta
$$
$V$ 只是:
> **告诉生成器这一步应该怎么改。**
---
# 7. 实际训练时发生了什么?
理论上我们写:
$$
y^+\sim p
$$
以及:
$$
y^-\sim q
$$
然后计算两个期望。
实际代码里面没有这么玄学。
每一步训练:
先采一批噪声:
$$
\epsilon_1,\epsilon_2,\cdots,\epsilon_N
$$
经过当前生成器:
$$
x_i=f_\theta(\epsilon_i)
$$
得到一个生成 batch:
$$
x_1,x_2,\cdots,x_N
$$
这些样本本身就拿来作为负样本:
$$
y^- = x
$$
然后从真实数据集里面再取一批:
$$
y_1^+,y_2^+,\cdots,y_{N_{\text{pos}}}^+
$$
接下来计算:
$$
V(x,y^+,y^-)
$$
再得到:
$$
x_{\text{drifted}}
=
\operatorname{stopgrad}(x+V)
$$
最后:
$$
\text{loss}
=
\operatorname{MSE}
(x,x_{\text{drifted}})
$$
然后正常反向传播。
所以整个训练流程可以压缩成:
```text
noise
↓
generator
↓
generated samples x
↓
和真实样本 y+、生成负样本 y- 一起计算 V
↓
x_target = stopgrad(x + V)
↓
MSE(x, x_target)
↓
更新 generator
```
就是这么简单。
---
# 8. 再回头看:Drifting 到底干了什么?
现在重新回头看整件事。
Diffusion / Flow Matching 做的是:
$$
x_0
\rightarrow
x_1
\rightarrow
x_2
\rightarrow
\cdots
\rightarrow
x_T
$$
它们把:
> **分布逐渐从噪声变成数据**
这件事情放在了**推理过程**里面。
所以生成一张图的时候,需要反复调用网络。
---
而 Drifting 突然换了一个角度:
神经网络训练本来就是:
$$
\theta_0
\rightarrow
\theta_1
\rightarrow
\theta_2
\rightarrow
\cdots
\rightarrow
\theta_T
$$
于是对应的生成分布自然也在发生:
$$
q_0
\rightarrow
q_1
\rightarrow
q_2
\rightarrow
\cdots
\rightarrow
q_T
$$
那为什么不直接利用这个过程?
通过漂移场 $V$,让:
$$
q_i
$$
每一次更新都朝:
$$
p_{\text{data}}
$$
移动。
最终训练完成:
$$
q_T
\approx
p_{\text{data}}
$$
于是推理的时候根本不需要再漂了。
直接:
$$
\epsilon
\xrightarrow{f_{\theta_T}}
x
$$
一次前向传播。
---
所以我现在对 Drifting 最核心的理解就是:
> **Diffusion / Flow Matching 在推理阶段不断移动样本;Drifting 则利用神经网络本来就存在的迭代训练过程,在训练阶段不断移动生成分布。**
或者再说得更粗暴一点:
> **FM:训练一个“怎么走”的网络,然后推理的时候真的一步一步走。**
> **Drifting:训练的时候告诉生成器每一步应该怎么改,最终把“怎么走”直接吸收到生成器参数里面。**
最终:
$$
f_{\#}p_\epsilon
\approx
p_{\text{data}}
$$
直接完成分布映射。
---
# 9. 最后总结
Drifting 的核心其实可以浓缩成三步。
### 第一步:承认训练本身就会让生成样本漂移
$$
\Delta x_i
=
f_{i+1}(\epsilon)-f_i(\epsilon)
$$
### 第二步:设计一个“正确的漂移方向”
$$
V_{p,q}(x)
$$
通过:
- 真实样本吸引
- 生成样本排斥
- kernel 衡量相似度
得到:
$$
V_{p,q}(x)
=
\frac{1}{Z_pZ_q}
\mathbb{E}_{p,q}
\left[
k(x,y^+)
k(x,y^-)
(y^+-y^-)
\right]
$$
### 第三步:用这个漂移方向监督生成器
$$
x_{\text{target}}
=
\operatorname{stopgrad}(x+V)
$$
然后:
$$
\mathcal L
=
\|x-x_{\text{target}}\|^2
$$
不断更新以后:
$$
q
\rightarrow
p_{\text{data}}
$$
最后获得:
$$
\epsilon
\xrightarrow{f_\theta}
x
$$
的一步生成器。
---
我觉得 Drifting 真正有意思的地方并不只是:
> “设计了一个新的 loss。”
而是它重新解释了**神经网络训练本身**。
传统 Diffusion / Flow Matching 认为:
> 分布演化发生在推理的时候。
Drifting 则说:
> **训练本身就是一个不断改变生成分布的迭代过程。**
既然如此,
干脆直接控制这个训练阶段的分布演化,
把推理阶段的多步过程省掉。
这大概就是我目前读完 Drifting 之后,对它最直观的理解。
至于论文后面的 feature space、latent generation、CFG、ImageNet 实现、DiT、各种 normalization……
那就是另一段故事了。
至少到这里,
Drifting 最核心的那根骨头,
应该算是啃明白了。

浙公网安备 33010602011771号