Zhou's home Zhou's home
首页
说话人识别
算法题库
编程相关
语音识别
关于
  • 分类
  • 标签
  • 归档
  • 常用工具
  • 友情链接

ZhouWJ

吾生也有涯,而知也无涯
首页
说话人识别
算法题库
编程相关
语音识别
关于
  • 分类
  • 标签
  • 归档
  • 常用工具
  • 友情链接
  • Kaldi Toolbox

    • Kaldi的基本框架和逻辑
    • 使用预训练Xvector模型进行测试
      • 已知条件
        • 数据集处理流程
        • 各Xvector集作用
      • 主要步骤
        • 表单准备
        • 提取Test集特征
        • 划分注册和验证集
        • 提取Xvector
        • trials文件准备
        • 打分&EER
      • 补充说明
        • transform-feats
        • utils/filter_scp.pl
        • 其他
    • Kaldi中的PLDA自适应
    • Kaldi声纹识别代码详解|egs/aishell
    • 源码阅读|Kaldi中的PLDA打分
    • PLDA相关代码详解
    • iVector相关代码详解
    • Voxceleb源码阅读
    • Kaldi相关项目及碎片知识
    • Kaldi中的nnet3
  • 算法原理梳理

  • 文献记录

  • 我的工作

  • 声纹识别
  • Kaldi Toolbox
xugaoyi
2021-06-12
目录

使用预训练Xvector模型进行测试

# 已知条件

# 数据集处理流程

  1. 联合SRE16之前的所有SRE系列数据和Mixer 6,放入data/sre
  2. 准备SWBD数据集,放入data/swbd
  3. 整理出注册数据data/sre16_eval_enroll,验证数据data/sre16_eval_test,无标签的广东话和菲律宾语集合data/sre16_major
  4. 将SRE和SWBD数据集联合,放入data/swbd_sre
  5. 加混响data/swbd_sre_noise,加噪data/swbd_sre_noise,加音乐data/swbd_sre_music,加语音swbd_sre_babble
  6. 将语音增强数据集合data/swbd_sre_aug,取子集swbd_sre_aug_128k
  7. 结合增强数据与原始数据data/swbd_sre_combined
  8. 分离出SRE系列数据data/sre_combined
  9. 去除静音后用于训练网络data/swbd_sre_combined_no_sil

# 各Xvector集作用

根据sre16/0003_sre16_v2_1a/run.sh脚本,在stage=7时,分别提取了如下Xvector:

  • exp/xvectors_sre16_major:(域内)data/sre16_major,用于中心化,白化和得分归一化(但该脚本目前还没有得分归一化);自适应PLDA
  • exp/xvectors_sre_combined:(域外)data/sre_combined,用于LDA/PLDA
  • exp/xvectors_sre16_eval_test:测试Ivector,与注册Ivector的spk应一致,但utt不可重叠
  • exp/xvectors_sre16_eval_enroll:注册Ivector

⚠️问题:

  1. 为什么LDA/PLDA,及中心化,白化和得分归一化不能用同一个数据集?

    可以,但是为了说明域适应的优越性和域适应原理,本脚本分开处理

  2. 所谓域内数据是不是测试集?

    不是,在实际应用中,域内数据是测试集的特征表示,通过无标签的域内数据我们可以使测试结果更加准确

# 主要步骤

$train_cmd exp/scores/log/sre16_eval_scoring.log \
   ivector-plda-scoring --normalize-length=true \
    --num-utts=ark:exp/xvectors_sre16_eval_enroll/num_utts.ark \
    "ivector-copy-plda --smoothing=0.0 exp/xvectors_sre_combined/plda - |" \
    "ark:ivector-mean ark:data/sre16_eval_enroll/spk2utt scp:exp/xvectors_sre16_eval_enroll/xvector.scp ark:- | ivector-subtract-global-mean exp/xvectors_sre16_major/mean.vec ark:- ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
    "ark:ivector-subtract-global-mean exp/xvectors_sre16_major/mean.vec scp:exp/xvectors_sre16_eval_test/xvector.scp ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
    "cat '$sre16_trials' | cut -d\  --fields=1,2 |" exp/scores/sre16_eval_scores || exit 1;
1
2
3
4
5
6
7
  • ⚠️使用的是域外数据训练得到的PLDA模型,--smoothing=0.0,为什么不直接用plda呢?可能是为了程序的规范化

  • ⚠️后续该脚本用此域外PLDA模型进行自适应得到域内PLDA,但此时域内PLDA是没有自己的LDA投影矩阵的,依旧使用域外LDA矩阵

  • 为什么不直接用域内数据训练LDA和PLDA呢?

    因为域内数据通常是小样本的,直接训练无法得到准确的模型参数

  • 需要自行准备exp/xvectors_sre16_eval_enroll/xvector.scp、exp/xvectors_enroll/num_utts.ark、exp/xvectors_sre16_eval_test/xvector.scp、sre16_trials

根据数据集的命名,enroll+test=eval,现在我们对数据集重新进行约定,test=enroll+eval,先对数据进行处理,再划分为注册集和验证集。使用TIMIT数据集,共630人。

# 表单准备

仿照aishell_data_prep.sh生成spk2utt、utt2spk、wav.scp:

find $audio_dir -iname "*.wav" | grep -i "wav/test" > $test_dir/wav.flist || exit 1;

echo Preparing $test_dir transcriptions
sed -e 's/\.wav//' $test_dir/wav.flist | awk -F '/' '{print $NF}' > $test_dir/utt.list
sed -e 's/\.wav//' $test_dir/wav.flist | awk -F '/' '{i=NF-1;printf("%s %s\n",$NF,$i)}' > $test_dir/utt2spk_all
paste -d' ' $test_dir/utt.list $test_dir/wav.flist > $test_dir/wav.scp_all
utils/filter_scp.pl -f 1 $test_dir/utt.list $test_dir/utt2spk_all | sort -u > $test_dir/utt2spk
utils/filter_scp.pl -f 1 $test_dir/utt.list $test_dir/wav.scp_all | sort -u > $test_dir/wav.scp
utils/utt2spk_to_spk2utt.pl $test_dir/utt2spk > $test_dir/spk2utt

mkdir -p data/test
for f in spk2utt utt2spk wav.scp; do
  cp $test_dir/$f data/test/$f || exit 1;
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 提取Test集特征

steps/make_mfcc.sh --mfcc-config conf/mfcc.conf \
  --nj 40 --cmd "$train_cmd" \
  data/test exp/make_mfcc $mfccdir
utils/fix_data_dir.sh data/test
sid/compute_vad_decision.sh --nj 40 --cmd "$train_cmd" \
  data/test exp/make_vad $vaddir
utils/fix_data_dir.sh data/test
1
2
3
4
5
6
7
  • TIMIT采样率是16k,但是预训练模型中给出采样率为8k,因此根据log文件提示,设置--allow-downsample=true

# 划分注册和验证集

参考aishell脚本中的local/split_data_enroll_eval.py,每人取3句话用于注册,1句话用于测试:

local/split_enroll_eval.py data/test/utt2spk data/enroll/utt2spk data/eval/utt2spk 3 1
1

# 提取Xvector

sid/nnet3/xvector/extract_xvectors.sh --cmd "$train_cmd" --nj $nj \
  $nnet_dir data/test/enroll exp/xvectors_enroll

sid/nnet3/xvector/extract_xvectors.sh --cmd "$train_cmd" --nj $nj \
  $nnet_dir data/test/eval exp/xvectors_eval
1
2
3
4
5
  • 只会使用到CPU,还是很快的
  • extract_xvectors.sh会生成num_utts.ark

# trials文件准备

直接使用aishell脚本中的local/produce_trials.py

trials=data/test/speaker_ver.lst
local/produce_trials.py data/test/eval/utt2spk $trials
1
2

# 打分&EER

$train_cmd exp/scores/log/scoring.log \
   ivector-plda-scoring --normalize-length=true \
    --num-utts=ark:exp/xvectors_enroll/num_utts.ark \
    "ivector-copy-plda --smoothing=0.0 exp/xvectors_sre_combined/plda - |" \
    "ark:ivector-mean ark:data/test/enroll/spk2utt scp:exp/xvectors_enroll/xvector.scp ark:- | ivector-subtract-global-mean exp/xvectors_sre16_major/mean.vec ark:- ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
    "ark:ivector-subtract-global-mean exp/xvectors_sre16_major/mean.vec scp:exp/xvectors_eval/xvector.scp ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
    "cat '$trials' | awk '{print \\\$2, \\\$1}' |" exp/scores/eval_scores || exit 1;
    
eer=$(paste $trials exp/scores/eval_scores | awk '{print $6, $3}' | compute-eer - 2>/dev/null)
echo "Using Out-of-Domain PLDA, EER: ${eer}%"
1
2
3
4
5
6
7
8
9
10
  • 注意格式,必须先是注册spk,再是测试utt,且trials文件的第1,2列也需要对应
  • 结果:Equal error rate is 5.71429%, at threshold -22.9097 5.714

# 补充说明

# transform-feats

应用变化(e.g. LDA; HLDA; fMLLR/CMLLR; MLLT/STC)。当transform-num-cols == feature-dim时,为线性变换,当transform-num-cols == feature-dim+1 (->append 1.0 to features)时,为仿射变换。默认作用于每个utt,当utt2spk文件提供时,可作用于每个spk。若提供了transform-rxfilename,则作用于全局。

Usage: transform-feats [options] (<transform-rspecifier>|<transform-rxfilename>) <feats-rspecifier> <feats-wspecifier>
See also: transform-vec, copy-feats, compose-transforms
1
2

# utils/filter_scp.pl

从输入文件中挑选出其第f列(默认第一列)在id_list中的行。注意:只关心id_list的第一列,--exclude则挑选出不在id_list中的行。

Usage: filter_scp.pl [--exclude] [-f <field-to-filter-on>] id_list [in.scp] > out.scp 
1

# 其他

  • '\r': command not found 解决办法 (opens new window)

    #转化为unix格式
    sed -i 's/\r$//' <filename> 
    
    1
    2
#Kaldi#PLDA
上次更新: 2024/04/10, 22:12:29
Kaldi的基本框架和逻辑
Kaldi中的PLDA自适应

← Kaldi的基本框架和逻辑 Kaldi中的PLDA自适应→

最近更新
01
方言语音识别综述
04-05
02
主流ASR模型概述
03-26
03
一些参考图表及表述
05-28
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式