kaldi跑aishell实例v1说话人识别
我尝试了自己创建shell文件分步跑run.sh的内容,但是在训练PLDA那一步出现了找不到exp/ivector_train_1024/log/plda.log。于是又直接从头开始直接跑整个run.sh,全程没报错。也不知道哪一步生成了plda.log,就有点奇怪。
文章目录
一、直接跑run.sh需要注意的坑[4]
注意修改好下面这俩个,就可以跑通了。
1. 按照run.sh的要求新建好data的路径
run.sh里面原本写的是export/a05/xna/data,我用这个跑会说找不到data文件,于是我修改成了data=/home/yuhm/kaldi/kaldi-trunk/egs/aishell/v1/export/a05/xna/data。当然,我一开始也觉得直接弄相对路径data=/data不是更简洁嘛,但是好像会在中途出现一些问题。。还是乖乖弄成绝对路径吧。
2. 修改cmd.sh里的queue.pl改成run.pl
原来在很多shell文件中出现的train_cmd变量在cmd.sh里面已经初始化好了,憨憨的我还在想train_cmd是个啥。。
二、run.sh运行过程中对应的输出显示
因为我是先运行的分步骤的run.sh,然后再训练PLDA的时候卡壳了。然后再重新整个运行的run.sh,所以下面的输出显示可能和直接整个运行run.sh有点区别,不过大致相同。
1.数据准备
代码如下:
# 地址变量(引号可省略,但是=之间不可有空格!)
data=/home/yuhm/kaldi/kaldi-trunk/egs/aishell/v1/export/a05/xna/data
data_url=www.openslr.org/resources/33
# 载入引用文件(使用.,类似import)
. ./cmd.sh
. ./path.sh
# 设置bash出错则退出
set -e # exit on error
# 下载和解压数据(应该是两者选一)
local/download_and_untar.sh $data $data_url data_aishell
local/download_and_untar.sh $data $data_url resource_aishell
#(download_and_untar.sh <数据/数据下载地址> <数据输出位置>)
# 数据准备 主要用到data_aishell数据 train340 dev40 test20 aishell_data_prep.sh里面可以生成utt2spk、wav.scp、text
local/aishell_data_prep.sh $data/data_aishell/wav $data/data_aishell/transcript
显示结果如下:
因为我已经下载好了data_aishell和resource_aishell,所以没有显示下载的反馈。
2.提取MFCC特征
代码如下:
# 提取MFCC特征(建议使用一个大容量的磁盘来储存mfcc。每个wav首先被分为很多帧,每帧用一串数字来表示,mfcc就是这串数字
# 这一步会生成两个文件夹,mfcc 和 exp/make_mfcc,mfcc 主要保存了提取的特征,exp/make_mfcc 里保存了日志,即log 文件。
mfccdir=mfcc
for x in train test; do
steps/make_mfcc.sh --cmd "$train_cmd" --nj 10 data/$x exp/make_mfcc/$x $mfccdir
#steps/make_mfcc.sh用来提取MFCC特征。make_mfcc.sh <数据所在文件夹> <日志文件夹> <mfcc输出文件夹>;
#-- 符号后面接的都是超参数设置
sid/compute_vad_decision.sh --nj 10 --cmd "$train_cmd" data/$x exp/make_mfcc/$x $mfccdir
#sid/compute_vad_decision.sh计算基于energy的VAD output,就是计算倒谱均值和方差归一化。compute_vad_decision.sh <数据所在文件夹> <日志文件夹> <mfcc输出文件夹>
utils/fix_data_dir.sh data/$x
done
显示结果如下:
3.训练UBM
代码如下:
#在sid/train_diag_ubm.sh中,这是steps / train_diag_ubm.sh的修改版本,专门用于说话人识别,不需要从训练有素的模型开始,用滑动窗口CMVN,它需要数据目录中的语音活动检测(vad.scp)。我们使用gmm-global-init-from-feats初始化GMM,它设置随机数据点的均值,然后在内存中进行一些EM迭代。在内存初始化之后,我们并行训练几次迭代。
#在sid/train_full_ubm.sh,这将从现有(对角线或完整)UBM训练完全协方差UBM,持续指定的迭代次数。这是针对speaker-id系统的(我们使用专门针对它的功能和vad)。
# train diag ubm
sid/train_diag_ubm.sh --nj 10 --cmd "$train_cmd" --num-threads 16 \
data/train 1024 exp/diag_ubm_1024
#train full ubm
sid/train_full_ubm.sh --nj 10 --cmd "$train_cmd" data/train \
exp/diag_ubm_1024 exp/full_ubm_1024
显示结果如下:
4.训练ivector,提取ivector
代码如下:
#在exp/extractor_1024可以看到提取的ivector。
#train ivector
sid/train_ivector_extractor.sh --cmd "$train_cmd --mem 10G" \
--num-iters 5 exp/full_ubm_1024/final.ubm data/train \
exp/extractor_1024
#extract ivector
sid/extract_ivectors.sh --cmd "$train_cmd" --nj 10 \
exp/extractor_1024 data/train exp/ivector_train_1024
显示结果如下:
5.训练 plda 模型
代码如下:
#用训练集的 ivector 来训练 plda 模型用于打分,可以从exp/ivector_train_1024/plda中查看plda的分数
$train_cmd exp/ivector_train_1024/log/plda.log \
ivector-compute-plda ark:data/train/spk2utt \
'ark:ivector-normalize-length scp:exp/ivector_train_1024/ivector.scp ark:- |' \
exp/ivector_train_1024/plda
6.划分测试集为enroll和eval
代码如下:
#split the test to enroll and eval。划分测试集(test)为enroll和eval
#
mkdir -p data/test/enroll data/test/eval
cp data/test/{spk2utt,feats.scp,vad.scp} data/test/enroll
cp data/test/{spk2utt,feats.scp,vad.scp} data/test/eval
local/split_data_enroll_eval.py data/test/utt2spk data/test/enroll/utt2spk data/test/eval/utt2spk
trials=data/test/aishell_speaker_ver.lst
local/produce_trials.py data/test/eval/utt2spk $trials
utils/fix_data_dir.sh data/test/enroll
utils/fix_data_dir.sh data/test/eval
显示结果如下:
7.提取注册集和验证集的ivector
代码如下:
#提取enroll和eval的ivector并计算结果
#extract enroll ivector
sid/extract_ivectors.sh --cmd "$train_cmd" --nj 10 \
exp/extractor_1024 data/test/enroll exp/ivector_enroll_1024
#extract eval ivector
sid/extract_ivectors.sh --cmd "$train_cmd" --nj 10 \
exp/extractor_1024 data/test/eval exp/ivector_eval_1024
显示结果如下:
8.用PLDA模型打分。得到eer
ACC是在测试数目中,目标被正确分类的个数:true/num_trials,侧重在分类;EER除了考虑到目标的是否对了之外,还考虑到了非目标是否被误判为目标,这对于声纹识别这种侧重识别是必须的。----Leon晋
EER(等错误率):EER=FR=FA
FA:错误接受率(nontarget_is_target / (target_is_target + nontarget_is_target)) 就是本来应该reject的结果accept了
FR:错误拒绝率(target_is_nontarget / (target_is_nontarget + nontarget_is_nontarget))就是本来应该accept 的结果 reject了[1]
代码如下:
#compute plda score
$train_cmd exp/ivector_eval_1024/log/plda_score.log \
ivector-plda-scoring --num-utts=ark:exp/ivector_enroll_1024/num_utts.ark \
exp/ivector_train_1024/plda \
ark:exp/ivector_enroll_1024/spk_ivector.ark \
"ark:ivector-normalize-length scp:exp/ivector_eval_1024/ivector.scp ark:- |" \
"cat '$trials' | awk '{print \\\$2, \\\$1}' |" exp/trials_out
#compute eer
awk '{print $3}' exp/trials_out | paste - $trials | awk '{print $1, $4}' | compute-eer -
显示结果如下:
参考:
[1] https://blog.csdn.net/zjm750617105/article/details/52558779
[2] https://www.jianshu.com/p/fe63969a7fe5
[3] https://yutouwd.github.io/posts/364e185b/
[4] https://blog.csdn.net/toohandsomeIeaseId/article/details/113807678