Skip to content

约 10 分钟阅读

14. 语音识别怎样训练:从声音到文字的对齐 ​

前面的篇章都在训练读文字、写文字的模型。资料助手接上麦克风以后,小林对着手机说“年假怎么申请”,最先工作的是语音识别(ASR,Automatic Speech Recognition):把一段声音变成文字。它的训练和大语言模型有一个根本差别:输入是每秒成千上万个采样点,输出只有几个字,而训练数据只告诉你“这段音频说的是这句话”,没告诉你哪一小段声音对应哪个字。这一篇先把声音变成模型能吃的特征并算清数量,再看 CTC、Transducer、注意力编解码三种方法怎样解决这个“对不上”的问题,最后看 Whisper 的弱监督大数据和 wav2vec 2.0 的自监督预训练。读完你应该能判断一个语音识别模型属于哪一类、为什么有的能边说边出字、有的要等说完,以及训练一个可用的识别器要多少标注数据。

一句 5 秒的提问有多少个数 ​

麦克风记录的是气压随时间的起伏。语音识别常用 16 kHz 采样,也就是每秒记 16,000 个数。小林这句话说了 5 秒:

text
采样点数 = 采样率 × 时长 = 16,000 × 5 = 80,000 个数

直接把 8 万个数喂给模型并不划算:单个采样点几乎不携带“这是哪个音”的信息,区分“年”和“连”靠的是一小段时间里各个频率的能量分布。所以先做特征提取,Whisper 的论文给出了一套典型口径:

text
窗长 25 ms → 16,000 × 0.025 = 400 个采样点
步长 10 ms → 16,000 × 0.010 = 160 个采样点
每秒帧数   ≈ 1 ÷ 0.010 = 100 帧
5 秒       ≈ 500 帧(严格按 (80,000 − 400) ÷ 160 + 1 ≈ 498 帧,实现里常补边凑整)

每一帧是一段 25 ms 的短窗,相邻两帧错开 10 ms,所以有 15 ms 重叠,保证一个音不会正好被切在两帧的缝里。对每帧做傅里叶变换得到频谱,再用 80 个按 Mel 刻度排布的滤波器把频谱压成 80 个数。Mel 刻度模仿人耳:低频分得细、高频分得粗。最后取对数,把动辄差上千倍的能量压到相近的数量级。结果叫 log-Mel 特征:

text
5 秒提问的特征 = 500 帧 × 80 维 = 40,000 个数

一句 5 秒的提问经过采样、分帧、频谱、Mel 滤波和编码器降采样,变成 250 帧表示,而标注只有 6 个字,没有逐帧对应关系

图里最后一步是神经网络编码器。Whisper 的编码器入口有两层卷积,第二层步长为 2,帧率从每秒 100 降到 50,5 秒就是 250 帧。到这里问题就清楚了:编码器给出 250 个向量,标注是“年假怎么申请”6 个字。训练数据里没有“第 31 到 58 帧是‘年’”这样的信息,人工逐帧标注又贵得不现实。语音识别训练的核心,就是在不知道对齐的情况下也能算出损失。

数字的细节因模型而异:Whisper large-v3 把 Mel 频带从 80 个改成了 128 个,wav2vec 2.0 直接从原始波形用卷积提特征。但“每秒几十到一百帧、一句话几百帧对几个字”这个量级关系基本不变,它决定了下面三种方法的设计。

三种对齐方法 ​

早期的语音识别先用另一套模型强行算出每帧对应哪个音素(强制对齐),再逐帧训练分类器,流程长、误差会传下去。现在主流的端到端方法有三种思路,同一句话放在一起比较:

CTC 每帧输出一个字或 blank 再合并;Transducer 用编码器、预测网络和 joiner 逐帧决定输出字还是前进;注意力编解码先听完整段再逐字生成

CTC:每帧出一个符号,再合并 ​

CTC(Connectionist Temporal Classification,连接时序分类,Graves 等人 2006 年提出)让编码器在每一帧都输出一个符号:要么是一个字,要么是一个特殊的 blank,表示“这一帧不出字”。得到逐帧序列后,先合并相邻的重复字,再删掉 blank:

text
逐帧输出:年 年 _ 假 _ _ 怎 么 _ 申 请 _
合并重复:年 _ 假 _ 怎 么 _ 申 请 _
删掉 blank:年假怎么申请

blank 还有一个作用:“看看”这样连续相同的字必须写成“看 _ 看”,否则会被合并成一个。能折叠成“年假怎么申请”的逐帧写法有成千上万种,CTC 的损失把所有这些路径的概率加起来,要求这个总和越大越好。路径虽多,但相邻帧之间的转移规则很简单,可以用动态规划在“帧数 × 文本长度”的表格里一次算完,不需要知道真正的对齐。

CTC 的代价来自一个假设:每一帧的输出只看声音,互相之间条件独立。模型在第 40 帧写“年”时,并不知道第 20 帧写了什么。这让它计算快、天然适合流式,但缺少文字上下文,同音字和专有名词容易写错,实际系统常在解码时加外部语言模型或热词。

Transducer:让输出看见已经写出的字 ​

Transducer(常称 RNN-T,Graves 2012 年提出)在 CTC 的编码器旁边加了一个预测网络,它读已经输出的文字,作用类似一个小语言模型;再用一个 joiner(联合网络)把“第 t 帧听到了什么”和“已经写到第 u 个字”合起来,给出下一步的分布。每一步要么输出一个字(送回预测网络,停在同一帧再试),要么输出 blank(前进到下一帧)。

它同样对所有可能的路径求和来训练,但输出不再相互独立,弥补了 CTC 最大的短板;同时又是逐帧推进的,说一个字出一个字,因此成了手机输入法、会议实时字幕这类流式识别的主流结构。训练成本是另一回事:joiner 要为每个“帧 × 已输出字数”的组合算一次整张词表的分布。

text
T = 250 帧,U = 6 个字,词表 V = 5,000(示意值)
joiner 输出 = T × (U + 1) × V = 250 × 7 × 5,000 ≈ 875 万个数 / 条
一批 32 条、FP32 存储:875 万 × 32 × 4 字节 ≈ 1.1 GB,只是这一个张量

句子更长、词表更大时这个三维张量增长很快,所以 Transducer 训练框架普遍要做裁剪或分块计算。CTC 只有“帧数 × 词表”这一层,便宜得多。

注意力编解码:先听完,再像写文章一样逐字生成 ​

第三种思路干脆不显式处理对齐。编码器一次读完整段音频(Whisper 每次读 30 秒),解码器像语言模型一样逐个预测下一个字,每一步用交叉注意力在全部编码器帧里查找“现在该听哪一段”。损失就是普通的交叉熵,和训练大语言模型预测下一个 token 完全相同。

这种结构上下文能力最强,还能把翻译、语种识别、时间戳当成不同的输出格式一起学。代价有两个:要等整段音频才能开始解码,流式需要额外改造;对齐完全靠注意力学,没对上时解码器会凭语言习惯继续写,出现重复或凭空编造的句子,第 15 篇会专门讨论这种幻觉。

方法训练损失输出之间流式典型代表
CTC所有对齐路径求和条件独立天然支持wav2vec 2.0 微调头、很多端侧模型
Transducer所有对齐路径求和依赖已输出文字天然支持流式输入法、实时字幕
注意力编解码逐字交叉熵依赖已输出文字需要改造Whisper

实际系统常常混用,例如训练时同时加 CTC 和注意力两个损失,让 CTC 帮注意力更快学会单调对齐。

编码器与解码方式的两个变体 ​

三种方法说的是“怎样对齐”,编码器本身用什么结构是另一维度。Conformer(2020)在 Transformer 层里插入卷积模块:自注意力负责全句范围的依赖,卷积负责几十毫秒内的局部声学模式。这两种依赖在语音里同时存在,所以 Conformer 成了 CTC 和 Transducer 模型里最常见的编码器。

中文场景常见的 Paraformer(2022,阿里达摩院,开源在 FunASR 工具包中)则改的是解码方式。它属于非自回归模型:先用一个 CIF 预测器根据声学信息估计这句话有几个字,并为每个字汇总出一个声学向量,再让解码器一次性并行输出全部字,不用一个个往后写。论文在 AISHELL 公开集和 2 万小时工业数据上报告,精度接近自回归 Transformer,速度快 10 倍以上。代价是字与字之间的依赖建模弱于自回归,论文为此加了一个按“字猜错多少”调整训练的采样器。

Whisper:用 68 万小时弱监督数据换鲁棒性 ​

传统做法是用几百到几千小时人工精标的录音训练。Whisper(OpenAI,2022)换了思路:从互联网收集带字幕的音频,共 680,000 小时,其中 117,000 小时覆盖英语以外的 96 种语言,另有 125,000 小时是“外语音频 → 英文文本”的翻译数据。这些字幕没有经过逐句人工校对,所以叫弱监督:数量极大,但有错字、有不对齐、甚至有别的识别系统自动生成的字幕。论文专门写了启发式规则来剔除机器生成的字幕,否则模型会学到别家系统的错误习惯。

弱标注换来的是鲁棒性。精标数据集大多在安静环境里朗读,模型换到嘈杂会议室、电话录音就明显变差;Whisper 见过各种口音、噪声和录音设备,开箱即用时更稳。后续的 large-v3 走得更远:按官方模型卡,它用了 100 万小时弱标注音频,加 400 万小时由 large-v2 自动转写的伪标注音频,参数约 15.5 亿,相比 large-v2 错误率降低 10%—20%。用上一代模型给海量无标注音频打标签再训练下一代,和第 13 篇讲的蒸馏是同一个思路。

伪标注也会把上一代的错误一起传下去。对资料助手来说,这意味着 Whisper 在通用中文上可用,但“钉钉审批”“OKR”这类训练数据里少见的组合,以及公司特有的项目代号,仍可能写错,这是下一篇微调要处理的问题。

wav2vec 2.0:先听大量无标注录音 ​

有标注的语音贵,无标注的语音便宜。自监督预训练先让模型只听声音、自己出题自己学,再用少量标注数据微调。wav2vec 2.0(Meta,2020)的做法和第 07 篇的“预测被遮住的内容”类似:卷积网络把波形变成隐向量,随机遮住一部分时间步,再让 Transformer 根据上下文,从若干候选中挑出被遮住位置的真实量化向量(对比学习:正确答案的得分要高过干扰项)。

论文的结果说明了这条路线的价值:在 5.3 万小时无标注音频上预训练后,只用 10 分钟有标注数据微调,LibriSpeech 测试集的词错误率就到了 4.8%(干净子集)和 8.2%(较难子集);用 1 小时标注数据,就超过了此前用 100 小时标注数据的最好结果。微调时通常在预训练编码器上接一个 CTC 输出层。

10 分钟这个结果有前提:英文朗读语料、预训练和测试数据风格接近、评测集相对干净。换到中文会议录音、方言或领域术语,所需标注量会多得多,它证明的是“预训练大幅降低了对标注的依赖”,而不是任何场景 10 分钟都够。

数据规模与标注成本 ​

把常见的数据量级放在一起,能看出不同路线依赖什么:

数据规模标注方式
AISHELL-1约 178 小时,400 名说话人,安静室内朗读人工精标,常用作中文入门基准
WenetSpeech1 万多小时标注 + 2400 多小时弱标注 + 约 1 万小时无标注视频字幕经 OCR 对齐,播客用识别系统生成候选
Whisper 原版68 万小时互联网字幕,弱监督
Whisper large-v3100 万小时弱标注 + 400 万小时伪标注字幕 + 上一代模型自动转写

人工精标的成本远高于音频时长本身:转写员要反复回听含糊处、查专有名词、统一数字和标点写法,再由第二个人抽检,转写 1 小时音频花的人工远不止 1 小时,倍数取决于噪声、口音和规范的严格程度。这也是为什么大模型都在想办法用弱标注、伪标注和自监督绕开人工标注,而企业自己的微调数据往往只有几小时到几十小时,必须精挑细选。

一个不该从零训练的判断标准:如果目标只是让通用识别器在公司场景里更准,从头训练一个识别器需要上万小时数据和对应的算力,几乎总是不划算;在已有的 Whisper、Paraformer 或 Conformer 模型上微调,或者先用热词和后处理,成本低几个数量级。

声音先按 16 kHz 采样,再按 25 ms 窗、10 ms 步长变成每秒约 100 帧的 log-Mel 特征,一句话几百帧对几个字,训练要在不知道逐帧对齐的情况下算损失。CTC 用 blank 和合并规则对所有路径求和,快但输出彼此独立;Transducer 加上预测网络和 joiner,保留流式又能看见上文,代价是训练显存;注意力编解码像语言模型一样逐字生成,上下文最强但要等整段音频,还可能幻觉。Whisper 用海量弱标注和伪标注换鲁棒性,wav2vec 2.0 用自监督把标注需求降到很低。通用模型听不准公司内部的词和口音时,下一步就是语音识别微调。识别器在部署时怎样流式运行、怎样接进整条语音链路,见推理系列的语音与多模态推理。

别急,先让缓存热一下。