语音识别FBank特征提取学习笔记

语音识别就是把一段语音信号转换成对应的文本信息,这一过程包括四个大的模块,分别是:特征提取、声学模型、语言模型、字典与解码。

本篇就来梳理一下特征提取模块的实现思路和方法。

常用的语音特征有:

  • 梅尔频率倒谱系数(Mel-Frequency Cepstral Coefficients, MFCC)
  • 梅尔滤波器组系数(Mel Filter Bank, FBank,也叫log-Mel)
  • 线性预测系数(Linear Prediction Coefficient, LPC)

基于深度学习网络的语音识别,目前多采用FBank特征。 获得FBank特征主要包括以下几个步骤:

  1. 预加重;
  2. 分帧、加窗;
  3. 快速傅里叶变换,计算功率谱;
  4. Mel滤波器组;
  5. 取对数,得到FBank。

1. 预加重(Pre-Emphasis)

在音频录制过程中,高频信号更容易衰减,高频成分的丢失,可能导致音素的共振峰不明显,使得声学模型对这些音素的建模能力不强。预加重是个一阶高通滤波器,可以提高信号高频部分的能量。

预加重的实现方法:给定时域输入信号x,预加重之后的信号y为:y(t)=x(t)−αx(t−1),其中0.9≤α≤1.0。经过预加重之后的频谱图和原始的频谱图的比较如下图所示,其中,左侧为原始频谱图,右侧为预加重处理之后的频谱图。

2. 分帧、加窗

语音信号是一个时变的、非稳态的信号,但在短时间范围内可以认为是时不变的、稳态的。这个短时间的长度一般取10~30ms,可在这个时间范围内进行语音信号处理。这就是分帧。

分帧一般采用交叠分段的方法,这是为了使帧与帧之间平滑过渡,保持其连续性。前一帧和后一帧的交叠部分称为帧移,帧移与帧长的比值一般为0~1/2。分帧如下图所示:

分帧之后,需要使用有限长度窗口进行加权处理,也就是加窗,即sw(n) = s(n) * w(n)。那么,为什么要加窗呢?这是因为后面要对信号进行快速傅里叶变换(FFT)。FFT处理的要求是,信号要么从-∞到+∞,要么为周期信号。由于语音信号只能是有限长度信号,并且分帧后的信号是非周期的,进行FFT处理时会存在频率泄露的问题。为了尽可能地减小频率泄露,就需要对信号进行加窗处理。那么,窗函数的选择就需要满足:(1) 窗函数频谱主瓣宽度尽量窄,以得到较高的频率分辨能力;(2) 窗函数旁瓣衰减尽量大,以减少泄露。

下图显示了加窗和不加窗的FFT变换对比:

常用的加窗函数有汉明窗(Hamming)、汉宁窗(Hanning)等。其中,汉明窗的窗函数表达式为:

其中,0≤n≤N−1,N为窗口长度。窗口图形绘制如下:

3. 短时快速傅里叶变换(STFT),计算功率谱

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

4.  Mel滤波器组

人耳对不同频率的声音有不同的感知能力,通常情况下,人耳对低频的感知辨识力比高频更好,为了模拟人耳对不同频率的非线性感知能力,引入了Mel频率。赫兹频率(f)与Mel频率(m)之间的转换关系如下:

该步是通过定义M个三角滤波器组,对上一步得到的功率谱进行滤波。M的取值范围一般在22~40,标准值为26,这里取40。滤波器组中的每个滤波器都是三角形的,中心频率为f(m),该处响应为1,中心频率两边线性减小到0。各f(m)之间的间隔随着m值的增大而变宽,如下图所示:

三角滤波器的定义如下:

f(m)是在Mel尺度上转换回赫兹频率的位置,由于滤波器最终对第3步计算出来的功率谱进行滤波,因此,在实现中,可以将滤波器位置转换成FFT bin所在的位置来计算。为了说明这一点,用一段代码来描述这个过程:

low_freq_mel = 0
high_freq_mel = (2595 * numpy.log10(1 + (sample_rate / 2) / 700))  # Convert Hz to Mel
mel_points = numpy.linspace(low_freq_mel, high_freq_mel, nfilt + 2)  # Equally spaced in Mel scale,在Mel频率范围内均匀创建nfilt+2也就是40个点
hz_points = (700 * (10**(mel_points / 2595) - 1))  # Convert Mel to Hz,将42个点的Mel points转回赫兹频率
bin = numpy.floor((NFFT + 1) * hz_points / sample_rate)   # 将hz_points转换到FFT binfbank = numpy.zeros((nfilt, int(numpy.floor(NFFT / 2 + 1))))for m in range(1, nfilt + 1):f_m_minus = int(bin[m - 1])   # leftf_m = int(bin[m])             # centerf_m_plus = int(bin[m + 1])    # rightfor k in range(f_m_minus, f_m):fbank[m - 1, k] = (k - bin[m - 1]) / (bin[m] - bin[m - 1])     # 三角滤波器左侧for k in range(f_m, f_m_plus):fbank[m - 1, k] = (bin[m + 1] - k) / (bin[m + 1] - bin[m])   # 三角滤波器右侧filter_banks = numpy.dot(pow_frames, fbank.T)  # pow_frames即当前帧的功率谱
filter_banks = numpy.where(filter_banks == 0, numpy.finfo(float).eps, filter_banks)  # Numerical Stability
filter_banks = 20 * numpy.log10(filter_banks)  # dB,进行对数计算,得到最终的FBank特征

5. 取对数,得到FBank

这一步较简单,在上一步的Python代码中,对三角滤波器组的输出取对数,得到最终的FBank特征。不再赘述。

6. 均值归一化(Mean Normalization)

为了平衡频谱并提高信噪比,可以通过减去(所有帧的)系数平均值的方式来进行归一化。

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

7. MFCC特征

由于许多ASR系统使用MFCC特征,这里做一个补充说明。

由于FBank系数存在高度相关性,在一些机器学习系统(如之前流行的GMMs-HMMs)中会存在问题,因此,如果对Fbank进行DCT变换来对FBank系数进行去相关,则可以得到MFCC(Mel-Frequency Cepstral Coefficients)。MFCC是FBank的一种压缩表示。在ASR系统中,一般会保留前2~13个系数,其他的则被丢弃。被丢弃的这些系数表示filter bank的快速变化,这些精细的细节对某些ASR系统是没有贡献的。

mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1 : (num_ceps + 1)] # num_ceps = 2 - 13

 还可以对MFCC应用正弦提升来改善ASR在噪声信号下的识别能力:

(nframes, ncoeff) = mfcc.shape
n = numpy.arange(ncoeff)
lift = 1 + (cep_lifter / 2) * numpy.sin(numpy.pi * n / cep_lifter)
mfcc *= lift  

MFCC也可以应用均值归一化。 

参考资料:

Practical Cryptography

Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What’s In-Between | Haytham Fayek

《人工智能技术》,郑孝宗主编 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/42626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学生管理系统(通过顺序表,获取连续堆区空间实现)

将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数 : 1】顺序表的创建, 2】判满、 3】判空、 4】往顺序表里增加学生信息、 5】遍历学生信息 6】任意位置插入学生信息 7】任意位置删除学生信…

0301STM32GPIO外设输出

STM32GPIO外设输出 STM32内部的GPIO外设GPIO简介基本结构GPIO位结构输入部分:输出部分: GPIO八种工作模式浮空/上拉/下拉输入模拟输入开漏/推挽输出复用开漏/推挽输出 手册寄存器描述GPIO功能描述外设的GPIO配置GPIO寄存器描述端口输入数据寄存器端口输出…

QT入门笔记-自定义控件封装 30

具体代码如下: QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 …

并查集(还有反集也在)

一.定义 定义: 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。 主要构成: 并查集…

PHP-实例-文件上传

1 需求 2 basename 在 PHP 中,basename() 函数用于返回路径中的文件名部分。如果路径中包含了文件扩展名,则该函数也会返回它。如果路径的结尾有斜杠(/)或反斜杠(\),则 basename() 函数会返回空…

Android计算器界面的设计——表格布局TableLayout实操

目录 任务目标任务分析任务实施 任务目标 使用TextView、Button等实现一个计算器界面,界面如图1所示。 图1 计算器界面效果图 任务分析 界面整体使用表格布局,第一行使用一个TextView控件,横跨4列,中间4行4列,最后一…

Laravel HTTP客户端:网络请求的瑞士军刀

标题:Laravel HTTP客户端:网络请求的瑞士军刀 Laravel的HTTP客户端是一个功能强大的工具,它提供了一种简洁、直观的方式来发送HTTP请求。无论是与外部API集成,还是进行网络数据抓取,Laravel的HTTP客户端都能满足你的需…

小红书选品中心商家采集 小红书商家电话采集软件

可采集名称销量评分联系方式等 需要有1000粉丝以上已实名认证过的小红书达人才可以使用 以下是一个示例程序,可以用于批量获取小红书选品中心商家的信息: import requestsdef get_merchants(page_num):url f"https://www.xiaohongshu.com/selec…

git 添加本地分支, clean

//以develop为源创建本地分支fromdevelop git checkout -b fromdevelop git add . git commit -m "local" git checkout -b local/dev //切换到远程分支. git checkout dev git clean_git clean -f -d-CSDN博客 git clean -f -d #删除当前目录下没有被track…

RAC spfile 坑 +data INSTANCE_NUMBER thread x is mounted by another instance

RAC相关三个参数 thread reset 就可以默认 instance_number 需要单独设置 sid‘SIDX’ cluster_database boolean TRUE SQL> alter system reset instance_number sid* scopespfile; alter system reset instance_number sid* scopespfile …

解析Torch中`Transformer`

解析torch官方代码脚本文件:transformer.py。版本:1.9.1cu111。 首先查看《Torch中多头注意力MultiheadAttention的中文注释》解析; 最后查看下方transformer解析。 话不多说,看代码吧! import copy from typing imp…

Vue的学习之class与style绑定

<!DOCTYPE html> <html><head><meta charset"utf-8"><title>Vue的学习</title><script src"vue.js" type"text/javascript" charset"utf-8"></script></head><body><…

如何在std::map中查找元素

在std::map中查找元素可以通过几种不同的方式完成&#xff0c;但最常用的方法是使用find成员函数。std::map是一个基于键值对的关联容器&#xff0c;其中每个元素都是一个键值对。键是唯一的&#xff0c;并且用于排序和快速查找。 使用find成员函数 find成员函数接受一个键作…

io流 多线程

目录 一、io流 1.什么是io流 2.流的方向 i.输入流 ii.输出流 3.操作文件的类型 i.字节流 1.拷贝 ii.字符流 ​3.字符流输出流出数据 4.字节流和字符流的使用场景 5.练习 6.缓冲流 1.字节缓冲流拷贝文件 2.字符缓冲流特有的方法 1.方法 2.总结 7.转换流基本用法…

第2集《修习止观坐禅法要》

请打开补充讲表第一面&#xff0c;附表一、念佛摄心方便法。 我们前面讲到修止&#xff0c;就是善取所缘境的相貌&#xff0c;然后心于所缘&#xff0c;专一安住&#xff1b;心于所缘&#xff0c;相续安住&#xff1b;达到心一境性的目的。 站在修学净土的角度&#xff0c;他…

FastAPI+SQLAlchemy数据库连接

FastAPISQLAlchemy数据库连接 目录 FastAPISQLAlchemy数据库连接配置数据库连接创建表模型创建alembic迁移文件安装初始化编辑env.py编辑alembic.ini迁移数据库 视图函数查询 配置数据库连接 # db.py from sqlalchemy import create_engine from sqlalchemy.orm import sessio…

9、程序化创意

程序化创意 程序化创意&#xff08;Programmatic Creative&#xff09;是指通过自动化的方式制作并优化广告创意&#xff0c;以提高广告效果。针对不同受众的多样化需求&#xff0c;以及同一受众在不同场景下的消费需求&#xff0c;程序化创意能够自动生成个性化的精准创意&am…

《C语言》预处理

文章目录 一、预定义符号二、#define定义常量三、#define定义宏四、宏更函数的对比五、#和##1、#运算符2、##运算符 一、预定义符号 C语言设置了一些预定义符号&#xff0c;可以直接使用&#xff0c;在预处理期间进行处理的。 __FILE__//进行编译的源文件 __LINE__//文件当前的…

在网站存在漏洞的情况下强化安全防御

一、引言 网络安全是一个持续的战斗&#xff0c;尤其是在网站存在已知或未知漏洞的情况下。本文将探讨如何在网站存在漏洞的情况下&#xff0c;采取有效措施进行安全防御。 二、理解漏洞 首先&#xff0c;我们需要理解网站的漏洞。这些可能包括SQL注入、跨站脚本&#xff08…

【数据结构与算法】插入排序

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​