第四章 语音识别(ASR)基础:ASR架构、声学模型与语言模型、端到端识别模型

各位同学,欢迎来到第四章。这一章我们聊聊语音识别,也就是ASR。说实话,ASR是整个座舱语音交互系统的“耳朵”。耳朵不好使,后面说啥都白搭。

我在做座舱项目时,最头疼的就是用户说“打开空调”,系统识别成“打开窗户”。这种低级错误,往往不是算法不行,而是架构设计上就埋了坑。今天我们就从根上把ASR捋一遍。

4.1 传统ASR架构:三件套

传统的ASR系统,说白了就是三个模块串在一起:声学模型、语言模型、解码器。我习惯叫它“三件套”。

  • 声学模型:把音频信号转成音素(比如“a”、“b”这些基本发音单元)。
  • 语言模型:判断哪些词串在一起更像人话。比如“我要去机场”比“我要去鸡场”概率高。
  • 解码器:把声学模型和语言模型的输出综合起来,找到最可能的文字序列。

你想想看,这三个模块是独立训练的。声学模型只管“听”,语言模型只管“猜”。最后解码器把它们拼起来。这种架构有个好处:每个模块可以单独优化。但坏处也很明显——误差会累积。

核心要点:传统ASR的瓶颈不在单个模型,而在模块之间的“信息损耗”。声学模型输出一个概率分布,语言模型再叠一层概率,解码器做搜索时,很多细节就丢了。

4.2 声学模型:从GMM到DNN

声学模型这块,我经历过好几个时代。最早是GMM(高斯混合模型),后来是DNN(深度神经网络),再后来是CNN、RNN、Transformer。

GMM时代,我记得每个音素都要手工设计特征。MFCC(梅尔频率倒谱系数)是标配。那时候调参调得我头秃。一个简单的“静音检测”就能折腾一周。

后来DNN来了,事情简单了很多。你只需要把原始音频特征扔进去,网络自己学。我在项目中用过的一个经典结构是这样的:

# 伪代码:DNN声学模型结构
输入层: 40维MFCC特征(每帧)
隐藏层1: 1024个神经元,ReLU激活
隐藏层2: 1024个神经元,ReLU激活
隐藏层3: 512个神经元,ReLU激活
输出层: 音素个数(比如40个),Softmax

嗯,这里要注意:DNN虽然强,但它对时序关系不敏感。你想想看,语音是连续的,前后帧有依赖。DNN只看当前帧,容易“断章取义”。

所以后来大家开始用RNN/LSTM。LSTM能记住前面几帧的信息,识别率明显提升。我在一个车载项目里,把DNN换成LSTM后,准确率从85%跳到了92%。

个人经验:声学模型训练时,数据增强特别重要。我习惯加一些噪声、混响、变速。座舱环境里,风噪、路噪、空调声都很常见。不加噪声训练,实车测试时识别率会掉10个点以上。

4.3 语言模型:N-gram与神经网络

语言模型的任务,是给词序列打分。比如“打开空调”得分高,“打开空条”得分低。

传统做法是N-gram。N-gram统计的是“前N-1个词出现后,下一个词的概率”。比如2-gram(bigram)就是看“打开”后面跟“空调”的概率。

N-gram简单、快、可解释。但有个问题:它只能看到局部上下文。比如“我想听周杰伦的《七里香》”,N-gram很难捕捉到“周杰伦”和“七里香”之间的远距离关系。

后来神经网络语言模型(NNLM)出现了。RNNLM、LSTM LM、Transformer LM,一个比一个强。它们能建模长距离依赖,效果明显好于N-gram。

我在座舱项目里,用的是“N-gram + 神经网络”的混合方案。N-gram做快速解码,神经网络做重打分。这样既保证了实时性,又提升了准确率。

模型类型 优点 缺点 适用场景
N-gram 速度快、可解释性强 无法建模长距离依赖 实时性要求高的场景
RNNLM 能建模长距离依赖 训练慢、推理慢 离线重打分
Transformer LM 并行计算、效果最好 资源消耗大 云端大模型

避坑指南:我曾经在项目里直接用了开源的通用语言模型,结果在座舱场景下效果很差。因为用户说的都是“导航到XXX”、“播放XXX”,这些短语在通用语料里出现频率低。后来我专门收集了座舱语料,微调了语言模型,准确率才上来。

4.4 端到端识别模型:一步到位

传统ASR的“三件套”虽然经典,但太复杂了。每个模块都要单独训练、调优、部署。而且模块之间的接口设计不好,容易出问题。

端到端模型,说白了就是“输入音频,直接输出文字”。中间没有声学模型、语言模型、解码器的区分。一个神经网络搞定所有。

主流的端到端模型有三种:

  • CTC(连接时序分类):最早期的端到端方案。它假设每一帧的输出是独立的,然后通过“空白符”处理对齐问题。CTC简单,但效果一般。
  • RNN-T(循环神经网络转录器):Google提出的方案。它不假设帧独立,而是用“预测网络”来建模语言信息。RNN-T在流式识别中表现很好。
  • Transformer/Conformer:基于自注意力机制。效果最好,但计算量大。适合离线场景。

我在座舱项目里,最终选的是RNN-T。原因很简单:座舱需要实时识别。用户说“导航到天安门”,系统得在说完之前就开始出结果。RNN-T天然支持流式解码,延迟低。

# 伪代码:RNN-T模型结构示意
class RNNTModel(nn.Module):
    def __init__(self):
        self.encoder = Encoder()      # 声学编码器
        self.prediction = Prediction() # 语言预测网络
        self.joiner = Joiner()        # 联合网络
    
    def forward(self, audio_features):
        # 编码器处理音频
        encoded = self.encoder(audio_features)
        # 预测网络处理已输出的文本
        predicted = self.prediction(prev_tokens)
        # 联合网络输出最终概率
        output = self.joiner(encoded, predicted)
        return output

核心要点:端到端模型虽然方便,但也不是万能的。它对数据量的要求很高。传统ASR可能几万小时数据就够了,端到端模型往往需要几十万小时。座舱场景下,如果数据不够,我建议还是用传统方案或者混合方案。

4.5 实际项目中的选择建议

说了这么多,到底怎么选?我给大家一个参考:

  • 资源受限(车机芯片弱):传统ASR(GMM/DNN + N-gram)。轻量、快速、可裁剪。
  • 资源中等(有GPU但不大):混合方案。DNN/LSTM声学模型 + N-gram解码 + 神经网络重打分。
  • 资源充足(云端或高端车机):端到端模型(RNN-T或Conformer)。效果好,但需要大量数据。

我个人习惯是:先跑一个传统ASR做基线,然后逐步替换成端到端。这样每一步都有对比,出了问题也知道是哪一步导致的。

小技巧:不管选哪种方案,一定要做“热词”优化。座舱场景里,“导航”、“空调”、“音乐”这些词出现频率极高。把它们加入语言模型或解码器的热词列表,能显著提升用户体验。

好了,这一章就到这里。下一章我们聊聊语音合成(TTS),也就是让车机“开口说话”。到时候我会分享一些让合成语音更自然的技巧,敬请期待。