参考脚本:egs/voxceleb/v2
提取Xvector
假设我们已经完成了train.sh的训练,并生成了相应的模型数据,诸如:final.raw,mean.vec.plda.transform.mat等
确认必要文件存在
模型目录下须有final.raw、min_chunk_size、max_chunk_size
数据目录下须有feats.scp、vad.scp
根据final.raw和extract.config生成新的网络
extract.config文件中只有1行:output-node name=output input=tdnn6.affine,表示以第6层作为提取层,该文件是在local/nnet3/xvector/run_xvector.sh脚本stage7中设置的
final.raw:顾名思义,是训练网络后的最终产物,通过nnet3-info fianl.raw
可以查看具体配置
工具:/src/nnet3bin/nnet3-copy
按speaker划分文件
在注册enroll与验证test目录下,有这些文件:feats.scp spk2utt utt2dur utt2num_frames utt2spk vad.scp wav.scp,因为是并行处理,所以需要根据设定的nj数将数据分块。
工具:utils/split_scp.pl、utils/utt2spk_to_spk2utt.pl
1)用utils/split_scp.pl将utt2spk分在split40/目录下的40个子文件夹下,每个speaker的所有utt必须都在同一个文件夹下
2)用utils/utt2spk_to_spk2utt.pl将各目录下的utt2spk转化为spk2utt(因为没有以speaker为索引的文件,所以这步可以省略)
根据子目录下的utt2spk,以utt为索引,生成各自的feats.scp spk2utt utt2dur utt2num_frames vad.scp wav.scp
提取MFCC
工具:/src/featbin/apply-cmvn-sliding、/src/ivectorbin/select-voiced-frames
将每个子目录下的feats.scp文件进行CMVN与VAD(根据各自目录下的vad.scp文件)
提取xvector
工具:/src/nnet3bin/nnet3-xvector-compute
根据nnet网络和MFCC,提取出每个子目录下的xvector并放至模型文件夹下
聚合xvector并按speaker拆分
工具:/src/ivectorbin/ivector-mean
将所有utt的xvector都集中在xvector.scp中,并根据spk2utt取每个人的均值xvector,存放于spk_xvector.{scp,ark},并得到num_utts.ark文件,该文件记录每个说话人的utt数目
PLDA打分
准备PLDA模型
复制train目录下的PLDA模型,并对类内协方差进行平滑处理
工具:/src/ivectorbin/ivector-copy-plda
去中心化
对xvector去均值处理,均值使用mean.vec
工具:/src/ivectorbin/ivector-subtract-global-mean
向量投影
对去均值后的向量进行投影以最大化类间差距,投影矩阵为transform.mat
工具:/src/bin/transform-vec
向量长度归一化
工具:/src/ivectorbin/ivector-normalize-length
计算相似度
注册用的是spk_xvector.scp,也就是每个人的均值xvector(模型),但是测试使用的是xvector.scp,也就是每句话的xvector,比较两个向量与plda模型的相似度
工具:/src/ivectorbin/ivector-compute-lda
流程图整理如下: