从扩散模型到 Flow Matching —— ZipVoice 凭什么用 4 步生成语音
当 Stable Diffusion 还在跑 50 步采样时,ZipVoice 已经做到了 4 步出语音。这背后的算法演进,比看上去要直观得多。
引言
熟悉文生图的开发者都知道一个事实:生成一张高质量图片需要几十次去噪迭代。从 DDPM 论文里的 1000 步,到后来 DDIM 的 50 步、100 步,再到 LCM、Turbo 模型的 1-4 步,扩散模型的"提速"一直是研究热点。
但当读者第一次接触 ZipVoice 的源码时,一个数字会让人眼前一亮:
num_steps = 4
不是优化版、不是蒸馏版、不是某种特殊配置——这就是论文推荐的默认值。一个 Flow Matching 架构的 TTS 模型,4 步迭代生成 8 秒语音。
读者难免会问:
- Flow Matching 和扩散模型是什么关系?
- 为什么只要 4 步?多步质量不会更好吗?
numSteps这个参数到底改变了什么?为什么改成 2 质量就变差?- 训练时是怎么学会"4 步等效原本几十步"的?
本文尝试用尽可能少的数学语言,把这些问题讲清楚。需要读者对扩散模型有基础印象——知道它是"加噪-去噪"的过程就够了。
一、回顾:扩散模型在做什么
扩散模型的核心思想,用一句话概括:把"无中生有"的难题,变成"逐步修正"的简单题。
具体来说,分两个阶段:
前向过程(训练用):拿一张真实图片 x₀,逐步往里加高斯噪声,加 1000 步后图片完全变成纯噪声 x_T。
x₀ (真实图片) → x₁ → x₂ → ... → x_T (纯噪声)
加噪 加噪 加噪
反向过程(推理用):从纯噪声 x_T 出发,逐步去噪,最终还原一张图片。每一步都让网络预测"这一步应该减掉多少噪声"。
x_T (纯噪声) → x_{T-1} → ... → x₁ → x₀ (生成图)
去噪 去噪 去噪
这里的关键认知是:训练时网络学的不是"如何画一张图",而是"在加噪过程中的任意位置,原始图片是什么样"。推理时,沿着反向链一步步问网络"再去一点点噪声后应该是什么样",最终就能从噪声还原出图。
为什么需要这么多步?因为每一步去掉的噪声很少,模型预测的目标比较接近输入,难度低,预测准。如果一步去太多噪声,相当于让模型从"几乎全是噪声"直接预测"几乎全是图片",难度太大,预测会偏。
所以步数越多,每步的目标越温和,质量越好;但步数越多,推理越慢。这是扩散模型的核心权衡。
二、扩散模型的几何视角:在概率空间中走路
把上面的过程换一个数学语言。
数据空间(图片空间)里有两个分布:
- 真实数据分布 p_data:所有可能的真实图片在这个分布里
- 噪声分布 p_noise:所有可能的纯噪声图(即标准高斯分布)
扩散模型本质上在学习一条从 p_noise 到 p_data 的路径。
p_noise p_data
●────────────────────────────────→●
x_T x_{T-1} x_{T-2} x₁ x₀
每一步都向 p_data 靠近一点
DDPM 的路径很曲折——每一步是带随机性的小跳跃(SDE,随机微分方程)。DDIM 把它"拉直"了——变成确定性的小跳跃(ODE,常微分方程),同样的起点和路径会得到同样的终点。
DDIM 是扩散模型走向"少步生成"的关键一步。一旦确定了路径是 ODE 而不是 SDE,就可以用更少的采样点近似这条路径。
三、Flow Matching 登场:直接学路径本身
DDIM 已经把扩散过程变成了 ODE,但训练目标依然是"预测加进来的噪声",间接地定义了 ODE 的形状。
Flow Matching(流匹配)做了一个更直接的事情:让模型直接学习这条路径上每一点的"运动方向"。
类比一下:
- 扩散模型说:“这是图片,这是噪声,路径在中间。给我一个中间点,告诉我现在的位置离图片有多远。”
- Flow Matching 说:“这是图片,这是噪声,路径在中间。给我一个中间点,告诉我此刻应该往哪走。”
数学上,Flow Matching 的训练目标是直接拟合一个速度场 v(x, t):
对路径上每一点 (x, t):
v(x, t) = 在此点的瞬时速度
推理时:
从 x_0 (噪声) 出发
按 dx/dt = v(x, t) 求解 ODE
到 t=1 时得到生成结果
如果路径设计得好(比如 Rectified Flow 用直线连接 p_noise 和 p_data 的对应点),那么这个 ODE 的解可以用很少的步数近似得到。这就是 Flow Matching 能做到少步生成的根源。
四、什么叫"路径设计得好"
一条路径走起来快不快,取决于它有多直。
情况 A:曲折山路 情况 B:直线公路
起点 起点
↓ ↓
● ●
╲ ╲
●─╮ ╲
╲ ╲
╭──● ● 终点
╱
●
终点
A 这种曲折路径必须用很多小步才能跟上每个转弯。B 这种直线路径可以一步从头跨到尾。
DDPM 学到的路径是 A:因为前向过程加了 1000 步小噪声,每步都是小幅度的转向,整条路径弯弯曲曲。
Rectified Flow 学到的路径是 B:训练时直接强制路径是直线(噪声点和图片点用直线连接),所以推理时少几步也能保持精度。
ZipVoice 用的就是 Rectified Flow 思想。它的理论速度场满足:
v(x, t) = (x_target - x_noise)
也就是说,每一点的速度都指向同一个方向。理论上,1 步就能从噪声到达目标:
x_target = x_noise + v × 1.0
但实际中由于:
- 速度场是用神经网络近似的,存在误差
- 1 步迈得太大会被误差放大
所以推荐用 4 步,每步走一段,让误差有机会被后面的步骤修正。
五、numSteps 改变了什么
读到这里,应该可以回答 numSteps 这个参数的含义了。
它决定了 ODE 数值积分的步长。
# numSteps = 4 时
t_values = [0, 0.143, 0.333, 0.6, 1.0] # 5 个点
# 步长 = [0.143, 0.190, 0.267, 0.4]
# 4 次前向,每次走一段
# numSteps = 2 时
t_values = [0, 0.333, 1.0] # 3 个点
# 步长 = [0.333, 0.667]
# 2 次前向,每次走更大一段
# numSteps = 1 时
t_values = [0, 1.0]
# 步长 = [1.0]
# 1 次前向,一步到位
t_values 不是均匀的,因为 ZipVoice 用了一个 t_shift = 0.5 的非线性时间映射:
def get_t(i, num_steps, t_shift=0.5):
raw_t = i / num_steps
return t_shift * raw_t / (1.0 + (t_shift - 1.0) * raw_t)
这个映射让前几步在 t 较小处更密集,后几步在 t 较大处稀疏。原因是 Flow Matching 的速度场在不同 t 值处变化幅度不同——靠近噪声端(t=0)变化剧烈,需要更密的采样;靠近目标端(t=1)变化平稳,可以稀疏采样。
实际工程经验:
- numSteps = 1:速度场误差被放大成 1 倍,质量明显下降,几乎不可用
- numSteps = 2:质量勉强可接受,速度提升一倍
- numSteps = 4:质量与稳定性的最佳平衡点(论文推荐)
- numSteps = 8 或更多:边际收益小,速度变慢
笔者实测,从 4 改到 2 后,合成出来的语音字数对得上但音色明显失真,发音不连贯。从 4 改到 1 直接变成不可识别的乱码。这印证了 Flow Matching 不是真的能"任意减步",而是在训练时已经为某个特定步数(通常是 4-8)做了优化。
六、ZipVoice 的"蒸馏"是怎么回事
ZipVoice 的发布版本叫做 zipvoice-distill,distill 就是蒸馏的意思。
完整的训练过程是:
第一阶段:训练标准 Flow Matching 模型。这个模型需要 16-32 步推理,质量好但慢。
第二阶段:蒸馏到 4 步。用第一阶段的模型作为"老师",训练一个新模型作为"学生"。学生的目标是:用 4 步推理产生与老师 16-32 步推理相同的结果。
蒸馏的具体做法(简化描述):
对每个训练样本:
用老师模型跑 32 步生成 mel_teacher
用学生模型跑 4 步生成 mel_student
损失 = ||mel_teacher - mel_student||²
反向传播更新学生
蒸馏完成后的学生模型,速度场被调整成"4 步走完正好等于老师 32 步的效果"。这就是为什么蒸馏版可以稳定地用 4 步推理。
关键认知:蒸馏后的模型不能直接用于其他步数。如果用 zipvoice-distill 跑 8 步,质量并不会比 4 步更好——因为模型的速度场已经为 4 步做了优化,再多走步数反而可能"过冲"。
读者在调试时如果发现增加 numSteps 没有改善音质,原因就在这里。
七、和图像扩散的对比
读者可能会想,为什么 Stable Diffusion XL Turbo 才把图像生成压到 1-4 步,而 ZipVoice 一开始就用 4 步?
几个原因:
第一,音频比图像简单。一张 1024×1024 图片有 100 万像素,而 8 秒音频的 mel 只有 1136×100 = 11.4 万个值。生成空间小一个数量级,模型容量需求小,Flow Matching 学起来更容易。
第二,TTS 的随机性低。给定文本和参考音频,理想的 mel 输出应该是相对确定的(音色、节奏由输入决定)。而文生图给一个 prompt,可以画出无数张合理的图。低随机性的任务更适合 Flow Matching 这种确定性 ODE 路径。
第三,TTS 模型小。ZipVoice 的 decoder 只有约 100 MB(FP32),而 SDXL 的 UNet 有 6.5 GB。小模型每步推理快,加上少步数,端到端就能做到接近实时。
但这并不意味着所有音频生成任务都能用 4 步。比如音乐生成、语音变声等更复杂的任务,仍然需要更多步数。Flow Matching 的"少步"优势依赖于:路径设计(直线性)、模型容量(足够拟合)、任务确定性(输入约束充分)。
八、工程上的取舍
理解了 Flow Matching 后,从工程角度看 ZipVoice,可以总结出几个权衡:
速度 vs 质量:4 步是平衡点。少于 4 步质量崩溃,多于 4 步意义不大。
模型大小 vs 推理速度:蒸馏版只有 100MB,全量版可能更大。FP32 vs INT8 也是一个量化精度与速度的权衡。
通用性 vs 专用性:蒸馏版只能 4 步,不能在推理时灵活调步数。如果想自适应(弱网络环境用 2 步、强算力用 8 步),就要保留全量版本,但失去蒸馏带来的速度优势。
Decoder 推理 vs 端到端时间:在中低端 ARM 芯片上,Decoder 4 步推理仍然要 50+ 秒,是端到端瓶颈。哪怕优化了步数,单步时间不降下来也没用。这就是为什么在端侧场景下,硬件加速(FP16、INT8 dot product 指令、专用 NPU)比算法优化更重要。
九、结语
Flow Matching 在 ZipVoice 上的成功表明,扩散类生成模型在算法层面已经接近"实时可用"。从 1000 步到 4 步,量级的飞跃发生在过去三年内,速度仍在加快。
但这套技术能不能在端侧普及,仍然取决于硬件。在最新的旗舰移动芯片(骁龙 8 Gen3、麒麟 9020、苹果 A17 Pro 等)上,Decoder 单步推理已经能压到几秒甚至秒级。配合 4 步的 Flow Matching,端侧 8 秒语音的合成时间可以做到 10-15 秒——已经接近"用户可以容忍的等待"门槛。
下一个突破点可能是:
- 进一步蒸馏到 1-2 步:让模型在保证质量的前提下减少步数
- 更好的硬件支持:ARM SME2 指令集、各家手机的 NPU 加速
- 流式推理:边生成边播放,让用户感知不到等待
现在做端侧 TTS 还需要在产品层面做妥协(比如限制文本长度),但相信再过一两代芯片,端侧实时声音克隆就会变成标配能力。
附:相关阅读
- ZipVoice 论文:arXiv:2506.13053
- Rectified Flow 论文:arXiv:2209.03003
- Flow Matching for Generative Modeling:arXiv:2210.02747
- DDIM 论文:arXiv:2010.02502
- Stable Diffusion Turbo:Adversarial Diffusion Distillation
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)