3. 数据采集与标注

好,咱们进入第三章。这一章聊的是特征提取,说白了就是怎么把麦克风收进来的声音,变成模型能看懂的数字。

我刚开始做唤醒词的时候,也想过一个问题:为什么不直接把原始波形扔给模型?后来发现,原始波形太“原始”了。它里面藏着大量跟唤醒词无关的信息,比如环境噪声、说话人的音色差异、音量大小。模型要是直接学这些,参数量会爆炸,而且泛化能力很差。

所以我们需要一个“翻译官”,把声音信号翻译成更紧凑、更鲁棒的表示。这就是特征提取干的事。

3.1 从波形到频谱:先理解声音的本质

声音本质上是空气的振动。麦克风把它变成了电压信号,也就是我们看到的波形图。横轴是时间,纵轴是振幅。

但波形有个问题:它看不出频率成分。你想想看,一段“你好”和一段“你好吗”,波形长得完全不一样,但它们的频率成分其实很相似。模型要学的是“频率模式”,而不是“时间模式”。

所以第一步,我们要把时域信号转成频域信号。用的工具是短时傅里叶变换(STFT)。

核心思路:把一段长语音切成很多小帧(通常20-30ms一帧),每帧做一次傅里叶变换,得到这一帧的频谱。把所有帧的频谱按时间堆起来,就是语谱图(Spectrogram)。

语谱图的横轴是时间,纵轴是频率,颜色深浅代表能量大小。这就是后面所有特征的基础。

3.2 三大特征:Mel谱图、Fbank、MFCC

从语谱图出发,我们演化出了三种最常用的特征。我按“从原始到压缩”的顺序给你捋一遍。

3.2.1 Mel谱图

人耳对频率的感知不是线性的。低频区域,我们分辨得很细;高频区域,我们分辨得很粗。Mel刻度就是模拟这种感知的映射关系。

Mel谱图的做法很简单:把语谱图的频率轴,从线性刻度映射到Mel刻度。公式是:

Mel(f) = 2595 * log10(1 + f/700)

映射完之后,再通过一组三角滤波器(Mel滤波器组)把频谱能量聚合到各个Mel频带上。最终得到的就是Mel谱图。

特点:保留了完整的能量信息,没有做进一步压缩。信息量最大。

3.2.2 Fbank(Filter Bank)

Fbank其实就是Mel谱图的对数版本。在Mel谱图的基础上,取一个log。为什么要取log?

因为人耳对声音响度的感知也是对数级的。你音量翻一倍,人耳感觉只是“大了一点”,而不是“大了一倍”。取log之后,能量分布更符合人耳特性,也更容易让模型训练收敛。

我在项目中做过对比:用Fbank训练的模型,收敛速度比直接用Mel谱图快大概20%。

我的习惯:在唤醒词场景下,Fbank是我最常用的特征。它信息量足够,计算量适中,而且跟深度学习模型配合得很好。

3.2.3 MFCC(Mel频率倒谱系数)

MFCC是在Fbank的基础上,再做一步离散余弦变换(DCT)。DCT的作用是去相关,把Fbank各个频带之间的冗余信息去掉,只保留最关键的系数。

通常我们只取前12-13个MFCC系数,再加上一阶差分和二阶差分,组成一个39维的特征向量。

MFCC的优势:维度低,计算快,在传统GMM-HMM时代是绝对的主流。

MFCC的劣势:DCT会丢掉一些非线性信息。对于深度学习模型来说,这些信息可能是有用的。

3.3 为什么选这些特征?

这个问题我经常被问到。我的回答是:看场景。

特征类型 信息量 维度 计算量 推荐场景
Mel谱图 最高 高(如128维) 中 需要精细频率信息的场景
Fbank 高 中(如40-80维) 低 深度学习唤醒词、语音识别
MFCC 中 低(如13-39维) 最低 传统模型、资源受限设备

我个人习惯:做唤醒词,首选Fbank。原因有三:

  • 唤醒词任务只需要识别几个固定的词,不需要像语音识别那样区分所有音素。Fbank的信息量足够。
  • Fbank的计算量比Mel谱图低,比MFCC略高,但深度学习模型能从中学到更多判别性信息。
  • 我在多个项目里对比过,Fbank在唤醒词上的准确率通常比MFCC高1-3个百分点。

避坑指南:我曾经在一个低功耗项目里强行用Fbank,结果发现DSP芯片算不过来。后来换回MFCC,模型精度只掉了0.5%,但功耗降了30%。所以,特征选择一定要结合硬件算力来权衡。

3.4 特征维度对模型大小的影响

这一点很多人会忽略。特征维度直接影响模型的第一层参数量,进而影响整个模型的大小。

假设你的模型第一层是线性层,输入维度是D,输出维度是H。那么这一层的参数量就是 D × H + H(偏置)。

如果D从40变成80,参数量直接翻倍。而且这个影响会传递到后续层,因为第一层的输出维度H通常也会跟着调整。

我画了一张图,帮你直观理解这个关系:

特征维度对模型参数量影响示意图 输入特征 D=40 隐藏层 H=128 输出层 参数量 = 40×128 + 128 = 5248 输入特征 D=80 隐藏层 H=128 输出层 参数量 = 80×128 + 128 = 10368 参数量翻倍 特征维度从40增加到80,第一层参数量从5248增加到10368 如果模型有5层,总参数量可能增加数万甚至数十万

所以,特征维度不是越大越好。你需要找到一个平衡点:

  • 维度太低:信息丢失严重,模型学不到足够特征,准确率上不去。
  • 维度太高:模型变大,推理变慢,而且容易过拟合。

我在实际项目中,一般这样选:

设备类型 推荐特征 推荐维度 理由
手机/智能音箱 Fbank 40-80 算力充足,追求精度
耳机/手表 MFCC 13-26 算力有限,需要低功耗
IoT设备(MCU) MFCC 13 极致压缩,能跑起来就行

一个小技巧:如果你不确定选多少维,可以先从40维Fbank开始。然后尝试降低到20维,看准确率掉多少。如果掉得不多,就选20维。如果掉得厉害,再往上加。这叫“从下往上试探法”,我一直在用。

3.5 总结一下

特征提取是整个唤醒词流程的“入口”。入口选对了,后面事半功倍。入口选错了,后面再怎么调模型也救不回来。

我个人建议:

  • 先搞清楚你的硬件能承受多大的计算量。
  • 再根据场景选特征类型(唤醒词首选Fbank)。
  • 最后用“从下往上试探法”确定最佳维度。

嗯,这一章就到这里。特征提取这块,你只要把Mel谱图、Fbank、MFCC三者的关系和适用场景搞清楚,后面做优化的时候就不会走弯路。