Kaldi中的PLDA自适应
将TIMIT数据集分为用于训练PLDA的域内数据和用于测试的Test集[⛳以后再写随机划分脚本],取前130人作为域内数据。使用预训练模型(详见使用预训练Xvector模型进行测试 (opens new window))中域外数据的PLDA模型和LDA矩阵,但是重新训练均值向量。
# 主代码分析
参考脚本:sre16/0003_sre16_v2_1a/run.sh stage8
# 获取中心化所需的均值向量
$train_cmd exp/xvectors_domain/log/compute_mean.log \
ivector-mean scp:exp/xvectors_domain/xvector.scp \
exp/xvectors_domain/mean.vec || exit 1;
1
2
3
2
3
- 中心化只使用域内数据,所谓中心化,就是取与你需要去中心化的数据集最接近的已知数据集的均值
# 自适应得到域内PLDA
该阶段使用预训练模型exp/xvectors_sre_combined/plda
,由域外数据得到
$train_cmd exp/xvectors_domain/log/plda_adapt.log \
ivector-adapt-plda --within-covar-scale=0.75 --between-covar-scale=0.25 \
exp/xvectors_sre_combined/plda \
"ark:ivector-subtract-global-mean scp:exp/xvectors_domain/xvector.scp ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
exp/xvectors_domain/plda_adapt || exit 1;
1
2
3
4
5
2
3
4
5
# 直接训练域内PLDA模型
需要data/domain/spk2utt
$train_cmd exp/xvectors_domain/log/plda.log \
ivector-compute-plda ark:data/domain/spk2utt \
"ark:ivector-subtract-global-mean scp:exp/xvectors_domain/xvector.scp ark:- | transform-vec exp/xvectors_sre_combined/transform.mat ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
exp/xvectors_domain/plda || exit 1;
1
2
3
4
2
3
4
# PLDA打分
为了方便考虑分析各种模型下的性能,对PLDA打分过程进行改进:
meanVec=exp/xvectors_sre_combined/mean.vec
LDA=exp/xvectors_sre_combined/transform.mat
PLDA=exp/xvectors_sre_combined/plda
$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 '$PLDA' - |" \
"ark:ivector-mean ark:data/test/enroll/spk2utt scp:exp/xvectors_enroll/xvector.scp ark:- | ivector-subtract-global-mean '$meanVec' ark:- ark:- | transform-vec '$LDA' ark:- ark:- | ivector-normalize-length ark:- ark:- |" \
"ark:ivector-subtract-global-mean exp/xvectors_domain/mean.vec scp:exp/xvectors_eval/xvector.scp ark:- | transform-vec '$LDA' 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 "EER: ${eer}%"
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 结果与分析
中心化 | LDA | PLDA | EER(%) |
---|---|---|---|
xvectors_sre16_major | xvectors_sre_combined | xvectors_sre_combined | 6.4 |
xvectors_domain | xvectors_sre_combined | xvectors_sre_combined | 8.4 |
xvectors_sre_combined | xvectors_sre_combined | xvectors_sre_combined | 6.4 |
xvectors_domain | xvectors_sre_combined | xvectors_domain(自适应) | 6.4 |
xvectors_sre16_major | xvectors_sre_combined | xvectors_domain(自适应) | 4.8 |
xvectors_sre_combined | xvectors_sre_combined | xvectors_domain(自适应) | 4.8 |
xvectors_sre_combined | xvectors_sre_combined | xvectors_domain | 5.6 |
xvectors_domain | xvectors_sre_combined | xvectors_domain | 8.2 |
中心化使用域内数据效果不理想,原因是100人数据实在是太少了,反而不如大规模数据来得准确;⚠️后期需要调整域内spk数
用域内数据自适应得到的PLDA比直接训练的要好
⚠️待补充:LDA也用域内数据会怎样?
一般来说,域内数据都是无标签的,因此无法训练LDA矩阵
# ivector-compute-plda
为一组Ivector计算PLDA,用spk2utt中的说话人信息计算类内和类间方差
Usage: ivector-compute-plda [options] <spk2utt-rspecifier> <ivector-rspecifier> <plda-out>
e.g.:
ivector-compute-plda ark:spk2utt ark,s,cs:ivectors.ark plda
Options:
--binary: Write output in binary mode (bool, default = true)
--num-em-iters: Number of iterations of E-M used for PLDA estimation (int, default = 10)
1
2
3
4
5
6
7
2
3
4
5
6
7
# ivector-adapt-plda
用非监督自适应数据Ivector从与训练数据不同的域自适应得到PLDA对象
Usage: ivector-adapt-plda [options] <plda-in> <ivectors-rspecifier> <plda-out>
e.g.: ivector-adapt-plda plda ark:ivectors.ark plda.adapted
Options:
--between-covar-scale: Scale that determines how much of excess variance in a particular direction gets attributed to between-class covar. (float, default = 0.7)
--binary: Write output in binary mode (bool, default = true)
--mean-diff-scale: Scale with which to add to the total data variance, the outer product of the difference between the original mean and the adaptation-data mean (float, default = 1)
--within-covar-scale: Scale that determines how much of excess variance in a particular direction gets attributed to within-class covar. (float, default = 0.3)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 主要流程
上次更新: 2024/04/10, 22:12:29