在 github 上面找到了三个比较酷的说话人识别的代码:
Python 2 版本:https://github.com/ppwwyyxx/speaker-recognition
python 3版本(在python2版本下进行修改):https://github.com/crouchred/speaker-recognition-py3
说话人识别(声纹识别)的简介在我前面的简书有提到,有兴趣的宝宝可以去前面看看。//www.greatytc.com/p/19d34b19517b
上周五 我用Aishell的数据跑,准确率100%。这周我将对我收集到的另外的安静的,但是没有怎么做预处理的语音再去跑一次,希望有好消息嘻嘻!几个最新免费开源的中文语音数据集 | AI柠檬
这周我录了几个朋友的声音(有一点点噪声)去跑,训练集大概30个人,每个人语音大概20条,然后放2条去测试,准确率有91.5%!!!算是比较优秀的模型了!!!
今天记录一下自主学习说话人识别的知识,下面主要是根据下面的python3版本进行记录。
模块介绍
下面会介绍几个在代码中出现的比较重要的模块:
collections:collections是Python内建的一个集合模块,提供了许多有用的集合类。想详情了解的可以看一下廖雪峰老师的总结。
Pickle:将对象转换为一种可以传输或存储的格式。经常遇到在Python程序运行中得到了一些字符串、列表、字典等数据,想要长久的保存下来,方便以后使用,而不是简单的放入内存中关机断电就丢失数据,这个时候Pickle模块就派上用场了。
python_speech_features:这个模块是专门用来提取语音特征的。这个库提供了一般的用于ASR(语音识别)的语音特征,他包含了MFCCs(梅尔倒谱系数)和 FilterBank energies。后面我会详细解说。
operator:operator模块输出一系列对应Python内部操作符的函数。
sklearn:是数据挖掘和数据分析方面的一个简单而有效的工具,主要包括6大功能:分类(Classification),回归(Regression),聚类(Clustering),降维(Dimensionality Reduction),模型选择(Model Selection)和预处理(Preprocessing)。
argparse:在多个文件或者不同语言协同的项目中,python脚本经常需要从命令行直接读取参数。万能的python就自带了argprase包使得这一工作变得简单而规范。PS:optparse包是类似的功能,只不过写起来更麻烦一些。
itertools:itertools用于高效循环的迭代函数集合。
声谱图介绍
这段语音被分为很多帧,每帧语音都对应于一个频谱是通过短时FFT(Fast Fourier Transformation,快速傅里叶变换)计算的,频谱表示频率与能量的关系。频谱图就是描述在某一时间点上,各个频率的声音分布情况。在实际使用中,频谱图有三种,即线性振幅谱、对数振幅谱、自功率谱(对数振幅谱中各谱线的振幅都作了对数计算,所以其纵坐标的单位是dB(分贝)。这个变换的目的是使那些振幅较低的成分相对高振幅成分得以拉高,以便观察掩盖在低幅噪声中的周期信号)。
我们先将其中一帧语音的频谱通过坐标表示出来,如下图左。现在我们将左边的频谱旋转90度。得到中间的图。然后把这些幅度映射到一个灰度级表示(也可以理解为将连续的幅度量化为256个量化值?),0表示黑,255表示白色。幅度值越大,相应的区域越黑。这样就得到了最右边的图。那为什么要这样呢?为的是增加时间这个维度,这样就可以显示一段语音而不是一帧语音的频谱,而且可以直观的看到静态和动态的信息。
这样我们会得到一个随着时间变化的频谱图,这个就是描述语音信号的spectrogram声谱图。
下图是一段语音的声谱图,很黑的地方就是频谱图中的峰值(共振峰formants)。
重点算法介绍
一、LTSD(Long-term Spectral Divergence)
信号必须首先被过滤,以排除沉默部分,否则训练可能会有严重的偏差。所以,必须首先执行VAD(Voice Activity Detection,语音活动检测),目的就是从复杂的环境中区分出语音部分和非语音部分。一项观察发现,提供的语料库几乎是无噪音的。因此,我们使用一种简单的基于能量的方法来去除沉默部分,只需去掉平均能量低于整个演讲的平均能量的0.01倍的帧。而LTSD(Long-term Spectral Divergence,长时谱能量差异)就可以完成这个工作。
LTSD算法将语音分解为重叠帧,并根据该帧中存在语音活动的可能性给出每个帧的评分。这一概率将累积起来,以提取所有具有语音活动的间隔。一幅描绘LTSD的图片如下:
二、MFCC(Mel Frequency Cepstral Coefficents)
在任意一个语音自动识别(ASR,Automatic speech recognition) 系统中,第一步就是提取特征。换句话说,我们需要把音频信号中具有辨识性的成分提取出来,然后把其他的乱七八糟的信息扔掉,例如背景噪声啊,情绪啊等等。
MFCC(Mel Frequency Cepstral Coefficents,梅尔频率倒谱系数)是一种表示声音的短期功率谱的方法,它基于对数功率谱在非线性Mel尺度上的线性余弦变换。MFCC是语音ASR中应用最广泛的特征,也可以应用于说话人识别任务中。
梅尔频率是基于人耳听觉特性提出来的, 它与Hz频率成非线性对应关系。梅尔频率倒谱系数(MFCC)则是利用它们之间的这种关系,计算得到的Hz频谱特征。主要用于语音数据特征提取和降低运算维度。例如:对于一帧有512维(采样点)数据,经过MFCC后可以提取出最重要的40维(一般而言)数据同时也达到了将维的目的。
上图是MFCC的基本流程,其中最重要的就是FFT和梅尔滤波器组,这两个进行了主要的降维操作。
1、预加重
预加重处理其实是将语音信号通过一个高通滤波器:
其中的值介于之间,我们通常取。
预加重的目的是提升高频部分,使信号的频谱变得平坦,保持在低频到高频的整个频带中,能用同样的信噪比(信号与噪声的比例)求频谱。同时,也是为了消除发生过程中声带和嘴唇的效应来补偿语音信号收到发音系统所抑制的高频部分,也为了突出高频的共振峰。
2、分帧
为了方便对语音分析,可以将语音分成一个个小段,称之为帧。先将N个采样点集合成一个观测单位,即帧。通常情况下N的值为或,涵盖的时间约为左右。为了避免相邻两帧的变化过大,因此会让两相邻帧之间有一段重叠区域,此重叠区域包含了个取样点,通常M的值约为的或。通常语音识别所采用语音信号的采样频率为或,以来说,若帧长度为个采样点,则对应的时间长度是。
3、加窗
语音在长范围内是不停变动的,没有固定的特性无法做处理,所以将每一帧代入窗函数,窗外的值设定为0,其目的是消除各个帧两端可能会造成的信号不连续性。常用的窗函数有方窗、汉明窗和汉宁窗等,根据窗函数的频域特性,常采用汉明窗。
将每一帧乘以汉明窗,以增加帧左端和右端的连续性。假设分帧后的信号为,,为帧的大小,那么乘上汉明窗后,形式如下:
4、FFT(Fast Fourier Transformation,快速傅里叶变换)
由于信号在时域上的变换通常很难看出信号的特性,所以通常将它转换为频域上的能量分布来观察,不同的能量分布,就能代表不同语音的特性。目的是获得能量分布在时间轴上不同时间窗内的频谱,即能量谱。所以在乘上汉明窗后,每帧还必须再经过快速傅里叶变换以得到在频谱上的能量分布。对分帧加窗后的各帧信号进行快速傅里叶变换得到各帧的频谱。并对语音信号的频谱取模平方得到语音信号的功率谱。
FFT是DFT的一种高效快速算法。DFT(Discrete Fourier Transform,离散傅里叶变换),是傅里叶变换在时域和频域上都呈离散的形式,将信号的时域采样变换为其DTFT(Discrete Time Fourier Transform离散时间傅里叶变换)的频域采样。
设语音信号的DFT为:
其中为输入的语音信号,为傅里叶变换的点数
5、Mel滤波器(三角带同滤波器)
将能量谱通过一组Mel尺度的三角形滤波器组,定义一个有M个滤波器的滤波器组(滤波器的个数和临界带的个数相近),采用的滤波器为三角滤波器,中心频率为M。M通常取。各之间的间隔随着值的减小而缩小,随着值的增大而增宽,如图所示:
三角带通滤波器有两个主要目的:对频谱进行平滑化,并消除谐波的作用,突显原先语音的共振峰。(因此一段语音的音调或音高,是不会呈现在MFCC 参数内,换句话说,以MFCC 为特征的语音辨识系统,并不会受到输入语音的音调不同而有所影响)此外,还可以降低运算量。通过Mel频谱,将线形的自然频谱转换为体现人类听觉特性的Mel频谱
三角滤波器的频率响应定义为:
6、对数运算
计算每个滤波器组输出的对数能量.
7、DCT(Discrete Cosine Transform,离散余弦变换)
经DCT得到MFCC系数
将上述的对数能量带入DCT中,求出阶的Mel-scale Cepstrum参数。阶指MFCC系数阶数,通常取。这里M是三角滤波器个数。一般取DCT后的第2个到第13个系数作为MFCC系数。
8、对数能量(可用于完善)
此外,一帧的音量(即能量),也是语音的重要特征,而且非常容易计算。因此,通常再加上一帧的对数能量(定义:一帧内信号的平方和,再取以10为底的对数值,再乘以10)使得每一帧基本的语音特征就多了一维,包括一个对数能量和剩下的倒频谱参数。
注:若要加入其它语音特征以测试识别率,也可以在此阶段加入,这些常用的其它语音特征包含音高、过零率以及共振峰等。
9、动态差分参数的提取(包括一阶差分和二阶差分)
标准的倒谱参数MFCC只反映了语音参数的静态特性,语音的动态特性可以用这些静态特征的差分谱来描述。实验证明:把动、静态特征结合起来才能有效提高系统的识别性能。差分参数的计算可以采用下面的公式:
其中,表示第个一节差分,表示第个DCT,表示DCT的阶数,表示一阶导数的时间差,可取或。将上式的结果再代入就可以得到二阶差分的参数。
MFCC的全部组成:维MFCC参数(MFCC系数(DCT)+一阶差分参数+二阶差分参数)+帧能量(此项根据需求添加替换)
三、GMM-UBM(混合高斯-通用背景模型)
在上一篇声纹学习的文章中,我曾向大家介绍过GMM(高斯混合模型)。GMM将空间分布的概率密度用多个高斯概率目睹函数的加权来拟合,可以平滑地逼近任意形状的概率密度函数,并且是一个易于处理的参数模型,具备对实际数据极强的表征力。但反过来,GMM规模越庞大,表征力越强,其负面效应也会越明显:参数规律也会等比例的膨胀,需要更多的数据来驱动GMM的参数训练才能得到一个更加通用(或称泛化)的GMM模型。
在实际中每一个说话人的语音数据很少,这将导致无法训练出高效的GMM模型。并且由于多通道的问题,训练GMM模型的语音与测试语音存在失配的情况,这些因素都会降低声纹识别系统的性能。所以机器学习的前辈们(DA Reynolds的团队)提出了一个通用背景模型(Universal Background Model, 简称UBM)。我们可以用UBM和少量的说话人数据,通过自适应算法(如最大后验概率MAP、最大似然线性回归MLLR等,本文选择阐述MAP算法)来得到目标说话人模型。
GMM-UBM实际上是一种对GMM的改进方法,我们既然没法从目标用户那里收集到足够的语音,那就换一种思路,可以从其他地方收集到大量非目标用户的声音,我们将这些非目标用户数据(声纹识别领域称为背景数据)混合起来充分训练出一个GMM,这个GMM可以看作是对语音的表征,但是又由于它是从大量身份的混杂数据中训练而成,它又不具备表征具体身份的能力。我们可以把这种模型看作是某一个具体说话人模型的先验模型。形象的比方就是说你准备去相亲,媒人给你看了小莉的照片,你耳边浮现的肯定是小莉各种可能的温柔的声音,而不是你家旺财的叫声。这种GMM-UBM就是起到类似的作用,它对语音特征在空间分布的概率模型给出一个良好的预先估计,让我们可以提前训练GMM。然后将目标用户的数据在这个模型上进行参数的微调即可。GMM-UBM模型最重要的优势就是通过MAP算法对模型参数进行估计,避免了过拟合的发生,同时我们不必调整目标用户GMM的所有参数(权重,均值,方差)只需要对各个高斯成分的均值参数进行估计,就能实现最好的识别性能。 根据实验表明,这可以让待估的参数减少超过一半,越少的参数也意味着更快的收敛,不需要那么多的目标用户数据即可模型的良好训练。
GMM-UBM就是以UBM为初始模型,采用目标说话人数据进行基于最大后验概率(Maximum A Posterior, MAP)的自适应训练,得到目标说话人的混合高斯模型(GMM)。简单来说,用其他用户的数据来进行“预训练”,减少对真正目标用户的训练时间和参数调整。
MAP自适应算法
在GMM-UBM系统框架中,UBM拟合出大量说话人的特征分布,目标用户的数据散落在UBM某些高斯分布的附近。其中自适应的过程就是将UBM的每个高斯分布向目标用户数据偏移。MAP(Maximum a posteriori estimation,最大后验概率估计)就是解决这种问题的算法之一。
我们对目标用户的GMM模型自适应的过程分为两个步骤:
1、首先,使用目标说话人的训练数据计算出UBM模型的新参数(高斯权重、均值和方差)
2、将得到的新参数与UBM模型的原参数进行融合,从而得到目标说话人的模型。
具体的计算方法如下:
1、给定GMM模型和目标说话人的训练矢量集。计算新的参数说话人的训练数据新参数(高斯权重、均值和方差)。
计算和UBM中的第个高斯分布的相似度:
其中是从说话人的训练数据计算的高斯权重,的计算公式如下:
然后计算新的权重、均值和方差参数:
2、由第一步得到的新参数和UBM原参数融合,得到最终的目标说话人模型:
其中,自适应参数用于调节新参数和UBM参数对最终模型的影响。归一化因子(可以理解为权重值的权重)可以保证各混合度的权重满足:
对于GMM-UBM系统框架,是GMM模型的一个推广,是用于解决当前目标说话人数据量不够的问题的一种方式。通过收集其他说话人数据来进行一个预先的训练。通过MAP算法的自适应,将预先训练过的模型向目标说话人模型进行微调。这种方式可以大大减少训练所需要的样本量和训练时间(通过减少训练参数)。
稍微总结一下GMM的做法:每一个说话人的个性特征可以用概率密度分布来描述,高斯混合模型是用M个多为高斯分布加权得到,它秒速了语音特征信号在特征空间的分布。训练时利用语音特征来训练成与说话人对应的GMM模型,识别时则是通过识别语音和GMM模型进行匹配,选择概率最大的模型说话人作为识别的结果。为了方便计算,每个说话人的概率密度函数都用相同的表达式,而每个说话人的模型则可以用一组函数的参数来表示。
模块参考:
Pickle:https://www.cnblogs.com/pannyvan/p/4439308.html
operator:https://blog.csdn.net/zhtysw/article/details/80510113
argparse: https://www.cnblogs.com/arkenstone/p/6250782.html
itertools: https://www.cnblogs.com/fengshuihuan/p/7105545.html
声谱图参考:https://www.cnblogs.com/BaroC/p/4283380.html
LTSD参考:https://max.book118.com/html/2017/0809/126872851.shtm
MFCC参考:
https://blog.csdn.net/liuliqun520/article/details/80538259
https://blog.csdn.net/class_brick/article/details/82743741
https://www.cnblogs.com/BaroC/p/4283380.html
GMM-UBM参考:
https://blog.csdn.net/weixin_38206214/article/details/81084456
https://blog.csdn.net/zongza/article/details/82143278