Chapter 1: 任务全景:ASR 与 Diarization 的训练对象、边界与通用流水线
1. 开篇:从“听写”到“听懂”
在深度学习爆发之前,语音识别(ASR)往往被视为一个单纯的信号处理问题:将连续的模拟信号映射为离散的符号序列。但在 MLLM(多模态大语言模型)时代,我们的视野必须从单纯的转写(Transcription)扩展到语音智能(Speech Intelligence)。
当你接到任务“训练一个语音模型”时,你实际上是在构建一个复杂的概率系统,它需要解决以下层层递进的问题:
- 声学层面:这是声还是人声?(VAD)
- 语音学层面:这是什么音素?(Acoustic Model)
- 语言学层面:这串音素是“南京市长”还是“南京市 长”?(Language Model)
- 说话人层面:这是老板说的还是员工说的?(Diarization)
- 语义层面:这段话是指令还是闲聊?(NLU/MLLM)
本章将为你拆解这个庞大的系统,确立本书的工程边界,并定义一套通用的训练流水线。
学习目标
- 任务界定:精准区分 ASR, Diarization, SA-ASR 与 AST 的输入输出与评价标准。
- 全链路视野:掌握从原始音频到最终指标的完整数据流转,而不局限于模型结构。
- 多语种认知:理解 Code-switching(混语)与 Multi-script(多脚本)带来的 Tokenizer 灾难。
- 场景权衡:在流式(Streaming)与离线(Non-streaming)之间做出正确的架构选择。
2. 核心任务定义与边界
为了避免在项目后期出现需求错,我们首先用 ASCII 图表清晰定义各类任务的 I/O(输入输出)。
2.1 ASR (Automatic Speech Recognition)
最基础的任务,但在多语种环境下变得极其复杂。
Input: [Waveform: 16kHz, Mono, Float32]
|
v
Model: P(Text | Audio)
|
v
Output: "We used PyTorch 框架 to train the model."
- 关键挑战:
- 声学模糊性:同音词("their" vs "there", "期权" vs "弃权")。
- 归一化(Normalization):音频里说的是 "two thousand and twenty five",输出要是 "2025" 还是 "二零二五"?(详见 Chapter 4)。
2.2 Speaker Diarization (说话人日志)
俗称“声纹分割聚类”,解决 "Who spoke when" 的问题。
Input: [Waveform containing multiple speakers]
|
v
Model: Segmentation + Embedding + Clustering
|
v
Output: [
(0.00s - 3.50s, Speaker_A),
(3.50s - 5.20s, Speaker_B),
(5.10s - 6.00s, Speaker_A) <-- 注意这里的时间重叠 (Overlap)
]
- 关键挑战:
- 说话人数量未知:会议可能是 2 人也可能是 10 人。
- 极短语音:像“嗯”、“好”这种短词很难提取出鲁棒的声纹特征。
- 重叠(Overlap):当两人同时说话时,传统聚类模型往往会失效或只把这一段归给占主导地位的人。
2.3 SA-ASR (Speaker-Attributed ASR)
这是 ASR 与 Diarization 的终极融合形式,也是目前会议记录产品的标配。
- 级联模式(Cascade):先跑 Diarization 拿到时间戳,再切片跑 ASR,最后拼接。缺点是误差累积。
- 端到端模式(E2E):模型直接输出带标签的 Token,如
<spk:1> Hello <spk:2> Hi。这是学术界的研究热点(如 t-SOT),但在长音频泛化上仍有难度。
2.4 AST (Audio Speech Translation)
语音翻译,直接从“源语言音频”到“目标语言文本”。
- 趋势:过去是
ASR (Audio->Text) + MT (Text->Text)的级联。现在更倾向于 E2E AST,因为级联会丢失语调情感信息(比如讽刺语气的翻译)。
3. “训练一个系统”的通用流水线
训练绝不仅仅是 model.forward()。在工业级系统中,代码量的分布通常是:数据处理 40%,评测与分析 30%,模型结构 20%,部署逻辑 10%。
3.1 阶段一:数据准备 (The Data Front)
这是决定模型生死的环节。
- Manifest Generation:不直接读取音频文件,而是生成元数据文件(JSON/CSV),记录
path,duration,text,lang,speaker_id。 -
Filtering: * 丢弃过短(<0.5s)或过长(>30s,除非做长音频训练)的样本。 * 丢弃标注质量低(Text/Audio 长度比率异常)的样本。
-
Tokenization:构建词表。是选 Char(字),BPE(子词),还是 Bytes(字节)?多语种场景下这个选择至关重要。
3.2 阶段二:建模与训练 (The Training Loop)
- Augmentation (在线增广):在 GPU 读取数据时实时添加噪声、混响、速度扰动(Speed Perturb)。
-
Encoder-Decoder: * Encoder (Conformer/Zipformer): 压缩声学特征。 * Decoder (Transformer/RNN-T): 生成文本。
-
Loss Calculation: * CTC Loss: 负责对齐(Alignment)。 * CE Loss (Attention): 负责语义连贯。 * Hybrid Loss:
Loss = λ * CTC + (1-λ) * Attention是经典配方。
3.3 阶段三:解码与后处理 (Inference & Post-processing)
模型输出的只是概率或原始 Token 序列,离“人能看的文字”还差很远。
- Search Strategy:Greedy Search(贪心) vs Beam Search(束搜索)。
- LM Rescoring:外挂一个只训练过文本的大语言模型(N-gram 或 Neural LM)来修正语法错误(例如把“南京市 长”修正为“南京市长”)。
- Timestamp Extraction:从 Attention 权重或 CTC 峰值中找回每个字的时间戳。
- ITN (Inverse Text Normalization):把“二零二三年”转回“2023年”。
3.4 阶段四:评测与回归 (Evaluation)
- Sanity Check:在小规模验证集上确收敛。
- Benchmark:在 AISHELL, LibriSpeech 等标准集上跑分。
- Side-by-Side (SxS):对于微小的改进,进行 A/B 测试对比。
4. 多语种与多脚本(Multi-script)的复杂性
本书的核心特色是面向“多语种”。这比单语种训练多出了一个维度的复杂度。
4.1 脚本(Script)vs 语言(Language)
- 语言:English, Mandarin, Japanese。
- 脚本:Latin, Hanzi (CJK), Kana, Cyrillic。
- 陷阱:日语同时使用了三种脚本(汉字、平假名、片假名)。如果我们简单的把所有“汉字”都归为中文,日文识别就会崩坏。
4.2 Code-switching (混语) 的三种形态
-
Intra-sentential (句内混合):最难。“我的 Presentation 需要 update 一下。” * 难点:声学边界模糊,且 Language Model 很难学到这种语法切换概率。
-
Inter-sentential (句间混合):一句中文,一句英文。 * 难点:LID (Language ID) 的切换延迟。
-
Sub-word mixing (词内混合):较少见,如 Chinglish 里的 "gelivable"(给力able)。
4.3 统一建模策略
目前主流的“可落地”方案是 Unified Vocabulary:
- 构建一个包含 5000-10000 个常用汉字 + 26 个英文字母 + 特殊符号的超大词表。
- 对于其他语种(如俄语、阿语),使用 SentencePiece 学习 BPE 子词。
- Prompting:在输入端加入
<|zh|>或<|en|>的 Token 来提示模型当前的(主要)语种。
5. Diarization 任务拆解:不仅仅是聚类
Diarization 通常被视为 ASR 的“后处理”,但其实它是一个独立的声学任务。
5.1 模块化流水线 (Modular Pipeline)
这是目前工业界(如 Kaldi, SpeechBrain, NeMo)最成熟的方案。
-
VAD (Voice Activity Detection) * 作用:切除静音。 * Gotcha:如果不切静音,聚类算法会把背景底噪(白噪声)聚成一个超级大的 Cluster,导致所有说话人结果偏移。
-
Segmentation (切片) * 将有效语音切成固定长度(如 1.5s)的滑动窗口。
-
Embedding (声纹提取) * 模型:TDNN, ResNet, CAM++。 * 目标:将 1.5s 的音频映射为一个固定维度(如 192维)的向量。同人的向量距离近,异人的距离远。
-
Clustering (聚类) * 算法:Spectral Clustering (谱聚类) 优于 K-Means,因为不需要预先指定 K(说话人数)。 * AHC:层次聚类,计算量大但精度高。
-
Resegmentation (重分割) * 利用 Viterbi 算法微调边界,修正聚类产生的粗糙切分点。
5.2 难点:Overlap (重叠语音)
当 A 和 B 同时说话时,提取出的 Embedding 既不像 A 也不像 B,而是一个位于两者中间的“怪异向量”。这会导致聚类产生第三个“幽灵说话人”。
- 解决思路:Overlapped Speech Detection (OSD) 模型,先检测重叠,再做分离(Separation)或多标签分类。
6. 典型产品形态与约束
你的训练目标必须服从于产品形态。
6.1 离线高精度 (Offline)
- 场景:会议录音转写、视频字幕生成。
- 特点:
- 可以使用 Bidirectional (双向) 模型,利用未来信息辅助当前识别。
- 可以使用庞大的模型(如 600M+ 参数的 Conformer)。
- 可以使用多轮 Rescoring。
6.2 流式低延迟 (Streaming)
- 场景:语音输入法、直播字幕。
- 硬约束:
- Causal (因果性):第 t 帧的输出只能依赖 t 时刻之前的输入。
- Lookahead (前瞻):允许看未来一小段(比如 160ms),以牺牲一点延迟换取精度。
- Stateful (有状态):RNN/LSTM 需要在内存中维护 hidden states;Transformer 需要维护 KV Cache。
6.3 隐私/合规 (PII & Compliance)
- PII (Personal Identifiable Information):训练数据中的身份证号、电话、姓名必须脱敏。
- 联邦学习:在极端隐私场景(如银行、医疗),数据不出域,模型去客户本地训练(这极大增加了工程复杂度)。
7. 本章小结
本章为你绘制了 ASR 与 Diarization 的工程地图。核心要点如下:
- 流水线思维:从 Manifest 到 ITN,模型训练只是其中一环。如果你的 ITN 写得烂,模型识别得再准,用户看到的也是错的(例如 "三点一四" vs "3.14")。
- 多语种即正义:在设计系统时,永远假设未来会加入新语种。避免 Hard-code 字符集。
- Diarization 的独立性:虽然 End-to-End 很诱人,但基于 Embedding + Clustering 的模块化方案目前在长会议场景下依然最稳健。
- 可复现性:下一章我们将详细介绍如何利用 YAML 配置和 Docker 容器,确保你的实验不是“一次性”的。
8. 练习题
基础题 (50%)
Q1: 为什么 ASR 系统中不仅需要 Acoustic Model (声学型),还需要 Language Model (语言模型)?请举一个声学信号完全相同但含义不同的例子。
- Hint: 同音词歧义。
- Answer:
- 声学模型只能判断发音是
/ji/ /shu/。 - 语言模型负责根据上下文概率判断这是“技术”(Technology)还是“计数”(Counting)或是“艺术”(Art - 某些口音下)。
- 经典例子:“南京市长江大桥”。断句不同,声学特征极似,全靠 LM 区分是“南京市/长江大桥”还是“南京/市长/江大桥”。
Q2: 计算 RTF (Real Time Factor)。如果你处理一段 10 秒的音频,花了 2 秒钟,RTF 是多少?如果 RTF > 1 意味着什么?
- Hint: RTF = 处理时长 / 音频时长。
- Answer:
- RTF = 2s / 10s = 0.2。这是一个很快的系统。
- 如果 RTF > 1,意味着处理速度慢于说话速度。在流式系统中,这意味着延迟会无限累积,系统最终崩溃或产生巨大的滞后。
Q3: 解释 ASR 评估指标中的 Substituted (S), Deleted (D), Inserted (I)。如果是“漏词”对应哪一个?“多词”对应哪一个?
- Hint: 比较 Reference (Ref) 和 Hypothesis (Hyp)。
- Answer:
- S (Substituted): 词被替换了(Ref: "猫", Hyp: "毛")。
- D (Deleted): 漏词(Ref: "一只猫", Hyp: "一只")。这是“漏词”。
- I (Inserted): 多词(Ref: "一只猫", Hyp: "一只大猫")。这是“多词”。
挑战题 (50%)
Q4: 在 Diarization 系统的聚类阶段,如果我们不知道具体有几个人说话(Speaker Number Unknown),K-Means 算法还适用吗?如果不适用,应该用什么算法?
- Hint: K-Means 需要预设 K 值。
- Answer:
- 原生 K-Means 不适用,因为它必须指定 K。
- 替代方案 1: Spectral Clustering (谱聚类) + Eigengap heuristic(特征值间隙启发式)来自动估计 K。
- 替代方案 2: Agglomerative Hierarchical Clustering (AHC, 层次聚类),设定一个距离阈值,让算法自动停止合并。
Q5: 设计一个处理中英混合(Code-switching)的 Tokenizer 策略。如果单纯把所有英文单词都加入词表,会发生什么问题?如果把英文全拆成字母,又有什么问题?
- Hint: 词表爆炸 vs 语义稀疏。
- Answer:
- 全单词入词表: 英文单词无穷无尽,词表会迅速爆炸(超过 100k+),导致 Softmax 计算巨慢,且 OOV(未登录词)无法识别。
- 全字母: 序列过长("Internationalization" 变成 20 个 token),模型难以捕捉长距离依赖,且容易拼写错误。
- 最佳实践 (Subword/BPE): 使用 BPE (Byte Pair Encoding) 或 SentencePiece。高频词("Apple")作为一个 Token,低频词("Bioinformatics")拆解为词根词缀("Bio", "infor", "matics")。这样既控制了词表大小,又保留了语义。
Q6: 思考题:为什么 MLLM(如 GPT-4o)在端到端 ASR 上表现强劲,但在精准的时间戳(Timestamp)预测上往往不如传统的 Conformer/Transducer 模型?
- Hint: 模型的训练目标与 Token 的离散性。
- Answer:
- 分辨率问题: 传统 ASR 模型通常以 40ms 或 80ms 为一帧进行输出,时间分辨率是物理绑定的。
- LLM 的本质: LLM 是在一个离散的语义空间预测下一个 Token。虽然可以微调它输出
<0.52s>这样的时间标签,但这本质上是“回归问题”被强行转化为了“分类生成问题”。 - 幻觉: MLLM 倾向于生成通顺的文本,有时会忽略音频中细微的停顿或含糊不清的发音,导致时间戳与实际发音对不齐。
9. 常见陷阱与错误 (Gotchas)
-
采样率的隐形杀手 * 现象:模训练得很好,线上测试全是乱码。 * 原因:训练数据是 16kHz,线上录音笔传回来的是 48kHz 或 8kHz。声学特征(Spectrogram)会完全变形。 * Fix:在特征提取的最前端加一个强制 Resample 模块。
-
Audio Length 的坑 * 现象:训练时显存爆炸(OOM),或者 Batch Normalization 统计值异常。 * 原因:数据集中混入了几条 2 小时的长录音,或者几条 0.1 秒的空录音。 * Fix:严格的数据清洗,剔除
duration < 0.5s或duration > 30s的样本(除非使用了 Chunk-wise 训练)。 -
WER 的虚假繁荣 * 现象:WER 降到了 2%,但用户反馈体验很差。 * 原因:模型把不该有的语气词“嗯、啊、那个”全识别出来了(因为训练数据里有),导致字幕看起来很乱;或者模型把重要的专有名词(人名)写错了,雖然只是错了一个字,但对业务是毁灭性的。 * Fix:引入 ITN 后的 WER 评测,以及针关键词(Keywords)的加权 WER 指标。
-
Diarization 的“说话人泄漏” * 现象:测试集效果极好,实际场景不行。 * 原因:切分 Train/Test 数据集时,是按“句子”切分的,而不是按“说话人”或“会议 Session”切分的。导致同一个人的声音既在训练集也在测试集,模型实际上是在做 Speaker Identification(认人)而不是 Diarization(聚类)。 * Fix:严格按 Session 划分数据集。
Next Step: 既然我们已经理解了全景图,下一步就是把手弄脏。请前往 Chapter 2,我们将开始搭建环境,并运行你的第一个“Hello World”级语音训练任务。