Method¶
这一页是长程知识,不随实验变。 概念用定义 + 公式 + 图固定; 会变的参数集中在最后一张表 —— 改了只动那一行,不动正文。
1 问题的形式化¶
CosyVoice3 的 flow-matching 解码器把高斯噪声积分成梅尔谱:
其中 \(x \in \mathbb{R}^{1\times 80\times K}\)。积分结果是 mel 而非波形,波形还要过 HiFT 声码器 (相位由声码器生成,不在 \(x_1\) 里)。
DFD (Dual-Forward Decomposition) 在同一个 \(x_t\) 上跑两遍 DiT,一遍喂情感参考、一遍喂中性参考:
\(\alpha\) 即情感强度旋钮。
\(A\) 是构造出来的,不是学出来的
训练里没有任何损失直接监督 \(A\)(见 §3)。\(A\) 只在推理时被构造。 这一点决定了很多现象 —— 比如 \(L_{\text{ortho}}\) 为何完全无效(见 05 Findings)。
2 架构¶
flowchart TB
subgraph LLM["LLM 通道 —— 情感的「源」"]
RT["参考文本"] --> L
TT["目标文本"] --> L
RA["参考音频<br/>→ prompt speech token"] --> L
L["LLM"] --> GT["gen_token<br/>长度 L_e"]
end
subgraph FLOW["Flow 通道 —— 情感的「闸门」"]
GT --> MU["μ (1,80,K)<br/>K = 2·L_e"]
RA2["参考音频 mel<br/>→ 前缀位置"] --> COND["cond"]
MU --> EST
COND --> EST
XT["共享状态 x_t"] --> EST["DiT estimator"]
EST --> VE["v_emo"]
EST --> VN["v_neu"]
VE --> A["A = v_emo − v_neu"]
VN --> A
A --> VC["v_ctrl = v_neu + α·A"]
end
VC --> INT["∫ dt → mel"] --> HIFT["HiFT → 波形"]
2.1 ICL 的输入结构¶
零样本推理里参考占据前缀位置:
token = cat([prompt_token, gen_token]) prompt 来自参考音频
cond = [参考的 mel | 生成段全零] 前缀有内容,生成段留空
spks = 说话人嵌入,逐帧广播
三条容易记错的事实:
prompt_text是参考的文本,不是目标文本 —— 参考与目标文本解耦, 因而可以固定一组参考、任意替换目标文本。- 输出要切掉前缀,只保留生成段。
- 各分支前缀可以不等长(各走各的,反正丢弃),但生成段必须等长才能逐帧混合。
2.2 张量形状与单位¶
| 量 | 形状 | 说明 |
|---|---|---|
| \(x, v, \mu, \text{cond}\) | \((1, 80, K)\) | 80 = mel 频带 |
| \(K\) | — | 帧数 @ 50 Hz (hop 480 @ 24 kHz),1 帧 = 20 ms |
| \(L\) | — | token 数 @ 25 Hz,1 token = 40 ms |
| 换算 | \(K = 2L\) | token_mel_ratio = 2 |
2.3 共享状态 ≠ 输出平均¶
所有分支在同一个 \(x_t\) 上求速度(类似 CFG),混合速度后只积分一次。 不是各自积分完再平均波形 —— 后者会重影。这也是 \(\alpha>1\) 外推有意义的原因: 在同一点上做方向外推。
3 训练目标¶
- 两个 FM 项各自完整、零截断,分别拟合情感样本与中性样本
- 没有交叉项 —— 因此等价于普通的单分支 flow-matching 微调
- \(\mathcal{L}_{\text{ortho}}\) 在 \(K_c = \min(K_{\text{emo}}, K_{\text{neu}})\) 上算 \(A\) 的跨通道余弦 —— 已证明完全无效(Findings F6)
4 量测¶
| 指标 | 模型 | 方向 | 用途 |
|---|---|---|---|
| 情感 | emotion2vec_plus_large | ↑ | 目标情感的概率 |
| CER | Paraformer-zh(标点归一化后) | ↓ | 字是否听得清 |
| SECS | campplus | ↑ | 音色相似度 |
| MOS | UTMOS22 strong | ↑ | 音质,<2.5 视为破音 |
派生量:
- mono = 相邻 \(\alpha\) 步里分数上升的比例,按 (key, 情感) 分组后平均。7 个 \(\alpha\) → 量化到 1/6 格点
- delta = \(\alpha{=}1\) 与 \(\alpha{=}0\) 的情感分之差
情感指标已被证明无法表达「部分情感」
emotion2vec 输出饱和的近 one-hot 分布,详见 Findings F5。 混合配方的情感分读不出结论。 这是当前的头号瓶颈。
5 方法论准则¶
从踩过的坑里提炼的可复用判断。事故经过留在实验页,这里只留原理。
5.1 分布跨在 1 两侧时,「统计量的函数」≠「函数的统计量」¶
截断率算错过两次(11% → 17% → 实测 12.4%)。错因是把中位比值代进截断公式, 而正确做法是逐对算截断再取中位。时长比中位 1.03 看着无害(情感有长有短、大致抵消), 但逐对截断中位有 12.4%、最坏 49.6%。
规则:比值类统计量,先逐样本算目标量,再聚合。
5.2 「跑起来了」不等于「跑对了」—— 要有落卡/落盘校验¶
--gpu 参数曾完全无效(deepspeed 在 import 期就初始化 CUDA),训练全落到物理卡 0,
挤到别人的任务上。症状是日志在跑但目标卡显存为 0。
规则:凡是「指定去哪」的参数,启动后必须验证它真的去了那里。
同类:评测报告 n_wavs=0 却退出码 0(读错了 manifest 文件)。
5.3 跨样本比较必须先解决对应关系¶
第一版跨句一致性测量是逐帧算余弦 —— 但第 \(k\) 帧在两句话里是不同音素, 即使 \(A\) 完全情感专一也测不出相关。改为子空间重叠(与时间对齐无关)才有意义。
规则:比较两个变长序列前,先问「第 k 个位置在两边是同一个东西吗」。
5.4 指标饱和时,低分读不出结论¶
一个真正成功的 50/50 混合本就不该在任一端点得高分。所以低分既可能意味着混合成功、 也可能意味着音频退化 —— 饱和的分类器无法区分这两者。
规则:用一个指标下结论前,先确认它在你关心的区间里有分辨率。
5.5 对照要能隔离单一变量,且要有「必然相同」的自检臂¶
六臂调色板里,纯情感配方在六臂逐条完全相同(单分支走恒等 warp,理应如此)。 这条「必然相同」的自检证明了所有差异确实来自混合配方,而非别的扰动。
规则:设计对照时留一个理论上必须相同的臂,它是整个对比有效性的证明。
5.6 n < 10 的数字只作线索,不写进结论¶
见 写作约定。定性结构通常稳,百分比数值在 n<30 时不可信。 本项目多数调色板实验 n=3 句,属弱证据。
5.7 观测到「没有结构」,不等于「不能施加结构」¶
M5 测出 \(A\) 的能量在前半/后半几乎无差异(比值 1.026),
我据此预测「前 K/2 vs 后 K/2」的分段 α 不会有效。M6 实测推翻了它 ——
half 档定位良好(比值 3.3)。
错在混淆观测与干预:前者问「\(A\) 天然在哪里强」,后者问「人为在某段施加能否只改那段」。 天然没有结构,不妨碍施加人工结构。
规则:从"分布长什么样"推不出"控制能不能施加"。想知道干预的效果,就得做干预。
5.8 接口「看起来一致」只说明最内层一致¶
M9 里 CosyVoice2 与 CosyVoice3 的 estimator 签名完全相同,我据此以为混合代码能原样跑。实际差异分三层,逐层才暴露: flow 外壳(token→μ 的路径不同)、声码器(参数表不同)、LLM prompt 约定。
规则:跨模型复用代码时,用目标模型自己的推理路径当参照逐层核对, 不能凭签名相同就假定行为相同。
6 参数与技巧¶
这一节会变。 上面是概念,这里是当前取值。
| 参数 | 当前值 | 为什么 | 变更历史 |
|---|---|---|---|
token_mel_ratio |
2 | 模型固有 | — |
| 采样率 / hop | 24 kHz / 480 | 模型固有 | — |
n_timesteps |
10 | Euler 步数 | — |
| 训练 lr / batch | 1e-5 / 2 | 与 v4 对齐 | — |
| \(\lambda_{\text{ortho}}\) | 0.01 | 沿用 v4 | 已证无效,保留仅为与 v4 可比 |
| 训练步数 | 53,700 (5 epoch) | 与 v4 对齐,便于消融 | — |
| \(\alpha\) 扫描网格 | 0, .25, .5, .75, 1, 1.25, 1.5 | 含外推段 | — |
| \(K^*\) 夹紧区间 | \([0.5\min K_e,\ 2\max K_e]\) | \(\alpha>1\) 时 \(w_{\text{neu}}<0\),\(K^*\) 会崩到 10 帧 | 2026-08-14 加入 |
| warp 平滑过渡 | 未实现 | 分段 \(\alpha\) 需要,否则速度场突变 | 见 OPEN |
| LLM 采样种子 | 按情感固定 | 采样噪声 1.288 会淹没时长曲线 | 2026-08-14 起 |
| 本项目可用 GPU | 卡 7 | 分配 | 2026-08-17 由卡 0–3 改为卡 7 |