Skip to content

hungryzzz/Speech-Recognition

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

孤立词识别

识别算法

归一化

  • 由于在采集数据的时候,每个人的音量各不相同,因此需要对音频进行归一化处理。归一化处理的基本原理是:取音频中幅度最大的点,将其幅度拉大到接近1的比例,再将其他所有点均按照这个比例拉伸。

端点检测

  • 在识别中,我们希望从带噪声的信号中得到纯净的语音信号,以此来减小噪声对识别过程的干扰,因此通过信号的时域特征来进行端点检测。本实验采用短时能量和短时过零率来进行测定。

平均短时能量

  • 由于在一段语音信号中,包含语音的信号强度比背景噪声大得多,而短时能量就是衡量信号强度的 指标之一,因此可以用它来进行端点检测。
  • 对信号进行分帧、加窗之后,$S_{w}[i : j]$的短时能量可以定义为$$STE = \sum_{n=i}^{j} S_{w}(n)^2$$即每一帧信号的的平方和。

平均短时过零率

  • 仅仅以短时能量作为端点检测的指标还是不够的,如果是像speech这样以清音开头的单词,则无法正确得到其端点,因为清音的短时能量与背景噪声接近。因此还需要引入短时过零率。

  • 同样对信号进行分帧、加窗之后,$S_{w}[i : j]$的短时过零率可以定义为$$STZCR = \frac{1}{2} \sum_{k=i}^{j-1} abs[sgn(S_{w}[k+1]) - sgn(S_{w}[k])]$$即每一帧内信号通过0的次数。

  • 由于出现在端点处的清音无法用短时能量与噪声加以区别,因此采用以短时能量为主、短时过零率为辅的方法来进行端点检测。

    • 首先,在观察音频后发现,在录音的开始和结束的时候均有可能会有一段能量较高的噪声(比如点击鼠标,移动耳机等),因此我删除了信号的前后十帧,将其信号置为0。
    • 接着再设置一个较高的短时能量阈值$E_{Max}$,先从信号两端向中间检测,若是遇到第一个短时能量大于该阈值的帧,则将其记录为$N_{1}$。
    • 再设置一个较低的短时能量阈值$E_{Min}$,再从$N_{1}$开始往信号的两端进行检测,若是遇到第一个短时能量小于该阈值的帧,则将其记录为$N_{2}$。
    • 最后再根据短时过零率的指标,设置一个较高的短时过零率阈值$ZRC_{0}$,从$N_{2}$开始往信号的两端进行检测,遇到第一个短时过零率小于该阈值的帧,则将其标注为信号的端点。

端点检测结果

1

2

预加重

  • 由于语音信号的功率谱随着频率的增加而减小,其大部分能量集中在低频范围内,这就会造成信号高频段的信噪比可能降到不能容许的程度。因此使用预加重使语音信号的高频特性更加突出。
  • 对于$y_{n} = x_{n} - \alpha x_{n-1}$的系统而言,其传递函数是$H_{z} = 1- az^{-1}$,为一个一阶线性高通滤波器。因此,只要让信号通过该高通滤波器就能增强其高频部分。在代码实现上,只要对数组进行加权差分就能实现。

预加重前后信号波形对比

3

分帧

  • 后续做梅尔频率域特征抽取的时候,需要对信号进行傅里叶变换。由于傅里叶变换要求输入的信号是平稳的,而语音从宏观来说是不平稳的(声道形状一改变,信号的特征就会变化)。但从微观上看,在较短的时间内,语音信号就可以看成是平稳的,就可以截取出来进行傅立叶变换。
  • 帧长的选择需要满足两个条件:
    • 从宏观上看,它必须足够短来保证帧内的信号是平稳的,所以在一帧的期间内口型是不能有明显变化的,即一帧的长度应该小于一个音素的长度。正常情况下音素持续时间约为50-200ms,因此帧长一般要小于50ms。
    • 从微观上讲,它又必须包括足够多的振动周期,因为傅里叶变换是频谱分析,只有重复足够多次才能分析频率。男性的基音频率在100HZ左右,换算成周期即为10ms,而一帧需要包含多个周期,所以一般选择20-30ms。

加窗

  • 分帧得到的信号在进行傅立叶变换之前需要进行加窗,实现上即与一个窗函数相乘。加窗的目的是让一帧信号的幅度在两端渐变到0,渐变可以提高傅里叶变换得到的频谱的分辨率。
  • 而加窗的代价是一帧信号的两段部分被削弱了,因此通过帧与帧之间相互重叠一部分来弥补。

梅尔频率域特征

  • Mel频率分析是基于人类听觉感知实验的。实验观测到人耳类似一个滤波器,它只会关注某些特定的频率分量(人的听觉对频率是有选择性的),也就是说,它只会让某些频率的信号通过,而无视其他频率信号。但是这些滤波器在频率坐标轴上不是同一分布的,在低频区域有很多滤波器,分布比较密集,而在高频区域,滤波器的数量就减小,分布比较稀疏。
  • 梅尔频率倒谱系数考虑到了人类听觉上的特征,先将线性频谱映射到基于听觉感知的Mel非线性频谱中,然后转换到倒谱上。通过$$mef(f) = 2595 * \log(1 + f / 700)$$就可以将普通频率转化到Mel频率。在Mel频域内,人对音调的感知度为线性关系,即若两段语音的Mel频率相差两倍,则人耳听起来二者的音调也相差两倍。
  • 从代码实现上看,要得到梅尔频率域特征,通过前述对信号进行端点检测,预加重,分帧和加窗后,对每一帧信号通过傅里叶变换得到相应的频谱;再将该频谱通过Mel滤波器组(等间距的三角滤波)得到Mel频率;最后在Mel频谱上取对数即可获得Mel功率下的功率谱。通过观察后可发现,对于同一个词来说,得到的功率谱有明显相同的特征,因此可将其视为图片,利用图片分类对其进行语音识别。
  • 传统上的语音识别会继续对Mel频谱做离散余弦变换(DCT)来求出倒谱系数,而后选取前13个系数作为特征。

识别模型

本实验识别模型采用Pytorch神经网络框架完成。比较了以VGG11和LSTM 作为模型的结果,最终选取VGG11。

模型构建

  • 本实验通过对功率谱进行分类来实现语音识别,因此选择VGG11模型作为本实验的模型:使用3 * 3的卷积核构建的8层深度卷积神经网络。具体结构如下:\

model

模型训练

  • 利用了Pytorch提供的BP模块,选择交叉熵作为损失函数,Adam作为梯度优化器。

前端界面

  • 为了操作方便,使用JQueryBootstrap实现了前端界面,提供了录音和预测的功能。

界面如下

8

服务器端

  • 通过flask实现了前端界面和后端预测模块的交互。
  • 运行该服务,则先会加载模型,然后等待前端的请求。

实验设置及数据集

实验设置

端点检测、预加重

  • 帧长为10ms,步长为帧长的一半
  • 通过多次尝试,最终$E_{Max}$ = 2, $E_{Min}$ = 1, $ZCR_{0}$ = 40
  • $\alpha$ = 0.97

分帧、加窗、梅尔频率域特征

  • 帧长为30ms,步长为10ms
  • 窗函数选择汉明窗
  • Mel滤波器组个数为128,最终得到的梅尔频率域特征为128 * 100
  • 下图为汉明窗波形图

4

模型参数

  • batch size = 32
  • 迭代次数 = 15
  • 学习率在前10次迭代中为4e-5,后5次迭代中为1e-5

数据集

  • 本实验先实现了预处理模块,将每个音频通过该模块后即可获得梅尔频率域特征,将每个特征进行保存以方便后续模型训练。
  • 本实验随机抽取每个人的每个词的音频作为验证集,因此大约有600个,其余数据为训练集。

实验结果分析与讨论

下图为不同人念同一个单词时的功率图

5

  • 训练结束后,在训练集上能获得99.27%的准确率,在验证集上能获得94.71%的准确率。可以看出VGG11模型在该实验中效果较好。

6

结论

  • 在本实验中,我实现了一个效果较好的孤立词识别系统,可以看出梅尔频率域特征确实是能反映出一段语音信号的特征,以及VGG11模型在该实验中表现较好。
  • 通过对一些基本功能的实现,更加加深了我对相关知识的印象和理解。

参考文献

  1. Speech-Recognition-Via-CNN
  2. 语音信号处理之(四)梅尔频率倒谱系数(MFCC)
  3. python_speech_features
  4. VGG