1.数据准备:无论使用kaldi来做语音识别还是说话人识别,第一步就是数据准备,对于说话人识别来说,需要准备的几个文件为wav.scp,utt2spk,spk2utt这三个文件。对应的格式如下:
1.1 wav.scp有两列,第一列是key,这个可以一定要唯一;第二列是 wav的路径wavpath;
1.2 utt2spk也有两列,第一列是key,与wav.scp的第一列一样;第二列是对应的说话人信息,叫spk。这个对于说话人识别来说很重要。此外,spk2utt可以根据utils/utt2spk_to_spk2utt.pl来生成。
2.特征提取:使用steps/make_mfcc.sh来进行提取mfcc特征。
提取出的特征写到一个大的 "archive" 文件中, 并且输出一个 "scp" file for easy random access
#!/bin/bash
for x in ./*.wav
do
b=${x##*/}
sox $b -r 16000 tmp_$b
rm -rf $b
mv tmp_$b $b
done
对每一帧:
steps/make_mfcc.sh命令指定参数包括 data-dir、 log-dir、mfcc-dir,分别指定原数据位置、日志输出目录、和提取结果目录。
打开 v1/conf/mfcc.conf 会发现:(这个配置文件挺重要)
--sample-frequency=16000
--num-mel-bins=40 #mel滤波器个数 higher than the default which is 23
--num-ceps=20 # 倒谱系数个数 higher than the default which is 12.
这里配置设置了有40个MEL三角形滤波器,有20个梅尔系数,delta3次后得到20*3=60
啥是delta?
标准的倒谱参数MFCC只反映了语音参数的静态特性,语音的动态特性可以用这些静态特征的差分谱即delta来描述。实验证明:把动、静态特征结合起来才能有效提高系统的识别性能。一般会有2个delta,加上原来的就是20*3=60。
因为做MFCC时一般会取40个滤波器使原始声音变成梅尔刻度(听觉音高单位),梅尔刻度是一种基于人耳对等距的音高变化的感官判断而定的非线性m刻度。
然后因为MFCC 最后一步是DCT,所以DCT的结果也是40个点;实际中,一般仅保留前13~20个,这就进一步压缩了数据。得到梅尔倒谱。
完成MFCC特征提取后,查看结果:
~/kaldi/src/featbin/copy-feats ark:raw_mfcc_test.1.ark ark,t:- | head
在文件名(加粗部分)前边加ark关键字,告诉copy-feats是什么格式的,还有后面加一个ark,t:- 表示输出格式为t文本,否则默认是二进制。打开得到数据,行是一条语音有多少帧的帧数,每行有20列,这里只显示了前20个(应该有60个)。
if you want to print out 2-deltas, enter the following can see
~/kaldi/src/featbin/copy-feats ark:raw_mfcc_test.1.ark ark:- | add-deltas ark:- ark,t:- | head
所以,N维MFCC参数 =(N/3MFCC系数+ N/3一阶差分参数+ N/3二阶差分参数)+帧能量(此项可根据需求替换)
参考:https://blog.csdn.net/robingao1994/article/details/80018415
3.vad:compute_vad_decision.sh 滑动+能量
VAD即 Voice Activity Detection, 用于检测静音和非静音由于说话人识别里静音会有很大的干扰,所以一般都会进行vad。具体kaldi里也有个简单的根据能量来判断vad的脚本。当然这个越精确越好。。通过使用VAD,我们可以找到有效语音段,剔除静音段,在语音识别等过程中可以大大减少要处理的数据量。
具体参考:https://blog.csdn.net/wxb1553725576/article/details/78069089
4.训练阶段:主要训练gmm-ubm跟i-vector模型
sid/train_diag_ubm.sh;sid/train_full_ubm.sh;train_ivector_extractor.sh
UBM特点:一个与说话人、信道无关的高斯混合模型;可以作为这个训练集的统一参考坐标空间;在一定程度上,还解决了某些说话人少样本问题;
假如初始化UBM时,我设了M=2048个高斯分量components,就会有2048个单高斯分量,每个 i 分量(i=1,2,...,M)包括一个权重、一个均值矢量、一个协方差矩阵:λ = {ci,μi,∑i},其中μi和∑i分别是矢量与矩阵;
假如声学特征是D=39维,则UBM的第 i 个高斯分量的均值矢量将包含了D维;
如果把均值矢量与协方差对角阵展开,则是μi = {μi1,μi2,...,μiD},∑i = diag{σ^(2)i1,σ^(2)i2,...,σ^(2)iD},即均值是一个D x 1维矢量,方差是D x D维对角(全)矩阵
提取ivector流程:https://www.zhihu.com/question/63978977/answer/215215119
5. 提取训练集的i-vector向量,并训练分类器,kaldi提供了三类:
dot-proucts,lda,plda等。
这样咱们就训练好了一个i-vector系统。当然前提你要有一些说话人识别的理论知识。
kaldi里的说话人识别的例子是sre08跟sre10,语种识别的例子是lre跟lre07。当然如果你理解说话人识别的理论,还可以做性别分类、噪声音乐分类等。对此kaldi也有一些对应的例子跟脚本。
kaldi当然也有dnn用于说话人识别的例子,dnn-ubm系统的例子大家可以参考sre10/v2里的带dnn的脚本。如果大家对于说话人识别还了解的应该还知道目前说话人识别里还有d-vector算法,end-to-end算法。
th30做的声纹识别
参考:https://blog.csdn.net/weixin_38858860/article/details/84346576