kaldi aidatatang_asr 项目如何测试准确率(cer/wer)
原文链接:https://www.cnblogs.com/harrymore/p/15732493.html
1. 前言
我们知道,在kaldi的egs中有很多例子,在运行run.sh的时候,会对测试集进行推断,中间会留下很多日志,其中在日志叫cer_xxx或者wer_xxx的,可以找到相应的字准确率或词准确率,当然我们使用普通话模型的时候,使用cer就可以了。
一般来说,kaldi的数据集,除了wav和标签文件之外,一般还需要wav.scp,text,spk2utt,utt2spk,当然在aidatatang_asr中想知道测试结果的cer,使用text文件就可以了,文件的具体内容为:
uttid word1 word2 ...
具体可以参考:基于kaldi和CVTE开源模型的中文识别
2. 代码研究
通过观察cvte的run.sh,可以发现,计算cer需要两个文件,一个是标签文件,也就是音频对应的实际的文字;一个是预测的结果。这些可以通过egs/cvte/s5/run.sh->egs/cvte/s5/steps/nnet3/decode.sh->egs/cvte/s5/local/score.sh找到最后评分调用的文件为egs/cvte/s5/steps/scoring/score_kaldi_cer.sh。
通过研究其中的内容发现,最终计算cer的命令为:
compute-wer --text --mode=present ark:data/train/text ark:hyp_text
如果是计算字准确率的话,还需要将两个text文件中的文字都分割并以空格隔开。同样的,通过score_kaldi_cer.sh可以得知处理的逻辑为:
cat $f | perl -CSDA -ane ' { print $F[0]; foreach $s (@F[1..$#F]) { if (($s =~ /\[.*\]/) || ($s =~ /\<.*\>/) || ($s =~ "!SIL")) { print " $s"; } else { @chars = split "", $s; foreach $c (@chars) { print " $c"; } } } print "\n"; }' > $fout
于是我们可以把cer处理总结为两步,首先对text中的文字进行分割,然后对标签text和预测text进行计算,得出cer。
3. 相关代码
aidatatang_asr推断语音数据的时候,会按照当天的日期进行命名,我们可以在run.sh中,生成预测文件后面增加一条语句:
local/score.sh exp/chain/tdnn_1a_sp/decode_offline_test_$vdate/rec_$vdate.txt ${wav_dir}/text
然后在local中增加自己的score.sh进行处理即可,其中${wav_dir}/text为我自己生成的音频标注文件,格式可参考前言。
local/score.sh:
#!/usr/bin/env bash set -e -o pipefail set -x echo "$0 $@" # Print the command line for logging [ -f ./path.sh ] && . ./path.sh . parse_options.sh || exit 1; result_file=$1 text_file=$2 for f in $result_file $text_file; do [ ! -f $f ] && echo "$0: no such file $f" && exit 1; done dir=$(dirname ${result_file}) cat $text_file > $dir/test_filt.txt || exit 1; files=("${result_file}" "$dir/test_filt.txt") for f in "${files[@]}" ; do fout=${f%.txt}.chars.txt if [ -x local/character_tokenizer ]; then cat $f | local/character_tokenizer > $fout else cat $f | perl -CSDA -ane ' { print $F[0]; foreach $s (@F[1..$#F]) { if (($s =~ /\[.*\]/) || ($s =~ /\<.*\>/) || ($s =~ "!SIL")) { print " $s"; } else { @chars = split "", $s; foreach $c (@chars) { print " $c"; } } } print "\n"; }' > $fout fi done compute-wer --text --mode=present \ ark:${dir}/test_filt.chars.txt ark:"${result_file%.txt}".chars.txt >& ${dir}/cer || exit1
最后的cer数据我重定向到推断结果所在的文件夹,也可以自己进行定制。
4. 参考
(完)