One-Forcing: Towards Stable One-Step Autoregressive Video Generation

Paper: arXiv:2605.23458 Code: Aurora-edu/One-Forcing Code reference: main @ dc6dd2f6 (2026-05-25)

1. Motivation (研究动机)

现有实时/交互式视频生成正在从一次性生成整段视频的 bidirectional diffusion,转向按帧或按短块滚动生成的 autoregressive causal video generation。后者更适合 world simulation、游戏引擎和交互式系统,因为它可以一边接收上下文一边继续生成;但真正的端到端延迟仍然被每个 block 内的 denoising steps 支配。多数已有少步 causal video distillation 默认仍用 4-step sampling,一旦把 NFE 压到 1,视频质量、运动幅度和时序结构会明显退化。

论文指出两个具体瓶颈。第一,trajectory-style consistency distillation 需要学生一次跨过 teacher ODE trajectory 的高噪声非线性区域;Wan 视频 teacher 的 trajectory curvature 在 high-noise endpoint 附近高度集中,而 EDM2 ImageNet-512 这类图像 teacher 没有这么尖锐的弯折,因此图像的一步 consistency 成功经验不能直接搬到视频。第二,DMD / Self-Forcing 这类 distribution matching 方法虽然避开了整条 ODE trajectory,但 DMD 的 score-difference 信号本质上偏局部;在 autoregressive rollout 中,局部 frame/block 的小偏差会作为下一步上下文继续放大,最终表现为 blurry frames、动态不足或跨帧累积误差。

One-Forcing 要解决的目标很具体:在 causal autoregressive video generation 中,把每个 block 的采样预算压到 one step,同时保持视觉清晰度、动态程度和 prompt alignment。这个问题值得研究,是因为 one-step framewise rollout 如果稳定,就能把交互式视频生成的 latency bottleneck 从“每帧多次 diffusion denoise”降为“每帧一次模型调用”,并且让更长视频、更高帧率的 world model / game engine 具备可部署的实时性。

Figure 1 解读:同一组 prompt 下,Wan2.1 teacher 用 50 denoising steps,Causal Forcing、Self Forcing 和 One-Forcing 都是一阶段 one-step autoregressive sampling。图中作者想展示的不是单帧美观度,而是 one-step 下是否还能维持可见运动与清晰纹理:One-Forcing 的样例比已有 one-step causal baseline 更少模糊和静态化,直观对应论文要解决的“极限一步采样仍保持 dynamism”的问题。

2. Idea (核心思想)

核心洞察是:one-step 视频生成不应该只追随 teacher 的中间轨迹,也不能只依赖局部 DMD score;它需要一个直接面向真实视频分布的全局拒绝信号。 One-Forcing 因此保留 DMD 的 fake-score vs real-score 局部分布匹配梯度,同时在同一个 noised latent space 中加入 GAN-style adversarial branch,让当前 one-step generator 生成的 noised latent 必须和真实训练视频的 noised latent 区分不开。

关键创新可以概括为三点:一是用 trajectory-curvature analysis 解释 consistency distillation 在视频 one-step 下为何比图像更难;二是把 trainable fake-score transformer 复用为 score critic + discriminator backbone,只在若干层上接 register-token attention classifier;三是把 discriminator 的 real side 绑定到真实训练数据,而不是像 ASD 一样用另一个模型输出作为“real”,从而让 density-ratio gradient 在训练早期和后期都有非退化信号。

与 Self Forcing 的差别在于,Self Forcing 主要依赖 DMD-style score difference 来逼近 teacher distribution,容易在 autoregressive context 中积累局部误差;One-Forcing 额外加入真实数据驱动的 adversarial penalty。与 ASD 的差别在于,ASD 的 discriminator 比较的是 -step 与 -step model outputs,两边都是模型生成样本,logit gap 很快接近 0;One-Forcing 比较的是 generated latent 与 real data latent,判别器有真实分布锚点。

3. Method (方法)

3.1 Overall framework

One-Forcing 的训练对象包含三个模型角色:generator 是 one-step causal autoregressive video generator;fake-score network 是可训练 critic,用来估计 generated distribution 的 score,同时承载 adversarial discriminator head ;real-score network 是 frozen teacher score model,用于提供真实数据分布方向的 score reference。一次 rollout 得到 fake latent 后,DMD 分支在 noised fake latent 上计算 ,GAN 分支则把 noised fake latent 与 noised real latent 输入同一个 fake-score backbone 的分类头。

Figure 2 解读:左侧是 one-step causal rollout 产生 fake latent;中间的 DMD branch 用 trainable fake score 和 frozen real score 的差来给 generator 一个局部分布匹配方向;右侧 adversarial branch 把 fake latent 和真实训练数据 latent 都加噪到同一 timestep,再用共享 fake-score backbone 的判别头输出 real/fake logit。图中最重要的结构关系是:DMD 和 GAN 不是两个独立 critic,而是在同一个 noised latent feature space 中协同;DMD 负责“往 teacher distribution 的 score 方向推”,GAN 负责“若 fake rollout 已经偏离真实视频分布,就给出全局拒绝信号”。

直觉上,DMD 的优势是高效:它不要求学生显式回放完整 ODE trajectory,只需对当前 fake sample 的 score difference 求梯度;但它看到的是局部 infinitesimal direction。Autoregressive video 的风险恰好在于局部误差会滚入上下文,下一帧又基于带误差的上下文生成,因此单靠局部 score 很容易把视频推向平均化、模糊化的安全区域。GAN branch 提供的是“当前 rollout 是否像真实训练视频”的二分类压力,它不关心 teacher 中间路径,而是直接约束最终生成 latent 的整体分布;这也是为什么它能补足 DMD 的 locality。

3.2 Why consistency distillation fails in one-step video

Consistency distillation 的标准目标是让相邻 ODE step 的 endpoint prediction 一致: 如果 teacher trajectory 比较平滑,学生可以用很少步数近似它;但视频 teacher 的高噪声区域有明显曲率集中。论文用相对 trajectory curvature 度量:

Figure 3 解读:Wan video trajectory 的 curvature 峰值集中在高噪声端,意味着从 noise 到 data 的路径开头有强非线性弯折;EDM2 image trajectory 相对平缓。因此 two-step sampler 还可以在高曲率之后放一个中间 anchor,而 one-step sampler 必须一次跨过这段弯折。该图支撑了论文的第一个判断:one-step video 不适合只做 trajectory endpoint matching,而应转向直接 output distribution matching。

3.3 DMD branch: local score-difference distribution matching

DMD 把 generator distribution 与 data distribution 的 reverse KL 梯度写成: 实际训练中,对 one-step rollout 采样 timestep 和噪声 ,构造 ,在同一个 noised latent 上评估 trainable fake score 与 frozen real score 。论文给出的 stop-gradient DMD generator update 是: released code 中,model/dmd.pycompute_distribution_matching_loss 会先对 generated latent 加噪,再由 _compute_kl_grad 计算 pred_fake_image - pred_real_image。默认配置 dmd_grad_normalization: p_real_l1 不直接用 raw score difference,而是用 的 L1 均值归一化梯度,避免梯度尺度随 timestep 或视频内容剧烈变化。

3.4 Noised-latent adversarial branch

Adversarial branch 的输入也是 noised latent,而不是 RGB 视频。它从当前 generator 得到 fake latent ,从训练数据得到 real latent ,二者在同一 critic timestep 被加噪。判别器 接在 fake-score transformer 上:配置中使用 layers ,2 个 register tokens,1536 feature dimension,2048 FFN dimension,12 heads。每个 register token 对选定 transformer layer 的 latent tokens 做轻量 attention,得到 layer-wise critic feature,再拼接后进入 MLP head 输出 real/fake logit。

非饱和 GAN loss 为: 总目标是: 论文公式与 released code 实现差异:论文把 写在总目标里;代码在 model/one_forcing.py_compute_gan_generator_loss / _compute_gan_discriminator_loss 内部已经把 F.softplus(...) 乘上 gan_g_weight / gan_d_weight,随后 generator_loss = dmd_loss + gan_g_losscritic_loss = denoising_loss + gan_d_total_loss。二者数学上等价,但读代码时不要再额外乘一次权重。另一个实现细节是论文强调共享 fake-score backbone;released code 确实共享主干,但仍新增 _cls_pred_branch_gan_ca_blocks_register_tokens 这类小型判别头参数,不是完全“零新增参数”。

3.5 Training schedule and data flow

训练采用 interleaved schedule:每个 iteration 都更新 fake-score critic;每 个 iteration 额外更新一次 generator。critic 更新时,generator 在 torch.no_grad() 下产生 fake latent,fake-score network 学习 denoising objective,同时判别头学习 noised real vs noised fake;generator 更新时,先冻结 discriminator 参数,再对 generator 回传 DMD + adversarial generator loss。这样做的目的类似 DMD2 的 two-time-scale intuition:critic 需要比 generator 更频繁地追踪当前 generated distribution,否则 generator 会追随过时 score / discriminator signal。

代码侧流程与论文 Algorithm 1 对应:

import torch
import torch.nn.functional as F
 
 
def dmd_generator_loss(generator, fake_score, real_score, scheduler, cond, uncond, shape):
    x_fake, grad_mask, t_from, t_to = generator.one_step_rollout(shape, cond)
    t = sample_uniform_timestep(t_from=t_from, t_to=t_to, shift=5.0)
    noise = torch.randn_like(x_fake)
    x_noisy = scheduler.add_noise(x_fake, noise, t)
 
    with torch.no_grad():
        pred_fake = fake_score(x_noisy, cond, t)
        pred_real_cond = real_score(x_noisy, cond, t)
        pred_real_uncond = real_score(x_noisy, uncond, t)
        pred_real = pred_real_cond + 5.0 * (pred_real_cond - pred_real_uncond)
        grad = normalize(pred_fake - pred_real, reference=x_fake - pred_real)
        target = (x_fake.float() - grad.float()).detach()
 
    loss = 0.5 * ((x_fake.float() - target) ** 2)[grad_mask].mean()
    return loss, x_fake
def gan_generator_loss(discriminator, x_fake, x_real, cond, scheduler, weight=0.03):
    x_fake = crop_score_window(x_fake)
    t = sample_uniform_timestep(shift=5.0)
    x_fake_t = scheduler.add_noise(x_fake, torch.randn_like(x_fake), t)
    logit_fake = discriminator(x_fake_t, cond, t)
    return F.softplus(-logit_fake.float()).mean() * weight
def gan_discriminator_loss(discriminator, x_fake, x_real, cond, scheduler, weight=0.03):
    x_fake = crop_score_window(x_fake)
    x_real = match_real_latent_to_reference(x_real, x_fake)
    t = sample_uniform_timestep(shift=5.0)
    shared_noise = torch.randn_like(x_fake)
    x_fake_t = scheduler.add_noise(x_fake, shared_noise, t)
    x_real_t = scheduler.add_noise(x_real, shared_noise, t)
 
    logits = discriminator(torch.cat([x_fake_t, x_real_t]), cond.repeat_for_pair(), t.repeat(2))
    logit_fake, logit_real = logits.chunk(2, dim=0)
    return (F.softplus(-logit_real.float()).mean() + F.softplus(logit_fake.float()).mean()) * weight
def one_forcing_train_loop(trainer, dataloader):
    for step, batch in enumerate(dataloader):
        train_generator = (step % 5 == 0)
 
        if train_generator:
            trainer.freeze_discriminator_head()
            x_fake = trainer.generator.one_step_rollout(batch["prompts"])
            dmd_loss = trainer.compute_distribution_matching_loss(x_fake, batch)
            g_gan_loss = trainer.compute_gan_generator_loss(x_fake, batch["clean_latent"])
            (dmd_loss + g_gan_loss).backward()
            trainer.generator_optimizer.step()
            trainer.update_ema_after_step_50()
 
        with torch.no_grad():
            x_fake = trainer.generator.one_step_rollout(batch["prompts"])
        fake_score_loss = trainer.compute_fake_score_denoising_loss(x_fake, batch)
        d_gan_loss = trainer.compute_gan_discriminator_loss(x_fake, batch["clean_latent"])
        (fake_score_loss + d_gan_loss).backward()
        trainer.critic_optimizer.step()

3.6 Code-to-paper mapping

Code reference: main @ dc6dd2f6 (2026-05-25) — pseudocode and mapping based on this commit

Paper ConceptSource FileKey Class/Function
One-Forcing model wrappermodel/one_forcing.pyOneForcing
DMD score-difference lossmodel/dmd.pycompute_distribution_matching_loss, _compute_kl_grad
GAN generator lossmodel/one_forcing.py_compute_gan_generator_loss, generator_loss
GAN discriminator / critic lossmodel/one_forcing.py_compute_gan_discriminator_loss, critic_loss, discriminator_loss
noised latent constructionmodel/one_forcing.py, model/dmd.py_prepare_noisy_latent, scheduler add_noise
register-token discriminator headmodel/one_forcing.py, wan/modules/model.pyadding_cls_branch, _gan_ca_blocks, _register_tokens
update scheduletrainer/one_forcing.pyfwdbwd_one_step, train
framewise training configconfig.yamlnum_frame_per_block: 1, max_steps: 200, gan_feature_layers: [21,29]
launch commandREADME.mdtorchrun --nproc_per_node=8 train.py --config_path config.yaml ...

4. Experimental Setup (实验设置)

4.1 Datasets and prompts

训练阶段使用预计算 latent 数据。论文说每个样本包含 text prompt 与对应 real data sample,distillation 时不重新 decode/load raw videos;released code 的 trainer/one_forcing.py 使用 CleanLatentLMDBDataset(config.data_path),README 训练命令把 --data_path 指向 mixkit_latents_lmdb,HuggingFace 资源中也提供 clean_data/*。训练数据的样本总量论文未详细说明,代码配置也没有给出固定 count;因此只能确定它是 prompt + clean latent/real data 的 LMDB-style 训练集,而不能从论文中可靠写出样本数。

评估使用 VBench。主表报告 official VBench 的 Total / Quality / Semantic 三个聚合分数;附录雷达图进一步展开 16 个 VBench dimensions。Human study 从 VBench prompt set 中抽取 50 个 prompt,按 11 个 primary dimensions 分层,每个 prompt 对三个 baseline 各生成一组 A/B 对比,由 3 名 annotators 独立投票,最多 votes。

4.2 Baselines and metrics

主结果比较了 many-step 与 one-step 两组方法:MAGI-1、Wan2.1、SkyReels-V2、NOVA、LTX-Video、Pyramid Flow、CausVid、Self Forcing 4-step,以及 Self Forcing 1-step、Causal-Forcing 1-step、ASD 1-step、One-Forcing chunkwise / framewise 1-step。VBench metrics 中 Total 是总分,Quality 偏低层视觉质量与动态/时序质量,Semantic 偏 prompt 对齐和语义一致性;论文还单独关注 Dynamic degree,因为它最能反映 one-step 视频是否退化成“清晰但静态”。Human study 的 win rate 是去除 tie 后,One-Forcing 在 decided votes 中被偏好的比例。

4.3 Training config

训练配置来自 released code 的 config.yaml 与 README launch command,而不是默认配置推测:

  • Model / initialization:generator 从 checkpoints/framewise/causal_ode.pt 初始化;teacher / real score 为 wan_models/Wan2.1-T2V-14B;fake score 为 Wan2.1-T2V-1.3B;generator / fake-score 主体为 1.3B 规模。
  • Video latent shapeimage_or_video_shape = [1, 21, 16, 60, 104],即 21 latent frames、16 latent channels、 latent spatial size,对应 generation。
  • Optimizationtorchrun --nproc_per_node=8 train.py --config_path config.yaml;batch size 1/GPU × 8 GPUs;AdamW,、weight decay 0.01;generator LR 和 critic LR 都是
  • Denoising / guidance:1000 training timesteps;flow denoising loss;timestep shift 5.0;generator 和 real-score CFG guidance scale 5.0,fake-score CFG 为 0.0。
  • GAN branch:non-relativistic discriminator(relativistic_discriminator: false);layers ;2 registers;feature dim 1536;FFN dim 2048;12 heads;;R1/R2 regularization 权重为 0。
  • Systems / schedule:mixed precision、FSDP full sharding、gradient checkpointing、generator activation CPU offload;dfake_gen_update_ratio: 5,即每 5 个 iteration 更新一次 generator;max_steps: 200;EMA decay 0.99,从 step 50 开始。

5. Experimental Results (实验结果)

5.1 Main VBench results

ModelNFETotalQualitySemantic
MAGI-16479.1882.0467.74
Wan2.15084.2685.3080.09
SkyReels-V23082.6784.7074.53
NOVA2580.1280.3979.05
LTX-Video2080.0082.3070.79
Pyramid Flow2081.7284.7469.62
CausVid481.1884.4168.30
Self Forcing483.4684.7778.24
Self Forcing177.1879.4068.34
Causal-Forcing178.3980.6769.25
ASD79.1281.3570.19
Ours (chunkwise)81.6083.6573.41
Ours (framewise)83.7685.2277.91

One-Forcing framewise 的 VBench Total 为 83.76,比 Self Forcing 1-step 高 6.58 分,比 Causal-Forcing 1-step 高 5.37 分,比 ASD 高 4.64 分;Quality 85.22 几乎追平 50-step Wan2.1 的 85.30,Semantic 77.91 也明显高于 prior one-step methods。更关键的是,它以 1 NFE 超过 CausVid 4-step、Pyramid Flow 20-step、LTX-Video 20-step、NOVA 25-step,并接近 Self Forcing 4-step 的总分 83.46。

Figure 4 解读:雷达图显示 One-Forcing 的优势不是只来自某个聚合维度;相对 ASD、Causal-Forcing 和 one-step Self Forcing,它在 object、spatial relationship、scene、dynamic degree 等维度上更强,同时保持较好的 temporal smoothness。相对 4-step Self Forcing,One-Forcing 的 normalized total / quality 更高,dynamic degree 更好,但在 color、imaging quality 和部分 consistency-style 维度仍略低,这解释了为什么它接近但没有全面超过 50-step teacher。

5.2 Human study

BaselineNFEOurs winsBaseline winsTotal decidedWin rate
Self Forcing 1-step11301714788.4%
ASD11391115092.7%
Self Forcing 4-step43211815021.3%

Human study 与 VBench 的结论一致但更直观:对 one-step baselines,One-Forcing 在人工偏好中压倒性胜出,说明它改善的不是只被 VBench 捕捉的数值指标,而是人眼可感知的运动、清晰度和整体质量。不过与 4-step Self Forcing 对比时,One-Forcing 只有 21.3% win rate,说明 one-step latency 的收益仍伴随感知质量上限;论文的定位不是完全替代多步强模型,而是在 one-step 极限下显著抬高下限。

5.3 Ablation and stability analysis

ConfigurationQualitySemanticTotalDynamic degree
Ours (Framewise causal init)85.2277.9183.7652.76
Ours (Framewise CD init)82.8280.5082.3623.61

Ablation 的重点是初始化与 objective 是否匹配。Framewise causal init 的 Dynamic degree 为 52.76,而 Framewise CD init 只有 23.61;后者 Semantic 更高到 80.50,但动态几乎被压扁,说明 consistency-style 初始化/约束可能把模型推向更保守、更静态的解。论文还讨论了 forward-KL regularization 的 squared-error surrogate:在 one-step setting 中它和 One-Forcing 的 distributional objective 不对齐,会把 total score 降到 74.83、dynamic degree 降到 1.30,相对 chunkwise baseline 81.60 掉近 7 分,动态几乎消失。

Figure 5 解读:该图比较 discriminator logit gap 。One-Forcing 的 gap 均值 、标准差 ,说明 real/fake latent 的分布距离足够大且随 generator 改善而动态变化;ASD 的 gap 几乎从一开始就贴近 0(),判别器没有可学习信号。这个结果直接支持 One-Forcing 对“real data as discriminator target”的设计选择。

Figure 6 解读:前 100 steps 的 loss curves 进一步解释训练动态。DMD loss 初值量级相近,但 One-Forcing 更稳定;generator GAN loss 在 One-Forcing 中持续变化,说明 discriminator 仍在提供有效梯度,而 ASD 的 GAN loss 基本固定在 ;critic 与 discriminator loss 也显示 One-Forcing 的判别器在逐步学会区分 real/fake,而 ASD 的判别器近似 collapsed。

5.4 Conclusions and limitations

论文的主要结论是:在 causal video generation 中,one-step 不是单纯把 4-step sampler 少跑几步,而需要重新设计 distillation objective。One-Forcing 用 DMD 处理局部 score matching,用真实数据驱动的 noised-latent GAN 处理 autoregressive rollout 的全局分布偏移,因此 framewise one-step 训练能在 200 iterations 内收敛,并以约 chunkwise 训练三分之一的成本达到更高 VBench quality。

限制也很明确。One-Forcing 需要 real data 作为 discriminator 的 real distribution,因此不同于 Self Forcing 和 ASD 这类更偏 data-free / self-distillation 的方法;如果训练视频或其 latent representations 不可得,方法适用性会下降。作者的未来方向包括扩展到更高分辨率、更长时长、更大 backbone(例如 14B 参数),结合 efficient attention / long video frameworks,并探索 adaptive step scheduling:对感知复杂片段动态分配更多 denoising steps,以在 one-step latency 和质量之间取得更好的折中。社会影响方面,论文指出高质量视频生成可能被用于误导媒体、冒充个人或放大偏见,部署时需要数据与 prompt filtering、provenance tracking、watermarking/content credentials、synthetic-media detection 和敏感场景政策约束。