01 食物语音识别baseline

1、任务背景:对不同事物咀嚼声音进行分类

2、算法模型:基于CNN的语音分类,原始语音信息提取为fbank特征,输入CNN卷积池化,再训练分类

3、需要的环境:

TensorFlow:一种人工智能训练框架,学习链接

https://github.com/aymericdamien/TensorFlow-Examples

keras:也是一种人工智能框架,Keras由纯Python编写而成并基于Tensorflow、Theano以及CNTK后端,相当于Tensorflow、Theano、CNTK的上层接口,号称10行代码搭建神经网络,具有操作简单、上手容易、文档资料丰富、环境配置容易等优点,简化了神经网络构建代码编写的难度。目前封装有全连接网络、卷积神经网络、RNN和LSTM等算法。学习链接

https://keras.io/zh/

sklearn:Scikit-learn(sklearn)是机器学习中常用的第三方模块,对常用的机器学习方法进行了封装,包括回归(Regression)、降维(Dimensionality Reduction)、分类(Classfication)、聚类(Clustering)等方法。学习链接

https://www.jianshu.com/p/6ada34655862

librosa:Librosa是一个用于音频、音乐分析、处理的python工具包。学习链接

https://blog.csdn.net/zzc15806/article/details/79603994

4、数据集:

训练集:http://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531887/train_sample.zip

测试集:http://tianchi-competition.oss-cn-hangzhou.aliyuncs.com/531887/test_a.zip

5、baseline源码:

https://github.com/datawhalechina/team-learning-nlp/tree/master/FoodVoiceRecognition

6、知识拓展:

常用语音特征:MFCC、fbank、语谱图、PLP、CQCC

语音格式:WAV、PCM、MP3

MFCC提取过程,转引至:https://blog.csdn.net/wudibaba21/article/details/108863431

语音参数提取特征

分帧 ——> 预增强 ——> 加窗 ——> 添加噪声 ——> FFT ——> Mel滤波 ——> 对数运算——> DCT

分帧

我们需要将不定长的音频切分成固定长度的小段,这一步称为分帧。一般取10-30ms为一帧,为了避免窗边界对信号的遗漏,因此对帧做偏移时候,要有帧迭(帧与帧之间需要重叠一部分)。 一般取帧长的一半作为帧移,也就是每次位移一帧的二分之一后再取下一帧,这样可以避免帧与帧之间的特性变化太大。通常的选择是25ms每帧,帧迭为10ms。接下来的操作是对单帧进行的。

要分帧是因为语音信号是快速变化的,而傅里叶变换适用于分析平稳的信号。在语音识别中,一般把帧长取为10~30ms,这样一帧内既有足够多的周期,又不会变化太剧烈。每帧信号通常要与一个平滑的窗函数相乘,让帧两端平滑地衰减到零,这样可以降低傅里叶变换后旁瓣的强度,取得更高质量的频谱。帧和帧之间的时间差常常取为10ms,这样帧与帧之间会有重叠,否则,由于帧与帧连接处的信号会因为加窗而被弱化,这部分的信息就丢失了。傅里叶变换是逐帧进行的,为的是取得每一帧的频谱。一般只保留幅度谱,丢弃相位谱。

预增强

预增强以帧为单位进行,目的在于加强高频。数学公式如下:

s(n)=s(n)−k∗s(n−1),∀n∈Ns(n)=s(n)−k∗s(n−1),∀n∈N

k是预增强系数,范围为[0, 1),常用0.97,N是每一帧的长度,从公式可以看出每一帧的第一个数需要特殊处理。

加窗

语音在长范围内是不停变动的,没有固定的特性无法做处理,所以将每一帧代入窗函数,窗外的值设定为0,其目的是消除各个帧两端可能会造成的信号不连续性。常用的窗函数有方窗、汉明窗等,根据窗函数的频域特性,常采用汉明窗,其对应的窗函数如下:


s′n=(0.54−0.46cos(2π(n−1)N−137))snsn′=(0.54−0.46cos⁡(2π(n−1)N−137))sn

加窗过程其实就是将data[0:n-1]与w[0:n-1]对应相乘。

注意:预增强和加窗同时使用时,要首先进行预增强

添加随机噪声

有时候我们需要进行数据增强,会手动合成一些音频。某些人工合成(使用软件)的音频可能会造成一些数字错误,诸如underflow或者overflow。 这种情况下,通过添加随机噪声可以解决这一类问题。公式如下:

s(n)=s(n)+q∗rand()s(n)=s(n)+q∗rand()

q用于控制添加噪声的强度,rand() 产生[ -1.0, 1.0 )的随机数。

注意:Kaldi中是在分帧之后的下一步添加随机噪声

FBank

背景

人耳对声音频谱的响应是非线性的,经验表明:如果我们能够设计一种前端处理算法,以类似于人耳的方式对音频进行处理,可以提高语音识别的性能。FilterBank分析就是这样的一种算法。FBank特征提取要在预处理之后进行,这时语音已经分帧,我们需要逐帧提取FBank特征。

提取FBank特征

傅里叶变换

我们分帧之后得到的任然是时域信号,为了提取FBank特征,首先需要将时域信号转换为频域信号。傅里叶变换可以将信号从时域转到频域。傅里叶变换可以分为连续傅里叶变换和离散傅里叶变换,因为我们用的是数字音频(而非模拟音频),所以我们用到的是离散傅里叶变换

快速傅里叶变换(fft)

我们分帧之后得到的仍然是时域信号,为了提取fbank特征,首先需要将时域信号转换为频域信号。傅里叶变换可以将信号从时域转到频域。傅里叶变换可以分为连续傅里叶变换和离散傅里叶变换,因为我们用的是数字音频(而非模拟音频),所以我们用到的是离散傅里叶变换。数学公式如下:


X(k)=∑j=1Nx(j)w(j−1)(k−1)NX(k)=∑j=1Nx(j)wN(j−1)(k−1)

公式比较难以理解,可以想象一下傅里叶级数,一个函数可以用其他基本函数组合逼近。从公式可以看出,傅里叶变化的计算复杂度较高,因此我们通常使用的是快速傅里叶变换(fft)。

信号频率 : 组合产生复杂信号的简单信号的频率,通常简单信号平率范围很广

采样频率 : 模拟到数字的转换过程中,需要对模拟信号进行采样,每秒内的采样点数量就是采样频率

Nyquist定理(奈奎斯特): 如果想要从数字信号无损转到模拟信号,我们需要以最高信号频率的2倍的采样频率进行采样。通常人的声音的频率大概在3kHz~4kHz ,因此语音识别通常使用8k或者16k的wav提取特征。16kHz采样率的音频,傅里叶变换之后的频率范围为0-8KHz。

计算能量谱

傅里叶变换完成后,我们得到的是频域信号,每个频带范围的能量大小不一,不同音素的能量谱不一样。有两种计算方法:

magnitude = sqrt(real*real + image*image)

power = real*real + image*image

注意:htk同时支持这两种方式,kaldi只支持第二种

Mel滤波

Mel滤波的过程如下图:

图中三角窗口表示滤波窗口。三角窗口可以覆盖从0到Nyquist的整个频率范围,通常我们会设定频率上限和下限,屏蔽掉某些不需要或者有噪声的频率范围。三角形的数量表示Mel滤波之后特征向量的维度,一般取40个。


M(b)=∑j=1bjmelb(j)∗mb(j)M(b)=∑j=1bjmelb(j)∗mb(j)

关于这一部分的详细情况,每个三角形对应的滤波系数可以查看

Mel系数计算, 滤波计算参考滤波计算

mel倒谱公式:


Mel(f)=2595∗log10(1+f700)Mel(f)=2595∗log10⁡(1+f700)

对数运算

Mlog(b)=log(M(b))Mlog(b)=log⁡(M(b))

这一步就是取上一步结果的对数。简单点理解,它是对纵轴的放缩,可以放大低能量处的能量差异;更深层次地,这是在模仿倒谱(cepstrum)的计算步骤。

mfcc

FBank特征已经很贴近人耳的响应特性,但是仍有一些不足:FBank特征相邻的特征高度相关(相邻滤波器组有重叠),因此当我们用HMM对音素建模的时候,几乎总需要首先进行倒谱转换,通过这样得到MFCC特征。

MFCC特征的提取是在FBank特征的基础上再进行离散余弦变换, 因此前面几步和FBank一样.

离散余弦变换(DCT)

假设做完取Log之后,我们得到N维的特征向量Mlog。离散余弦变换公式如下:

N是取Log之后的特征维度,M 是 DCT(离散余弦变换)之后的特征维度。DCT的实质是去除各维信号之间的相关性,将信号映射到低维空间。

离散余弦变换(discrete cosine transform,DCT)是傅里叶变换的一个变种,好处是结果是实数,没有虚部。DCT还有一个特点是,对于一般的语音信号,这一步的结果的前几个系数特别大,后面的系数比较小,可以忽略。上面说了一般取40个三角形,所以DCT的结果也是40个点;实际中,一般仅保留前12~20个,这就进一步压缩了数据。

均值方差归一化(CMVN)

实际情况下,受不同麦克风及音频通道的影响,会导致相同音素的特征差别比较大,通过CMVN可以得到均值为0,方差为1的标准特征。均值方差可以以一段语音为单位计算,但更好的是在一个较大的数据集上进行计算,这样识别效果会更加稳健。Kaldi中计算均值和方差的代码compute-cmvn-stats.cc, 归一化apply-cmvn.cc。


fbank与mfcc的比较

fbank特征更多是希望符合声音信号的本质,拟合人耳的接收特性。

DCT是线性变换,会丢失语音信号中原本的一些高度非线性成分。在深度学习之前,受限于算法,mfcc配GMMs-HMMs是ASR的主流做法。当深度学习方法出来之后,由于神经网络对高度相关的信息不敏感,mfcc不是最优选择,经过实际验证,其在神经网络中的表现也明显不如fbank。

有人质疑是否需要傅里叶变换,其根据是傅里叶变换也是一种线性变换,也会使得语音信号中的非线性成分丢失,因此是不是有可能对时域信号进行直接处理的效果会更好。经实验证明,信号经过傅里叶变换后比直接处理时域信号的效果更好,这是因为傅里叶变换本身不容易被拟合,不可避免地会增加模型的复杂度。此外,傅里叶变换是在短时上应用的,可以假设信号在短时内是线性的,因此,傅里叶变换的线性不会造成很严重的问题。

你可能感兴趣的:(01 食物语音识别baseline)