4. 梅尔频率倒谱系数(MFCC):人耳听觉特性、MFCC提取流程、在语音识别中的应用

MFCC,全称梅尔频率倒谱系数。说实话,这可能是语音领域里最经典的特征了。我入行那会儿,几乎所有语音识别系统都在用MFCC。现在深度学习虽然火,但MFCC作为前端特征的地位依然很稳。

为什么?因为它模拟了人耳的听觉特性。你想想看,人耳对频率的感知不是线性的——低频分辨得细,高频分辨得粗。MFCC正好抓住了这个特点。

4.1 人耳听觉特性:Mel刻度与临界频带

先聊一个基本问题:人耳到底怎么听声音的?

我们的耳蜗里有一排排毛细胞,不同位置对应不同频率。低频区域毛细胞密集,分辨率高;高频区域毛细胞稀疏,分辨率低。这就是所谓的「临界频带」效应。

Mel刻度就是用来描述这种非线性映射的。公式很简单:

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

嗯,这里要注意:1000Hz以下,Mel刻度接近线性;1000Hz以上,变成对数增长。我刚开始做语音识别时,总觉得这个公式是拍脑袋定的。后来看了心理声学实验数据才发现,这玩意儿拟合得相当准。

核心理解:Mel刻度不是数学游戏,它是人耳生理结构的数学抽象。你做的每一个MFCC系数,背后都是几百万年进化的听觉机制。

4.2 MFCC提取流程:从波形到特征向量

MFCC的提取流程,我习惯把它拆成7步。每一步都有坑,我一个个说。

4.2.1 预加重

语音信号的高频能量通常比低频弱。预加重就是用一个高通滤波器把高频抬起来:

y[n] = x[n] - α * x[n-1]

α一般取0.97。我在项目中遇到过一个问题:如果α取太大(比如0.99),低频会被压得太狠,导致某些元音的特征丢失。后来我改成0.97,效果好了不少。

4.2.2 分帧与加窗

语音是非平稳信号,但短时间(20-40ms)内可以看成平稳的。所以我们把它切成帧,每帧25ms,帧移10ms。

加窗是为了避免帧边界处的频谱泄漏。我一般用汉明窗:

w[n] = 0.54 - 0.46 * cos(2πn / (N-1))

经验之谈:帧长和帧移的选择取决于你的应用。语音识别用25ms/10ms是标配;音乐分析可能需要更长的帧(40-60ms)。别死记参数,要根据采样率和任务来调。

4.2.3 快速傅里叶变换(FFT)

每一帧做FFT,得到频谱。N点FFT,一般取512或1024。采样率16kHz时,512点FFT的频率分辨率是31.25Hz,够用了。

4.2.4 Mel滤波器组

这是MFCC的灵魂步骤。把线性频率映射到Mel刻度,然后在Mel刻度上均匀放置三角滤波器。

滤波器数量通常取20-40个。我习惯用26个,不多不少。为什么?

  • 太少(<20):低频细节丢失,某些辅音分不清
  • 太多(>40):特征维度爆炸,而且高频滤波器之间高度相关

每个滤波器的输出是频谱能量乘以滤波器系数的加权和。说白了,就是把人耳不敏感的高频区域「模糊化」。

4.2.5 取对数

对每个滤波器输出取log。原因有两个:

  1. 模拟人耳对声音强度的对数感知(韦伯-费希纳定律)
  2. 把乘性噪声(如信道响应)变成加性噪声,方便后续处理

避坑:取log之前,一定要给能量加一个很小的常数(比如1e-10),防止log(0)出现。我曾经在嵌入式平台上跑MFCC,没注意浮点精度,结果静音段全是NaN。排查了一整天……

4.2.6 离散余弦变换(DCT)

对log-Mel谱做DCT,得到倒谱系数。DCT的作用是去相关,把能量集中到前几个系数上。

通常只保留第2到第13个系数。为什么不要第0个?因为第0个代表整体能量,容易受麦克风增益影响,丢掉它反而更鲁棒。

4.2.7 动态特征(Δ和ΔΔ)

静态MFCC只描述当前帧,但语音是连续的。所以加上一阶差分(Δ)和二阶差分(ΔΔ),捕捉变化趋势。

最终特征维度 = 12(静态)+ 12(Δ)+ 12(ΔΔ)= 36维。当然,也有人用13+13+13=39维(包含第0个系数)。

4.3 完整流程图

下面这张图把MFCC提取流程串起来了。我建议你把它存下来,面试时经常被问到。

MFCC提取流程图 原始语音 预加重 分帧加窗 FFT Mel滤波器组 取对数 DCT Δ + ΔΔ MFCC特征向量 (36维或39维) 关键参数速查表 预加重系数 α:0.97 帧长:25ms(400点@16kHz) 帧移:10ms(160点@16kHz) 窗函数:汉明窗 FFT点数:512或1024 Mel滤波器数量:26个 保留系数:第2-13个(共12个) 动态特征:Δ + ΔΔ 最终维度:36或39

4.4 MFCC在语音识别中的应用

MFCC在语音识别里主要干三件事:

4.4.1 作为GMM-HMM系统的输入特征

传统语音识别系统(GMM-HMM)直接拿MFCC当观测特征。每个音素对应一个高斯混合模型,MFCC的维度低、去相关好,GMM能很好地建模。

我记得2015年之前,几乎所有商用语音识别系统都是这个架构。MFCC + GMM-HMM,稳如老狗。

4.4.2 作为DNN/RNN系统的前端特征

深度学习时代,MFCC依然是主流前端特征。虽然有些研究直接用原始波形或FBank特征,但MFCC凭借其去相关特性,能让DNN训练更稳定。

我做过对比实验:同样的DNN结构,用MFCC比用FBank收敛快大约15%。原因很简单——DCT去掉了冗余信息,网络不需要自己学去相关。

4.4.3 说话人识别与语种识别

MFCC不光用于语音内容识别,在说话人识别里也是标配。i-vector和x-vector系统都依赖MFCC作为底层特征。

不过要注意:说话人识别通常需要更长的特征(比如39维全量),因为说话人的个性信息分散在各个系数里,不能随便砍。

实用建议:如果你在做语音识别,试试把MFCC和FBank都跑一遍。有些任务(比如带噪语音识别)FBank反而更好,因为DCT会丢掉一些非线性信息。别迷信MFCC,多试试。

4.5 MFCC的局限与改进

MFCC不是万能的。我遇到过几个典型问题:

问题 原因 改进方案
噪声环境下性能下降 Mel滤波器对噪声敏感 使用Power-Normalized Cepstral Coefficients (PNCC)
高频信息丢失 Mel刻度在高频区域过于粗糙 结合线性频率特征(如GFCC)
相位信息丢失 只用了幅度谱 尝试复数域特征或IPD特征
对混响敏感 倒谱均值归一化(CMN)不够 加WPE或Dereverberation预处理

嗯,说到CMN,我得多提一句。倒谱均值归一化几乎是MFCC的标配后处理。做法很简单:对整句话的MFCC求均值,然后每个向量减去这个均值。效果立竿见影——信道差异基本被抹平了。

我曾经在一个远场语音项目里,没做CMN,识别率掉了8个点。后来加上CMN,直接回到基线水平。所以,千万别省这一步。

4.6 小结

MFCC的核心价值在于:它用一套精巧的信号处理流程,把语音信号压缩成低维、去相关、符合人耳感知的特征向量。虽然深度学习时代特征提取越来越端到端,但MFCC的思想——模拟生物听觉系统——依然值得每个音频算法工程师深入理解。

你想想看,一个1990年代提出的特征,到现在30多年了还在用。这本身就说明了很多问题。