M7 · 把 α 搬到情感 embedding 上¶
| 状态 | ✅ 成立 |
| 日期 | 2026-08-18 |
| 一句话 | embedding 层的 α 插值同样平滑、外推也不崩,但时长响应只有速度场层的 1/10 |
| 上游 | ← 用户澄清:M7 要问的是这件事(前一轮问错了题,结果改编号为 M9) |
| 下游 | → 判断我们的贡献是「新的控制量」还是「新的控制层级」 |
1 动机¶
我们的 α 作用在速度场上,那是 flow-matching 特有的位置。 但很多 instruct TTS 把情感编码成一个显式的全局向量,那里同样能放 α。
这个方法搬过去会怎样? —— 本实验只回答这一个问题。
2 方法原理¶
2.1 这类模型的情感是怎么进去的¶
有显式情感 embedding 的 TTS,结构大致是:
flowchart LR
P["情感提示<br/>「悲伤」"] --> ENC["提示编码器"] --> E["e ∈ ℝᵈ<br/>情感向量"]
T["目标文本"] --> TE["文本编码器"] --> H["h"]
E --> CAT["拼接 / 调制"]
H --> CAT --> AM["声学模型"] --> MEL["mel"] --> V["声码器"] --> W["波形"]
关键是 e 是一个全局向量:整句话共用同一个 \(e\),不随时间变化。
2.2 α 插在哪¶
与我们的做法完全同构,只是换了层级:
- \(\alpha=0\) → 中性
- \(\alpha=1\) → 该模型原本的情感输出
- \(\alpha>1\) → 外推(超出它训练见过的范围)
2.3 具体怎么做(四步)¶
1. 用「中性」提示跑一遍,在提示编码器输出处 hook 出 e_neu
2. 用「悲伤」提示跑一遍,同一位置 hook 出 e_emo
3. 算 e_ctrl = e_neu + α(e_emo − e_neu),**替换**回该位置
4. 让推理照常走完 → mel → 波形;扫一遍 α
只改一个张量,模型权重与其余推理路径一律不动 —— 与我们在 CosyVoice3 上的做法一致。
2.4 两个层级的本质差别¶
| 我们(速度场) | 本实验(情感 embedding) | |
|---|---|---|
| 形状 | \(80 \times K\),逐帧 | \(d\) 维,全句一个 |
| 能否只改句首 | 能(M6 定位比 42.3) | 结构上做不到 |
| 时长 | 随 α 连续变(F2) | 由时长预测器决定,不随 α 变 |
这两条差别是结构性的,不用做实验也知道。 本实验要看的是: 在 embedding 层做插值,输出到底怎么变 —— 平滑吗?外推崩不崩?情感真的变了吗?
3 设计¶
| 自变量 | α ∈ {0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5} |
| 控制量 | 同目标文本、同情感类别、同种子;只改 \(e\) 这一个张量 |
| 对照 | 该模型自己的 α=0 与 α=1;横向参照我们的 α 阶梯 |
| 判据 | 逐档 F0 / 能量 / 时长 / UTMOS 随 α 怎么走。不经过 emotion2vec |
| n | 12 句 × 4 情感 × 7 α |
模型怎么选¶
本实验要求模型满足三条,缺一不可:
- 有可定位的显式情感向量 —— 能 hook 出来、能替换回去
- 支持中文 —— 否则与我们的 ESD 中文数据不可比
- 权重可下载 —— 能在本机跑
按这三条筛下来:
| 模型 | 情感怎么表示 | 中文 | 判断 |
|---|---|---|---|
| InstructTTS(Yang et al.) | 自然语言风格提示 → 跨模态对齐的 style embedding | ✅ | ❌ 概念上最贴题,但权重未公开 —— HF / ModelScope 均无官方发布,NLSpeech 数据集也未放出 |
| OV-InstructTTS | 名字相近,实为基于 Step-Audio 2 的 LLM 架构 | ✅ | ⚠️ 与原版 InstructTTS 不是一回事;LLM 式模型的情感多在 token 空间,是否存在独立可插值向量需验证。下载量 11,可作 EmotiVoice 失败后的备选 |
| EmotiVoice | 情感提示 → 编码器 → 风格/情感向量 | ✅ | 首选 —— 三条都满足 |
| Parler-TTS | 自然语言描述 → T5 描述向量 | 多语版存疑 | ⚠️ 描述向量把情感、音色、语速、录音环境混在一起,插值等于同时动四样,拆不出纯情感分量 |
| StyleTTS2 | 扩散采样的 style 向量 | ❌ 仅英文 | ❌ 语种不匹配;且 style 同样混着音色 |
| CosyVoice instruct | 没有独立向量 —— 情感在指令文本里 | ✅ | ❌ 没有可插值的对象。这条路已由 M8 单独做过 |
| F5-TTS / GPT-SoVITS | 靠参考音频,无显式情感 embedding | ✅ | ❌ 情感与音色纠缠在同一个参考里,无法只动情感 |
⚠️ 表中的架构描述来自各模型的公开说明,内部是否真有一个可替换的纯情感向量尚未验证 —— 这正是 §4 步骤 0 要做的事。若 EmotiVoice 不通过,依次退到 OV-InstructTTS(需先确认有无独立向量)、 再退到 Parler-TTS(并在报告里写明"描述向量混杂"这一口径损失)。
为什么不干脆多测几个:本实验只想知道「这个方法搬过去是什么响应」, 一个满足三条的模型就够回答。多测几个只会引入更多不可比的基座差异 (见方法论 §5.8),不会让结论更强。
4 运行(计划)¶
步骤 0 — 可行性验证(先做,不通过就换模型)
找到那个情感向量,并确认插值后输出确实变化。若插值后输出几乎不动, 说明它不是有效的控制点,本实验不成立 —— 这是唯一的硬门槛。
步骤 1 12 句 × 4 情感 × 7 α,卡 7
5 结果¶
模型:EmotiVoice(说话人 8051,16 kHz)。336 条 = 12 句 × 4 情感 × 7 个 α,127 秒跑完,0 报错。
步骤 0 —— 硬门槛通过¶
style_embedding 是 768 维、由 inputs_style_embedding 独立传参的干净向量,
可 hook、可替换。插值后输出确实变化(波形相对 α=0 的差异 0 → 1.4)。
定量(n=48 条语句,跨语句中位数)¶
| α | Δ时长 /s | |ΔF0| /Hz | |Δ能量| /dB | |Δ谱倾斜| /dB |
|---|---|---|---|---|
| 0.25 | −0.02 | 4.3 | 0.13 | 0.21 |
| 0.50 | −0.01 | 7.8 | 0.32 | 0.44 |
| 0.75 | 0.01 | 11.6 | 0.53 | 0.76 |
| 1.00 | 0.04 | 17.3 | 0.58 | 0.92 |
| 1.25 | 0.12 | 20.8 | 0.63 | 1.03 |
| 1.50 | 0.21 | 30.2 | 0.74 | 1.11 |
F0 全程平滑单调递增,α>1 外推没有崩。 逐语句全程单调率: F0 39.6%、时长 56.2%、能量 16.7%(7 个点全程单调是很严的判据)。
趋势 —— 时长响应差一个数量级¶

embedding 层确实能改时长,但斜率只有 +0.135 s/α,而我们在速度场层是 +1.36 s/α —— 正好 10 倍差距。 Sad(绿)响应最强(α=1.5 时 +0.68 s),其余三个情感挤在 +0.2 附近。
定性 —— 直接听¶
同一句、同一说话人,只改 α(Sad 的时长响应最强,故选它):
| α=0(中性端) | α=0.5 | α=1.0 | α=1.5(外推) |
|---|---|---|---|
四档听下来是平滑过渡,α=1.5 没有破音。 另一情感的外推端作参照:
⚠️ 与我们的音频不可直接比音质:EmotiVoice 是 16 kHz、不同说话人、不同基座。 只能比各自相对自己 α=0 的变化趋势。
附带 —— 两个 style 空间的几何很不一样¶
| EmotiVoice 的情感提示向量 | 我们的 A 方向 | |
|---|---|---|
| 最高两两余弦 | +0.331(Angry–Surprise) | 0.72(Happy–Angry,F4) |
| 最低 | −0.358 | — |
EmotiVoice 的情感提示向量彼此接近正交,我们的 A 方向则明显沿唤醒度聚成一簇。
完整音频库¶
样例只放了 5 条,全部 336 条在:
/data/Zhengwei/Voice/outputs/m7_emotion_embedding/wav/
命名 <key>__<情感>__a<α>.wav 例 0001_text00000__Sad__a1.50.wav
规模 336 条 / 27 MB / 16 kHz
索引 ../per_scene.json(逐条声学量 + F0 原始轨迹)
../metrics.json(汇总,含 n / 单位 / 统计量口径)
6 结论¶
把 α 搬到 embedding 层,它工作得相当好。
- 响应平滑单调 —— F0 中位数 4.3 → 30.2 Hz 干净递增,没有跳变
- 外推不崩 —— α=1.5 仍在趋势线上,听感无破音
- 时长也能改,但弱一个数量级 —— +0.135 vs 我们的 +1.36 s/α
⚠️ 这推翻了我在 proposal 里的一处结构性判断¶
proposal §2.4 写道 embedding 层「时长由时长预测器决定,不随 α 变」。 实测它会变 —— EmotiVoice 的时长预测器吃 style 向量,插值会连带改时长。
我把「不用做实验也知道」的事情判断错了。能不能改时长是经验问题,不是结构问题; 真正结构性的只有「能不能时变定位」那一条。 → 同方法论 §5.7:从结构推断推不出干预结果。
那我们的优势剩下什么¶
| embedding 层 | 速度场层(我们) | |
|---|---|---|
| 插值平滑性 | ✅ 好 | ✅ 好 |
| α>1 外推 | ✅ 不崩 | ✅ 不崩(F2) |
| 时长控制 | 弱(+0.135 s/α) | 强 10 倍(+1.36) |
| 时变定位 | ❌ 全局一个向量,结构上做不到 | ✅ 定位比 42.3(F9) |
只剩两条,但都是实打实的。「α 插值本身」不是我们的贡献 —— 它在 embedding 层同样好用。
边界:单模型、单说话人、n=48;跨模型绝对值不可比。 定性结论(embedding 层也平滑好用)可信,具体倍数不宜外推到别的模型。
7 风险¶
- ⚠️ 找不到可替换的情感向量。 很多模型的"情感"混在 style/prompt 向量里拆不出来。 步骤 0 不通过就换模型 —— 这是成败关键,不能事后补。
- 绝对值不可比。 EmotiVoice 与 CosyVoice3 的基座能力、数据、音质都不同 (见方法论 §5.8)。 只能比各自相对自己 α=0 的变化趋势,不能比分数高低。
8 引出¶
→ 若 embedding 层的插值也平滑好用,说明 α 插值是个通用手法, 我们的价值在于把它放到了能时变的层级(M6)。 → 若 embedding 层很快就崩(尤其 α>1),说明速度场层更稳,那是另一条实打实的优势。