python实现组合cmn公式_ASR中常用的语音特征之FBank和MFCC(原理 + Python实现)

本文介绍了ASR中常用的语音特征提取,包括FBank和MFCC的原理及Python实现,涉及预加重、分帧、加窗、FFT、Mel滤波器组、DCT变换等步骤,并探讨了两者在不同场景的应用选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ASR中常用的语音特征之FBank和MFCC(原理 + Python实现)

一步一步讲解和实现ASR中常用的语音特征——FBank和MFCC的提取,包括算法原理、代码和可视化等。

语音信号的产生

语音通常是指人说话的声音。从生物学的角度来看,是气流通过声带、咽喉、口腔、鼻腔等发出声音;从信号的角度来看,不同位置的震动频率不一样,最后的信号是由基频和一些谐波构成。

之后被设备接收后(比如麦克风),会通过A/D转换,将模拟信号转换为数字信号,一般会有采样、量化和编码三个步骤,采样率要遵循奈奎斯特采样定律:f s > = 2 f fs >= 2ffs>=2f,比如电话语音的频率一般在300Hz~3400Hz,所以采用8kHz的采样率足矣。

下面采用一个30s左右的16比特PCM编码后的语音wav为例。

预加重(Pre-Emphasis)

预加重一般是数字语音信号处理的第一步。语音信号往往会有频谱倾斜(Spectral Tilt)现象,即高频部分的幅度会比低频部分的小,预加重在这里就是起到一个平衡频谱的作用,增大高频部分的幅度。它使用如下的一阶滤波器来实现:

y ( t ) = x ( t ) − α x ( t − 1 ) ,      0.95 < α < 0.99 y(t) = x(t) - \alpha x(t-1), \ \ \ \ 0.95 < \alpha < 0.99y(t)=x(t)−αx(t−1),0.95

笔者对这个公式的理解是:信号频率的高低主要是由信号电平变化的速度所决定,对信号做一阶差分时,高频部分(变化快的地方)差分值大,低频部分(变化慢的地方)差分值小,达到平衡频谱的作用。

pre_emphasis = 0.97

emphasized_signal = np.append(signal[0], signal[1:] - pre_emphasis * signal[:-1])

1

2

plot_time(emphasized_signal, sample_rate)

1

plot_freq(emphasized_signal, sample_rate)

1

从下面这个图来看,确实起到了平衡频谱的作用。

分帧(Framing)

在预加重之后,需要将信号分成短时帧。做这一步的原因是:信号中的频率会随时间变化(不稳定的),一些信号处理算法(比如傅里叶变换)通常希望信号是稳定,也就是说对整个信号进行处理是没有意义的,因为信号的频率轮廓会随着时间的推移而丢失。为了避免这种情况,需要对信号进行分帧处理,认为每一帧之内的信号是短时不变的。一般设置帧长取20ms~40ms,相邻帧之间50%(+/-10%)的覆盖。对于ASR而言,通常取帧长为25ms,覆盖为10ms。

加窗(Window)

在分帧之后,通常需要对每帧的信号进行加窗处理。目的是让帧两端平滑地衰减,这样可以降低后续傅里叶变换后旁瓣的强度,取得更高质量的频谱。常用的窗有:矩形窗、汉明(Hamming)窗、汉宁窗(Hanning)

快速傅里叶变换(FFT)

对于每一帧的加窗信号,进行N点FFT变换,也称短时傅里叶变换(STFT),N通常取256或512,然后用如下的公式计算能量谱:

FBank特征(Filter Banks)

经过上面的步骤之后,在能量谱上应用Mel滤波器组,就能提取到FBank特征。

在介绍Mel滤波器组之前,先介绍一下Mel刻度,这是一个能模拟人耳接收声音规律的刻度,人耳在接收声音时呈现非线性状态,对高频的更不敏感,因此Mel刻度在低频区分辨度较高,在高频区分辨度较低,与频率之间的换算关系为:

m = 2595 l o g 10 ( 1 + f 700 ) m = 2595 log_{10} (1 + \frac{f}{700})m=2595log10​(1+700f​)

f = 700 ( 1 0 m / 2595 − 1 ) f = 700(10^{m/2595} - 1)f=700(10m/2595−1)

Mel滤波器组就是一系列的三角形滤波器,通常有40个或80个,在中心频率点响应值为1,在两边的滤波器中心点衰减到0,如下图:

具体公式可以写为:

PS:“log mel-filter bank outputs”和“FBANK features”说的是同一个东西。

MFCC特征(Mel-frequency Cepstral Coefficients)

前面提取到的FBank特征,往往是高度相关的。因此可以继续用DCT变换,将这些相关的滤波器组系数进行压缩。对于ASR来说,通常取2~13维,扔掉的信息里面包含滤波器组系数快速变化部分,这些细节信息在ASR任务上可能没有帮助。

DCT变换其实是逆傅里叶变换的等价替代:

所以MFCC名字里面有倒谱(Cepstral)。

一般对于ASR来说,对MFCC进行一个正弦提升(sinusoidal liftering)操作,可以提升在噪声信号中最后的识别率:

从公式看,猜测原因可能是对频谱做一个平滑,如果D DD取值较大时,会加重高频部分,使得噪声被弱化?

FBank与MFCC比较

FBank特征的提取更多的是希望符合声音信号的本质,拟合人耳接收的特性。而MFCC特征多的那一步则是受限于一些机器学习算法。很早之前MFCC特征和GMMs-HMMs方法结合是ASR的主流。而当一些深度学习方法出来之后,MFCC则不一定是最优选择,因为神经网络对高度相关的信息不敏感,而且DCT变换是线性的,会丢失语音信号中原本的一些非线性成分。

还有一些说法是在质疑傅里叶变换的使用,因为傅里叶变换也是线性的。因此也有很多方法,设计模型直接从原始的音频信号中提取特征,但这种方法会增加模型的复杂度,而且本身傅里叶变换不太容易拟合。同时傅里叶变换是在短时上应用的,可以建设信号在这个短的时间内是静止的,因此傅里叶变换的线性也不会造成很严重的问题。

结论就是:在模型对高相关的信号不敏感时(比如神经网络),可以用FBank特征;在模型对高相关的信号敏感时(比如GMMs-HMMs),需要用MFCC特征。从目前的趋势来看,因为神经网络的逐步发展,FBank特征越来越流行。

其他特征

PLP(Perceptual Linear Prediction)

另外一种特征,与MFCC相比有一些优势,具体提取方式见下图:

动态特征

加入表现帧之间变化的特征,用如下公式:

d ( t ) = c ( t + 1 ) − c ( t − 1 ) 2 d(t) = \frac{c(t+1) - c(t-1)}{2}d(t)=2c(t+1)−c(t−1)​

一般在ASR中使用的特征(用于GMM相关的系统),是39维的;包括(12维MFCC+1维能量) + delta + delta^2

具体提取过程见下图:

标准化

其目的是希望减少训练集与测试集之间的不匹配。有三种操作:

去均值 (CMN)

为了均衡频谱,提升信噪比,可以做一个去均值的操作

filter_banks -= (np.mean(filter_banks, axis=0) + 1e-8)

1

plot_spectrogram(filter_banks.T, 'Filter Banks')

1

mfcc -= (np.mean(mfcc, axis=0) + 1e-8)

1

plot_spectrogram(mfcc.T, 'MFCC Coefficients')

1

方差归一(CVN)

除以标准差,从而使得方差为1

标准化(CMVN)

y t ( j ) = y t ( j ) − μ ( y ( j ) ) σ ( y ( j ) ) y_t(j) = \frac{y_t(j) - \mu (y(j))}{\sigma (y(j))}yt​(j)=σ(y(j))yt​(j)−μ(y(j))​

PS:这些操作,还可以针对speaker/channel做;在实时情景下,可以计算moving average。

总结

最后引用文末slide里面的一个总结:

传送门

<think>首先,用户的问题是关于使用Python实现实时语音识别的。我需要参考提供的引用内容,但用户说这些引用仅供参考,不是真正的需求,所以我应该基于用户的问题来回答。 用户的问题是:“我想使用Python实现语音识别功能 请问Python 实现 实时 语音识别” 关键点是:Python、实时语音识别。 从引用中,我可以提取一些有用的信息: - 引用[2]提到使用SpeechRecognition库进行语音识别。 - 引用[3][5]讨论了实时语音识别,特别是引用[5]提供了代码示例,使用while循环实现持续识别。 - 引用[5]的代码:使用speech_recognition库,在循环中监听麦克风识别语音。 系统指令要求: - 所有行内数学表达式用$...$格式。但在语音识别上下文中,可能没有数学表达式,所以可能不需要。 - 独立公式用$$...$$格式,但同样,这里可能不适用。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如[^1]。 - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠。 回答结构: 1. **介绍主题**:简要介绍Python实现实时语音识别。 2. **步骤指南**:逐步解释如何实现,包括安装库、写代码。 3. **代码示例**:提供一个实时语音识别的代码示例。 4. **注意事项**:讨论可能的问题,如准确性、性能。 5. **生成相关问题**:在结尾添加相关问题。 生成相关问题:基于主题,生成几个相关问题,如§§相关问题§§。 参考引用: - 引用[2]:使用SpeechRecognition库。 - 引用[3]:实时语音识别的精度速度问题。 - 引用[5]:代码示例。 在回答中,如果引用这些内容,添加引用标识。 现在,构建回答: 1. **介绍**:Python实现实时语音识别通常使用SpeechRecognition库,它支持多种语音识别引擎,如Google Speech Recognition。 2. **步骤**: - 安装所需库:pip install SpeechRecognition pyaudio(用于麦克风输入)。 - 写代码:使用while循环持续监听麦克风识别。 3. **代码示例**:提供类似引用[5]的代码,但要确保它是正确的。引用[5]的代码是: ```python import speech_recognition as sr import logging logging.basicConfig(level=logging.DEBUG) while True: r = sr.Recognizer() mic = sr.Microphone() logging.info('message enter') with mic as source: r.adjust_for_ambient_noise(source) audio = r.listen(source) logging.info('message end and recognize') test = r.recognize_google(audio, language='cmn-Hans-CN', show_all=True) print(test) logging.info('end') ``` 这个代码应该工作,但可以优化一下,比如减少在循环中创建RecognizerMicrophone对象,以提高效率。 改进版:在循环外创建RecognizerMicrophone对象。 4. **注意事项**:实时语音识别的准确性受噪音影响,速度取决于计算机性能网络(如果使用在线引擎)。 5. **相关问题**:生成几个相关问题。 最后,确保使用中文。</think>### Python 实现实时语音识别指南 实时语音识别是指系统能够持续监听麦克风输入,即时将语音转换为文本,无需用户手动分段。Python 提供了强大的库来实现这一功能,其中 `SpeechRecognition` 库是最常用的工具之一。它支持多种语音识别引擎(如 Google Speech Recognition),易于集成。下面我将一步步指导你如何实现实时语音识别,确保回答真实可靠,基于实际开发经验[^2][^5]。 #### 步骤 1: 安装所需库 首先,确保安装必要的 Python 库。`SpeechRecognition` 用于语音识别,`PyAudio` 用于麦克风输入。在终端运行以下命令: ```bash pip install SpeechRecognition PyAudio ``` 如果安装 `PyAudio` 遇到问题(常见于 Windows),可尝试安装预编译版本,如 `pip install pipwin` 然后 `pipwin install PyAudio`[^2][^5]。 #### 步骤 2: 编写实时语音识别代码 实时识别的核心是使用一个无限循环(`while True`)持续监听麦克风。以下是一个优化后的代码示例,减少了资源开销(如避免在循环内重复创建对象): ```python import speech_recognition as sr import logging # 设置日志记录(可选) logging.basicConfig(level=logging.INFO) def real_time_speech_recognition(): # 初始化识别器麦克风(只创建一次) recognizer = sr.Recognizer() microphone = sr.Microphone() # 调整环境噪音(只执行一次) with microphone as source: recognizer.adjust_for_ambient_noise(source) logging.info("环境噪音校准完成,开始监听...") # 实时识别循环 while True: try: with microphone as source: logging.info("请说话...") audio = recognizer.listen(source, timeout=5) # 设置超时,避免无限等待 text = recognizer.recognize_google(audio, language="cmn-Hans-CN") # 使用Google引擎,中文识别 print(f"识别结果: {text}") except sr.WaitTimeoutError: logging.warning("未检测到语音输入,继续监听...") except sr.UnknownValueError: logging.error("无法识别语音,请重试") except Exception as e: logging.error(f"发生错误: {e}") break if __name__ == "__main__": real_time_speech_recognition() ``` #### 代码说明 - **核心逻辑**:`while True` 循环持续监听麦克风,`recognizer.listen()` 捕获音频,`recognize_google()` 将语音转换为文本。 - **优化点**: - 在循环外初始化 `Recognizer` `Microphone`,减少资源消耗[^5]。 - 添加异常处理(如超时或识别失败),提高鲁棒性。 - 设置 `timeout=5` 避免无语音时卡死。 - **语言支持**:`language="cmn-Hans-CN"` 指定中文识别,可替换为其他语言(如 `en-US`)。 - **性能考虑**:实时识别依赖于网络(Google 引擎需联网)计算机性能。性能较差的设备可能延迟较高[^3]。 #### 注意事项 1. **准确性与噪音**:环境噪音会影响识别精度。使用 `adjust_for_ambient_noise()` 校准可改善效果,但高噪音环境下结果可能不理想[^4]。 2. **网络依赖**:`recognize_google()` 需要互联网连接。如需离线方案,可考虑 `pocketsphinx` 引擎(但精度较低)。 3. **实时性调整**:如果识别延迟高,尝试减少音频采样率或使用本地引擎。引用中提到,在老旧计算机上可能表现不佳[^3]。 4. **隐私与合规**:使用在线引擎时,确保遵守数据隐私政策(如 GDPR)。 #### 实际应用案例 - **智能助手**:集成到聊天机器人中,实现语音交互。 - **实时字幕**:为视频会议生成实时字幕。 - **无障碍工具**:帮助听障人士转换语音为文本。 通过以上步骤,你可以快速实现 Python 实时语音识别。如需进一步优化,参考官方文档或社区资源[^2][^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值