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. 参考

基于kaldi和CVTE开源模型的中文识别

(完)

posted @ 2021-12-26 11:10  大师兄啊哈  阅读(641)  评论(0编辑  收藏  举报