Kaldi命令词识别(续)

2017-03-08

kaldi

task4 : 特征提取(FMCC)

完成了语言模型的构建,下面开始生成声学模型部分,首先对语音文件进行特征提取,这里用到了上面准备的文件,包括:text, wav.scp, utt2spk, spk2utt 。
run.sh中完成特征提取,并对语音进行归一化处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
#gen MFCC features
rm -rf data/mfcc && mkdir -p data/mfcc && cp -R data/{train,cv,test} data/mfcc || exit 1;
for x in train cv test; do
#make mfcc
steps/make_mfcc.sh --nj $n --cmd "$train_cmd" data/mfcc/$x exp/make_mfcc/$x mfcc/$x || exit 1;
#compute cmvn
steps/compute_cmvn_stats.sh data/mfcc/$x exp/mfcc_cmvn/$x mfcc/$x || exit 1;
done
```

生成的特征提取相关文件保存在data/mfcc目录下,真实的数据保存在mfcc/目录下。
#### task5 : 训练声学模型、 构建解码图
该部分调用kaldi脚本,训练单音节模型,后面测试证明,单个词汇的识别,该模型同样能保证良好的识别效果,同样run.sh脚本中:

#monophone

#steps/train_mono.sh –boost-silence 1.25 –nj $n –cmd “$train_cmd” data/mfcc/train data/lang exp/mono || exit 1;

1
声学模型的训练结果文件保存在exp/mono目录下。下面构建解码图,这部分调用utils/mkgraph.sh, 利用先前创建的语言模型和上步训练的声学模型构建HCLG解码图,该部分生成的解码图保存在exp/mono/graph_word文件夹下:

utils/mkgraph.sh –mono –nj $n data/graph/lang exp/mono exp/mono/graph_word || exit 1;

1
2
3

#### task6: 测试
在local目录下创建data_decode.sh 脚本对解码步骤进行封装:

#!/bin/bash

#decoding wrapper

#run from ../
nj=2
mono=false
. ./cmd.sh ## You’ll want to change cmd.sh to something that will work on your system.
. ./path.sh ## Source the tools/utils (import the queue.pl)
. utils/parse_options.sh || exit 1;

decoder=$1
srcdir=$2
datadir=$3

if [ $mono = true ];then
echo “using monophone to generate graph”
opt=”–mono”
fi

#decode word
$decoder –cmd “$decode_cmd” $srcdir/graph_word $datadir/test $srcdir/decode_test_word || exit 1

1
在run.sh脚本中调用上脚本:

#test mono model
local/data_decode.sh –nj 2 “steps/decode.sh” exp/mono data/mfcc &

1
2
3
4
5
这里注意由于测试集只有两个说话者,并发度设置为2,否则会出现文件分割数与并发数不匹配的情况,解码过程主要用到特征提取后的test文件,上部分生成的解码图,测试结果在exp/mono/decode_test_word文件夹中查看。

为了对测试结果进行评估,还需在local目录下完成打分脚本相关的代码,这里参考thchs30,拷贝文件:score.sh、wer_output_filter 。

下面给出完整的run.sh脚本,之后运行脚本:

#!/bin/bash

. ./cmd.sh
. ./path.sh

run_path=pwd
n=8 #parallel jobs

#dataset path
dataset=~/dataset_wakeup

#data prepare

#gen text, wav.scp, utt2spk, spk2utt
local/data_prep.sh $run_path $dataset/King-ASR-M-005 || exit 1

#gen lang dir
(
echo “create new dir data/dict,lang,graph”
cd $run_path
mkdir -p data/{dict,lang,graph} && \
cp $dataset//resource/dict/{extra_questions.txt,nonsilence_phones.txt,optional_silence.txt,silence_phones.txt} data/dict && \
cat $dataset/resource/dict/lexicon.txt | \
grep -v ‘‘ | grep -v ‘‘ | sort -u > data/dict/lexicon.txt || exit 1;
utils/prepare_lang.sh –position_dependent_phones false data/dict “<SPOKEN_NOISE>” data/local/lang data/lang || exit 1;
gzip -c $dataset/King-ASR-M-005/lm_word/word.arpa > data/graph/word.arpa.gz || exit 1;
utils/format_lm.sh data/lang data/graph/word.arpa.gz $dataset/King-ASR-M-005/lm_word/lexicon.txt data/graph/lang || exit 1;
)

#gen MFCC features
rm -rf data/mfcc && mkdir -p data/mfcc && cp -R data/{train,cv,test} data/mfcc || exit 1;
for x in train cv test; do

#make mfcc
steps/make_mfcc.sh –nj $n –cmd “$train_cmd” data/mfcc/$x exp/make_mfcc/$x mfcc/$x || exit 1;

#compute cmvn
steps/compute_cmvn_stats.sh data/mfcc/$x exp/mfcc_cmvn/$x mfcc/$x || exit 1;
done

#monophone
steps/train_mono.sh –boost-silence 1.25 –nj $n –cmd “$train_cmd” data/mfcc/train data/lang exp/mono || exit 1;

#decode word

make decoder graph

utils/mkgraph.sh –mono data/graph/lang exp/mono exp/mono/graph_word || exit 1;

#test mono model
local/data_decode.sh –nj 2 “steps/decode.sh” exp/mono data/mfcc &

1
运行脚本,由于数据量不大,并不需要很长时间,运行测试结束查看效果:

[uesrname@hostname scoring_kaldi]$ ls
best_wer log penalty_0.0 penalty_0.5 penalty_1.0 test_filt.txt wer_details
[uesrname@hostname scoring_kaldi]$ more best_wer
%WER 5.57 [ 100 / 1795, 19 ins, 4 del, 77 sub ] exp/mono/decode_test_word/wer_17_1.0
`
错词率为5.57%,在penalty_1.0中可以查看最好的识别结果。

小结

文章记录了从拿到语料库,到应用Kaldi的全过程,主要想对流程进行总结,对语音识别相关的原理没有涉及太多。另外这里仅仅训练了单音节模型,其他模型可以参照thchs30完成,这里不再补充。
过程中遇到的小问题很多,一个比较典型的,一开始想偷懒直接使用thchs30的词典,后来识别结果很差,单词均为一个或两个毫不相干的字。考虑自己语料库中的词汇在thchs30的词典中并未涉及,还是通过自己标注词典解决问题。

更多关注公众号:
wechat