基于chain多唤醒词识别模型

基于chain多唤醒词识别模型

参考袁有根NCMMSC会议分享

image-20211021162722733

目标:训练更好的AM;如何将测试时的解码网络内的参数自动调整;

思路:一开始想要防止语言模型过拟合!!!其实根本没必要!!!,因为端到端模型中有语言模型部分,该部分参数会更新,因此越训练会越适配训练集,因此语言模型容易过拟合(而一般外部语言模型用的可不止训练数据,用的是很大文本统计得到的,可以做shallow fusion),而chain model里面参与计算loss的语言模型部分根本不会跟新,不用考虑过拟合问题!!!

如果是只考虑有无必要把语言模型融入,按照人家拼命把语言模型拿掉的思路,是没有必要再引入语言模型的。

但是希望测试时的解码网络的参数能调整,因此借鉴模型fusion的思路,1.shallow fusion cold fusion 外部语言模型参与,可使得模型倾向于

用无调音节建模

step1. 训练一个初始大一点的chain模型,分母网用训练数据得到的3gram phone ,记作chain model1,目的是后续的对齐;

用tri3对齐lattice,训练大chain model

用tri3对齐,训练tdnn,用tdnn进行后续对齐:local/nnet3/run_tdnn_bigmodel_for_align.sh

step2. 对齐生成lattice,重新训练,注意,此时构建egs时不再下采样(frame-subsampling-factor=1),分母网用训练数据得到的3gram phone loop,记作chain model2,目的是做finetune的初始模型

step3. finetune:

  • 语言模型P(W)都是1,进行finetune,得到chain model2,这个想法是为了训练更好的声学模型,让声学模型受语言模型的帮助更小,更独立。花哥说,这有点类似em思路,固定语言模型,更新声学模型,再放开语言模型,更新声学模型,最后的结果可能和一开始就引入语言模型的结果差不多;
  • 用测试解码网络作为P(W)进行finetune,得到唤醒任务的chain model3,雷博尝试了该方法,并且把学习率调小,结果far会很高,可能由于解码网络的竞争路径太少,竞争路径的分数也很高?
  • loss分母竞争路径分数-唤醒路径分数(如何挑选出唤醒路径?),参考专利《[重要]CN201710343427-基于鉴别性训练的定制语音唤醒优化方法及系统-审定授权.pdf》
  • 训练LM网络,LM网络的输入是测试解码网络概率,输出是新G概率,再用该概率去做分母,这个如何实现??

step4. 用step1的模型,用上下文无关音节建模,减少分类数,重新对齐生成lattice,再训练一个chain model

先看一下language model fusion的论文《LANGUAGE MODEL FUSION FOR STREAMING END TO END SPEECH RECOGNITION 》,看一下如何容融合外部语言模型

赋予loss不同权重

思路:

参考多任务学习的赋予权重思路:kaldi/egs/babel_multilang/s5/local/nnet3/run_tdnn_multilingual.sh

修改多任务学习的脚本,使得loss不同权重,但是又只训练一个任务

kaldi判断多任务的脚本:steps/nnet3/train_raw_dnn.py

通过有没有valid_diagnostic.scp或valid_diagnostic.ark来判断use_multitask_egs=True还是False,这个只在raw里有,因此要把mdl中的也增加多任务学习,然后作用到train_lib.common.train_one_iteration训练。

train_one_iteration里决定存储的是mdl还是raw的符号:get_raw_nnet_from_am。

实验汇总

topo区别实验

比较四/三/二个字用四/三/二状态建模,与不管几个字都用四状态建模的区别。

比较单音素(现在里面是单音素)与三音素的区别?需要比较吗

DNN对齐模型区别实验

  • 用tdnn大模型(69M)作为后续对齐模型:
    • 路径:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/exp_syll/nnet3/tdnn
    • 脚本:local/nnet3/run_tdnn_bigmodel_for_align.sh
    • 学习率:initial_effective_lrate=0.008,final_effective_lrate=0.00008,num_epochs=6(这样学习率太大了会报LOG Per-component max-change active)
    • 训练集特征:train_set=data/plp/train_12000
    • 对齐:ali_dir=exp_syll/tri3_ali
    • 模型:tdnn,6层,1024结点,左拼13右拼9
    • 分类数:8000类
    • 结果:loss=-2,acc=46%(可能因为分类数太多,调小学习率继续训练无改善)
  • 用conv tdnnf的chain大模型(67M)作为后续对齐模型
    • 路径24.4:/home/data/yelong/kaldi/egs/hi_mia/w1/exp_syll/chain/tdnn_cnn_tdnnf
    • 脚本:run_2_chain_ddt1500h.sh
    • lattice:/home/storage/yelong/lattice/exp_syll/tri3_lats
    • tree:exp_syll/chain/tri4_cd_tree
    • feat:data/plp/train_12000
    • 模型:cnn-tdnnf

对齐大模型生成lattice

  • tdnn大模型生成lattice:
    • 训练集:负样本12000小时(1111万条),正样本2000小时(380万条),data_multi/merge_all_sub4_12000/,正负样本1:6
    • tdnn大模型路径:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/exp_syll/nnet3/tdnn
    • 对齐lattice路径:exp_syll/nnet3/tdnn_12000n_2000p_lats/(集群跑的)
  • chain大模型生成lattice
    • 训练集:负样本12000小时(1111万条),正样本2000小时(380万条),data_multi/merge_all_sub4_12000/,正负样本1:6
    • 对齐lattice路径:exp_syll/chain/tdnn_cnn_tdnnf_12000n_2000p_lats/(集群跑的)[没跑完]
    • 这次把命令词都放在词典中,作为整词,不分词【没必要,因为chain用1状态建模(2个pdf),不是三音素是单音素,和前后文无关】
    • 料想和tdnn对齐模型效果差不多,实验暂停。

构建单音素(每个音素两个pdf)

  • 脚本:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/run_2_chain_ddt1500h.sh

  • 构建单音素build-tree时:–context-width=1 –central-position=0

  • 得到pdf=808(不是810,这是因为音节den和dia的forward-pdf和self-loop=pdf相同,应该是因为训练样本里没有?)

训练chain model

Finetune

  • 根据chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm,解码训练集data_multi/merge_all_sub4_12000,得到data_multi/merge_all_sub4_12000_filter_false_rejection_alarm,其中,

    • false alarm数量6k
    • false rejection数量50w,其中,7w条是识别成其他唤醒词(也就是其他唤醒词的误唤醒),7w条中有6w条是上/下一曲/集的误唤醒,小源小源4w
    • 方法2重训后,再次解码false alarm和false rejection样本
      • false alarm:6k -> 5k(下降19%)
      • false rejection:50w -> 48w(下降4.7%)
  • 根据chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch,解码训练集data_multi/merge_all_sub4_12000,得到data_multi/merge_all_sub4_12000_filter_false_rejection_alarm_tdnnf8,其中,

    • false alarm数量1.8w
    • false rejection数量66w,其中,小源小源4.8w
    • 测试集far会更低的,但是解码训练集,居然比chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm的更多!!!
    • 方法2重训后,再次解码false alarm和false rejection样本,和想象的不同的是,误唤醒和误拒绝并没有少很多,感觉还是没训练好
      • false alarm:1.8w -> 1.5w (下降17.2%)
      • false rejection:66w -> 62w(下降5.6%)

方法1:

  • 只对这些样本重新训练一轮(也要保证正负样本比例,小源正样本还不能少,否则唤醒率会略有下降)
    • 随机shuf取出300w的负样本,与false alarm构成300w的负样本,正样本50w
    • 在exp_syll/nnet3/tdnn_12000n_2000p_lats/中用
    • 脚本:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/run_2_chain_ddt1500h.filter_far_frejection.sh
    • 模型:exp_syll/chain/chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_filter_false_reje_ala_small_learningrate
    • input_model:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/final.mdl
    • 初始和结束的学习率都为==0.000001==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
lattice-copy "--include=cat data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/uttlist |" --ignore-missing "ark:gunzip -c exp_syll/nnet3/tdnn_12000n_2000p_lats/lat.1.gz |" "ark:| gzip -c > exp_syll/nnet3/tdnn_12000n_2000p_filter_false_rejection_alarm_lats/lat.1.gz"
#或者
lattice-copy "--include=cat data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/uttlist |" --ignore-missing "ark:gunzip -c exp_syll/nnet3/tdnn_12000n_2000p_lats/lat.1.gz |" ark,t:exp_syll/nnet3/tdnn_12000n_2000p_filter_false_rejection_alarm_lats/lat.1.ark

# 脚本:
for n in $(seq 1 120);do
#lattice-copy "--include=cat data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/uttlist |" --ignore-missing "ark:gunzip -c exp_syll/nnet3/tdnn_12000n_2000p_lats/lat.$n.gz |" "ark:| gzip -c > exp_syll/nnet3/tdnn_12000n_2000p_filter_false_rejection_alarm_lats/lat.$n.gz"
lattice-copy "ark:gunzip -c exp_syll/nnet3/tdnn_12000n_2000p_filter_false_rejection_alarm_lats/lat.$n.gz |" ark,t:1
awk '{if(NF==1)print$1,$1}' 1 | grep -E "^0|^K|^Xiaoyuan|^SY|^sp" > data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk
cp data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/spk2utt
utils/filter_scp.pl data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/feats.scp > data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/feats.scp
utils/filter_scp.pl data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/cmvn.scp > data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/cmvn.scp
utils/filter_scp.pl data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/text > data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/text
utils/filter_scp.pl data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2spk data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/utt2dur > data_multi/merge_all_sub4_12000_filter_false_rejection_alarm/split120/$n/utt2dur
done

  • 将筛选出的lattice放在exp_syll/nnet3/tdnn_12000n_2000p_filter_false_rejection_alarm_lats中
    • 结果:如果学习率是0.00015开始训练的,学习率一开始设置得较大,效果不好,没有改善,误唤醒还增加了,但是==调小学习率后,效果变好了==
  • 用同一批数据finetune tdnnf8试一试

方法2:

  • 对这些样本赋予高一点的权重,其他样本赋予低一点的权重,对所有样本finetune训练一轮
  • 脚本:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/run_tdnn_multilingual.sh
  • 模型:exp_syll/chain/chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch_multitask_test_input_model/
    • awk -F'-' '{$NF=null;print$0}' 1| sed 's/ *$//' | tr ' ' '-' | paste -d ' ' - 1
1
2
3
for n in $(seq 1 3430);do
nnet3-chain-copy-egs ark:exp_syll/chain/chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN/egs/cegs.${n}.ark ark,scp:exp_syll/chain/chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_multi_2/egs/cegs.${n}.temp.ark,exp_syll/chain/chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_multi_2/egs/cegs.${n}.temp.scp
done
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
src=exp_syll/chain/chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_multi_2/egs
dir=exp_syll/chain/chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch_multitask/egs
for n in $(seq 1 3430);do
echo $n
cp $src/cegs.$n.temp.scp $dir/cegs.$n.scp
awk -F'-' '{$NF=null;print$0}' $dir/cegs.$n.scp| sed 's/ *$//' | tr ' ' '-' | paste -d ' ' - $dir/cegs.$n.scp | utils/filter_scp.pl false_alarm_rejection - > $dir/$n.temp.ark.1
awk '{print$2,"2.5"}' $dir/$n.temp.ark.1 > $dir/cegs.weight.$n.ark.1
awk '{print$2,"output-0"}' $dir/$n.temp.ark.1 > $dir/cegs.output.$n.ark.1
awk -F'-' '{$NF=null;print$0}' $dir/cegs.$n.scp| sed 's/ *$//' | tr ' ' '-' | paste -d ' ' - $dir/cegs.$n.scp | utils/filter_scp.pl --exclude false_alarm_rejection - > $dir/$n.temp.ark.2
awk '{print$2,"1"}' $dir/$n.temp.ark.2 > $dir/cegs.weight.$n.ark.2
awk '{print$2,"output-1"}' $dir/$n.temp.ark.2 > $dir/cegs.output.$n.ark.2
cat $dir/cegs.weight.$n.ark.1 $dir/cegs.weight.$n.ark.2 > $dir/cegs.weight.$n.ark.3
cat $dir/cegs.output.$n.ark.1 $dir/cegs.output.$n.ark.2 > $dir/cegs.output.$n.ark.3
awk '{print$1,$1}' $dir/cegs.$n.scp | utils/apply_map.pl -f 1 $dir/cegs.weight.$n.ark.3 | awk '{print$2,$1}' > $dir/cegs.weight.$n.ark
awk '{print$1,$1}' $dir/cegs.$n.scp | utils/apply_map.pl -f 1 $dir/cegs.output.$n.ark.3 | awk '{print$2,$1}' > $dir/cegs.output.$n.ark
rm $dir/cegs.weight.$n.ark.*
rm $dir/cegs.output.$n.ark.*
rm $dir/$n.temp.ark.*
done

for i in combine train_diagnostic valid_diagnostic;do
nnet3-chain-copy-egs ark:exp_syll/chain/chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN/egs/$i.cegs ark,scp:$src/$i.cegs,$src/$i.scp
cp $src/$i.scp $dir/$i.scp
awk -F'-' '{$NF=null;print$0}' $dir/$i.scp | sed 's/ *$//' | tr ' ' '-' | paste -d ' ' - $dir/$i.scp | utils/filter_scp.pl false_alarm_rejection - > $dir/$i.temp.ark.1
awk '{print$2,"2.5"}' $dir/$i.temp.ark.1 > $dir/$i.weight.ark.1
awk '{print$2,"output-0"}' $dir/$i.temp.ark.1 > $dir/$i.output.ark.1

awk -F'-' '{$NF=null;print$0}' $dir/$i.scp| sed 's/ *$//' | tr ' ' '-' | paste -d ' ' - $dir/$i.scp | utils/filter_scp.pl --exclude false_alarm_rejection - > $dir/$i.temp.ark.2
awk '{print$2,"1"}' $dir/$i.temp.ark.2 > $dir/$i.weight.ark.2
awk '{print$2,"output-1"}' $dir/$i.temp.ark.2 > $dir/$i.output.ark.2

cat $dir/$i.weight.ark.1 $dir/$i.weight.ark.2 > $dir/$i.weight.ark.3
cat $dir/$i.output.ark.1 $dir/$i.output.ark.2 > $dir/$i.output.ark.3

awk '{print$1,$1}' $dir/$i.scp | utils/apply_map.pl -f 1 $dir/$i.weight.ark.3 | awk '{print$2,$1}' > $dir/$i.weight.ark
awk '{print$1,$1}' $dir/$i.scp | utils/apply_map.pl -f 1 $dir/$i.output.ark.3 | awk '{print$2,$1}' > $dir/$i.output.ark
rm $dir/$i.weight.ark.*
rm $dir/$i.output.ark.*
rm $dir/$i.temp.ark.*
done
  • 初始学习率设置为1.2e-04(8卡,脚本里对应0.000015)或者1e6,结果差不多
  • input_model:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/final_add_output01.mdl
  • 似乎是因为这是tdnn5的false alarm和false rejection样本,似乎对于tdnnf8无效,因此没有改善,应该用tdnnf8的解码训练集训一轮,会好一点

把以上对于tdnn5不同权重finetune一轮:

  • 脚本:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/run_tdnn_multilingual_tdnn5.sh

  • 模型:exp_syll/chain/chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_multitask

  • input_model:exp_syll/chain/chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/final_add_output01.mdl

  • 初始和结束的学习率都为==0.000001==(8卡,脚本里对应0.000000125)(是否有点小了?)

  • 有改善,改善比方法1多,不知道这个改善是否来源于多训练一轮epoch?

重新解码tdnnf8训练集,用tdnnf8解码的false alarm和false rejection样本finetune一轮

  • weight比例2.5:1,无论学习率是1e-6(8卡后)或者1.5e-5(8卡后),效果都没有改善
  • 查看有没有==过拟合==:grep output-0-xent compute_prob_valid.* | sed 's/valid./ /g' | sed 's/.log/ /g' | sort -k 2 -n
  • grep "average objective function for 'output-0'" train.*.1.log | sed 's/train./ /g' | sed 's/.1.log/ /g' | sort -k 1 -n
  • 少数测试集有改善

学习率设置

脚本里initial_lr(实际lr (乘以gpu数) 脚本里final_lr(实际lr (乘以gpu数)
普通 0.00015 0.000015
more_epoch 0.000015 0.0000015
false_reje_ala:训练的是tdnn5(结果不好) 0.00015 0.000015
false_reje_ala调小学习率:训练的是tdnn5(有改善) 1.25e-7(1e-06) 1.25e-7(1e-06)
multitask_test_input_model:训练的是tdnnf8(没有改善) 0.000015(0.00012) 0.0000015(1.2e-05)
multitask_test_input_model_small_learningrate:训练的是tdnnf8(没有改善) 1.25e-7(1e-06) 1.25e-7(1e-06)

测试解码

  • chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm

实验测试结果

  • 10000条命令词,测唤醒率

  • tdnn[1]:chain_tdnn5_256_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/graph_add_two

  • tdnn[2]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_filter_false_reje_ala_small_learningrate/graph

  • tdnn[3]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_multitask/graph

  • tdnn[4]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph

  • tdnnf[1]:chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm

  • tdnnf[2]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph_add_two2/

  • tdnnf[3]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch_multitask_tdnnf8decode/graph_10_1

  • tdnnf[4]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph1/ (2gram lm)[实际不可用]

  • 47万条随机语音片段,测误唤醒(479984)

  • tdnn[1]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/graph_add_two

  • tdnn[2]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_filter_false_reje_ala_small_learningrate/graph

  • tdnn[3]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_multitask/graph

  • tdnn[4]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph

  • tdnnf[1]:chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm

  • tdnnf[2]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph_add_two2/

  • tdnnf[3]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch_multitask_tdnnf8decode/graph_10_1

  • tdnnf[4]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph1/ (2gram lm)[实际不可用]

  • 小源小源一个唤醒词

  • lei:V1+SIL

  • tdnn[1]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/graph_add_two

  • tdnn[2]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_filter_false_reje_ala_small_learningrate/graph

  • tdnn[3]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_multitask/graph

  • tdnn[4]:chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph

  • tdnnf[1]:chain_tdnnf13_320_32_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/graph_add_two2 前向计算时间长,不考虑

  • tdnnf[2]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph_add_two2

  • tdnnf[3]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch_multitask_tdnnf8decode/graph_10_1

  • tdnnf[4]:chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph1/ (2gram lm)[实际不可用]

  • ()内是所有命令词的误唤醒

实验小结

  • 从声学模型输出观察:

pdf2phone exp_syll/chain/chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/final.mdl ark:feats.scp1.1.1 | utils/int2sym.pl -f 2- exp_syll/chain/chain_tdnn5_256_l39r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm/phones.txt -

发现确实是声学模型不够好造成的误触发。相似音(比如jing和ji)容易误触发

  • 多训练epoch效果有改善(4epoch->5epoch)

  • 学习率不能调高,否则易过拟合

  • 训练分母的phone lm从4gram到2gram,效果会提升,训练中复杂的语言模型反而没有带来收益,推测原因:

    • 1.简单的语言模型能让声学模型得到的信息更少,加重了声学模型的训练难度,使得声学模型训练得更不容易过拟合;
    • 2.复杂的语言模型(适配训练集的语言模型)使得声学模型更容易过拟合;
    • 3.训练中简单的语言模型与测试的1gram语言模型更接近;
  • 解码训练集,用false alarm和false rejection的样本,增加高一点权重(调参10:1和2.5:1),不同学习率,重训练一轮。结果没有改善

结果分析

  • 小源小源唤醒词的唤醒率、误唤醒基本可以达到要求,但是其他唤醒词的误唤醒还是比较高。
  • 尝试从样本出发:解码训练集,用false alarm和false rejection的样本,增加高一点权重(调参10:1和2.5:1),重训练一轮。结果:没有改善
  • 尝试从后处理出发:增加简单二级阈值判断(解码命令词起止时间长度,解码命令词cost值)。结果:没有改善,简单阈值判断不出。
  • 尝试从训练目标函数出发:用最大化状态/音素正确率作为目标函数(sMBR、MPE),增加唤醒词的唤醒率;尝试center loss减少类内距离(从而增加类间距离)(未完成)
  • 尝试从声学模型出发:tdnnf比tdnn好,在前向时间相同情况下尝试其他声学模型(未完成)

增加解码竞争路径

花哥说,用类似2gram语言模型思路,通过判断两个字前后的文本是怎样的,来抑制两个字的误触发。

具体做法思路:把1gram里的命令词去掉,放在2gram里

路径:25.3:/home/data/yelong/kaldi/egs/hi_mia/w1/data_syll/lang_context

HCLG:exp_syll/chain/chain_tdnnf8_432_48_l27r27_id_merge_all_sub4_12000_basedTDNN_smaller_phone_lm_more_epoch/graph1/

把四字放到2gram里,删掉1gram它的路径,效果没有提升反而下降,原因分析

该方法有效降低误触发,二、三字误触发能降低17%~30%

image-20211220141423434

1是开始状态,两个圈是结束状态。

表示只能以 2gram里只能以 比如 静音 开头,可以 有“静音 其他音” 的路径,但没有“其他音 静音” 的路径

与原先区别:命令词前有其他声音会降低唤醒率(要很大声)(现实总是有其他声音的,不可行)

实验不可行:测试0807(实际录音),小源小源也采用上述方法放进2gram,发现唤醒率很低。

虽然在test_1w里,四字的唤醒率没有降低,但是在0807实测测试集里,唤醒率大幅度降低

2gram

用训练集ali训练的2gram LM,误识别率可以下降34%,但是时间多5倍

剪枝后:

ngram -lm srilm.o3g.kn.gz -order 2 -prune 0.00001 -write-lm newlm:误唤醒能下降28%,时间2倍之前(雷博说这个可能测不准,要用keyword_lib测才会准一点)

ngram -lm srilm.o3g.kn.gz -order 2 -prune 0.0001 -write-lm newlm:误唤醒只能下降4%,时间1.4倍之前

降低一点点识别率,同时也降低误识别率的方法:

把相似音(比如zan的相似音zai、zi、zhan…….)的权重提高一点

误触发常发生在有个xiao/yuan开头的音,即使音后面不同,也会触发

我的意思是修改FST,让小源小源在发音发完整个词后,output label才是小源小源。

雷博说,现在输出文本,都是发完小源小源,达到结束state了,才会回溯判断是否有小源小源,不存在发音一半就出来小源小源的情况;

唯一可能减少一点误触发的方法就是,小/源状态自己也有结束state,可能到达小/源就结束;

但其实这个在垃圾路径里已经添加了,没有走到还是路径权重的原因;

image-20220104172646296