0%

语音识别简介(一)——特征提取

上学期,我们学习了 “Design and Implementation of Speech Recognition System” 这门课 (CMU 18799)。通过这门课的学习,我们了解语音识别的基础知识并最终实现了连续语音的识别(采用HMM-GMM模型)。本文主要介绍下进行语音识别前的一些预处理工作,即是如何提取出特征的。

就提取特征的预处理而言,具体可以分为这几个步骤:采样、分帧加窗、endpointing、MFCC、DCT到一个确定的维度。

Sampling 采样(录制)

现实中的声音属于一种模拟信号,要想让计算机能够对声音进行处理,我们首先要做的就是将模拟信号转换为数字信号。那么我们又该如何用计算机实现这个采样的过程呢?在具体操作的过程中,我们使用的是 PortAudio 开源库来录制声音。

我当时是在Mac OS系统下用Xcode配置了PortAudio,具体的配置过程可以参见这篇博文,在此不作赘述。

于是通过PortAudio这个库我们可以实现语音的录制,即采样。得到的文件中的数值参见具体的文件后缀格式而定。接下来我们需要对语音进行分帧处理

分帧加窗

为了更好地去除噪声的影响,我们需要加一个preemphasize 的过程:即 $s[n] = s[n] - \alpha * s[n - 1],\alpha$一般接近1.

在Mac OS系统下,一般采用的采样频率是44100hz,每个点代表的时间约为0.02ms,对于声音信号而言,这个范围太小了,既没有区间差异性又会导致计算量的增多,所以我们这里将20ms这一时间段视为一个特征点,这就需要我们进行分帧处理,一般采用移动窗函数来实现,帧与帧之间有overlap,这里我们将overlap定为10ms,之所以要有overlap是为了更好地描述上一帧中被忽略的部分,防止信息的丢失。

由于有了overlap,所以如果用rectangular 窗函数进行分帧的话会导致不平滑的现象,在这里我们采用hanning窗函数进行分帧,可以得到平滑的帧。同时加窗函数的意义还在于可以比截断部分刚好地体现出原始信号的频率信息:

最终得到的是就是一帧帧的信号(可以理解为一个二维数组)。

Endpointing

对于一串语音而言,其中有很大的一部分是没有声音的,尤其是以开头和结尾处为主。较多的non-speech部分不仅会导致不必要的计算负担,同时还可能会将non-speech的部分错误地识别成一些词。

为了防止出现这种现象,我们首先要找出speech region,即做一个endpointing:

如何endpointing呢?我们基于的原理就是speech region较之non-speech region有着较高的能量。一种最简单的方法就是直接对信号施加一个阈值,当能量超过阈值的时候,其对应的就很有可能是speech region。当然这种方法忽略了背景噪音等一些因素,因此往往不能准确对speech region进行划分。下面介绍两种更加准确的endpointing的方法:

第一种也叫做 Adaptive Endpointing Algorithm,其核心思想就是用一个smoothed signal level 和一个fast-varying estimation of background进行比较,之所以被称为adaptive就是指adapt background level。 伪代码见下图:

另一种更复杂一点的方法就是对speech部分的开始和结尾分别处理:开始部分会有一个很明显的能力增加的过程,即便是在高噪声的环境中仍然如此;而结束的部分由于延长音等一些因素,使得能量的降低不是那么明显,尤其是在高噪声的环境中更是如此,所以我们采用两个阈值分别处理语音的开始部分和结尾部分。伪代码见下:

MFCC

经过上述处理后,我们得到了一个包含着较少non-speech region的一帧帧信息,然而这里的信息都只是在时域上的,不能反映出什么,我们需要对其进行傅里叶变换,将其转为频域上的信息。

这里为了方便进行fft快速傅里叶变换,我们需要先进行zero padding的过程,关于zero-padding可以参见我之前的一篇博文

将其转到频域之后,我们好像需要将频率匹配到是和人耳听觉的区域(即mel域)

mel域可以认为是对频域做一个warp的过程,每处的warp不同。这主要是由于人耳对低频变化比较敏感而对高频的不敏感。频域到mel域的公式为:

下图中横轴是原始频域,纵轴是mel域。

实际操作时我们一般用一定数量的filter bank得到对应数目的mel域的值(一般采用三角滤波)(one value per filter)

为了对数据进行更好地压缩,我们再对求得的mel spectrum做一个log变换(同时也是为了reduce imbalance)

DCT变换

得到了log mel spectrum的值后,每一帧的维度可以认为是filter的数目,为了方便计算我们还需要对其进行降维处理,这里采用的是DCT变换将维度变为13维。在DCT中减去的维度在不同声音间有着较小的变化。

在得到13维的特征向量之后,我们还想进一步得到一些关于频率变化的信息,于是我们对13维的每一维分别求一阶导和二阶导(由于一帧的时间很短,可以认为是$\Delta t$)最终得到的特征向量有39维度

通过上述这些方法,我们就得到了进行语音识别的特征点。

在下一节中我将介绍如何用DTW to HMM的方法进行简单的语音识别。

项目代码

这一部分的相关代码可以详见我的github中的 SpeechRecognition项目