3、特征提取基础:MFCC、Fbank、Mel谱图,为什么选这些特征?特征维度对模型大小的影响。
好,咱们进入第三章。这一章聊的是特征提取,说白了就是怎么把麦克风收进来的声音,变成模型能看懂的数字。
我刚开始做唤醒词的时候,也想过一个问题:为什么不直接把原始波形扔给模型?后来发现,原始波形太“原始”了。它里面藏着大量跟唤醒词无关的信息,比如环境噪声、说话人的音色差异、音量大小。模型要是直接学这些,参数量会爆炸,而且泛化能力很差。
所以我们需要一个“翻译官”,把声音信号翻译成更紧凑、更鲁棒的表示。这就是特征提取干的事。
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通常也会跟着调整。
我画了一张图,帮你直观理解这个关系:
所以,特征维度不是越大越好。你需要找到一个平衡点:
- 维度太低:信息丢失严重,模型学不到足够特征,准确率上不去。
- 维度太高:模型变大,推理变慢,而且容易过拟合。
我在实际项目中,一般这样选:
| 设备类型 | 推荐特征 | 推荐维度 | 理由 |
|---|---|---|---|
| 手机/智能音箱 | Fbank | 40-80 | 算力充足,追求精度 |
| 耳机/手表 | MFCC | 13-26 | 算力有限,需要低功耗 |
| IoT设备(MCU) | MFCC | 13 | 极致压缩,能跑起来就行 |
一个小技巧:如果你不确定选多少维,可以先从40维Fbank开始。然后尝试降低到20维,看准确率掉多少。如果掉得不多,就选20维。如果掉得厉害,再往上加。这叫“从下往上试探法”,我一直在用。
3.5 总结一下
特征提取是整个唤醒词流程的“入口”。入口选对了,后面事半功倍。入口选错了,后面再怎么调模型也救不回来。
我个人建议:
- 先搞清楚你的硬件能承受多大的计算量。
- 再根据场景选特征类型(唤醒词首选Fbank)。
- 最后用“从下往上试探法”确定最佳维度。
嗯,这一章就到这里。特征提取这块,你只要把Mel谱图、Fbank、MFCC三者的关系和适用场景搞清楚,后面做优化的时候就不会走弯路。