在Kaldi的egs文件下有很多基于公共语音数据库的训练步骤及测试结果,其中也有中文的,本文就相对很简单的yesno样例结合脚本以及脚本运行结果进行详细的解析,以更好地理解语音识别的整体流程。
我们先来看一下run.sh脚本
cd ./egs/yesno/s5/
vi run.sh
========================================================================
#!/bin/bash
train_cmd="utils/run.pl"
decode_cmd="utils/run.pl"if [ ! -d waves_yesno ]; then
wget http://www.openslr.org/resources/1/waves_yesno.tar.gz || exit 1;
# was:
# wget http://sourceforge.net/projects/kaldi/files/waves_yesno.tar.gz || exit 1;
tar -xvzf waves_yesno.tar.gz || exit 1;
fitrain_yesno=train_yesno
test_base_name=test_yesnorm -rf data exp mfcc
# Data preparation
local/prepare_data.sh waves_yesno
local/prepare_dict.sh
utils/prepare_lang.sh --position-dependent-phones false data/local/dict "" data/local/lang data/lang
local/prepare_lm.sh# Feature extraction
for x in train_yesno test_yesno; do
steps/make_mfcc.sh --nj 1 data/$x exp/make_mfcc/$x mfcc
steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x mfcc
utils/fix_data_dir.sh data/$x
done# Mono training
steps/train_mono.sh --nj 1 --cmd "$train_cmd" \
--totgauss 400 \
data/train_yesno data/lang exp/mono0a
# Graph compilation
utils/mkgraph.sh data/lang_test_tg exp/mono0a exp/mono0a/graph_tgpr# Decoding
steps/decode.sh --nj 1 --cmd "$decode_cmd" \
exp/mono0a/graph_tgpr data/test_yesno exp/mono0a/decode_test_yesnofor x in exp/*/decode*; do [ -d $x ] && grep WER $x/wer_* | utils/best_wer.sh; done
if [ ! -d waves_yesno ]; then
wget http://www.openslr.org/resources/1/waves_yesno.tar.gz || exit 1;
# was:
# wget http://sourceforge.net/projects/kaldi/files/waves_yesno.tar.gz || exit 1;
tar -xvzf waves_yesno.tar.gz || exit 1;
fi
每个wav文件中的发音都是Yes, No。其中,文件名中的1代表Yes,0代表No,从文件名可以知道wav的内容,这种格式方便后面的数据准备,当然文件存在大量发音的时候不可能采用如此的文件命名方式。
local/prepare_data.sh waves_yesno
结果保存在s5/data/train_yesno和s5/data/test_yesno中,主要有下面几个文件
text :音频文件id(文件名)与单词的对应
wav.scp :音频文件id与音频文件的对应
utt2spk :音频文件id与说话人的对应
spk2utt:说话人id与音频文件id的对应
其大致步骤为:将60个音频文件提取出文件id,其中30个作为训练,剩余30个作为测试。根据文件名中的1和0获取音频文件的内容。将其写入相应的文件,在实际大规模音频内容的情况下,需要自己制作上面的文件来做数据准备。
local/prepare_dict.sh
结果保存在s5/data/local/dict/目录下面
lexicon.txt:完整的词位(包含静音SIL)-音素对
lexicon_words.txt:单词-音素对
silence_phones.txt: 非语言学音素
nonsilence_phones.txt:语言学音素
optional_silence.txt :备选非语言音素
其大致步骤为:将input的文件夹下的已经写好的文件复制到该目录下,并加入SIL。
utils/prepare_lang.sh --position-dependent-phones false data/local/dict "
" data/local/lang data/lang
结果保存在s5/data/lang/目录下
phones.txt:音素与整形的对应(openfst格式的symbol tables),以后的操作单词将以整形数字代替
words.txt:单词与整形的对应(openfst格式的symbol tables),以后的操作音素将以整形数字代替
L_disambig.fst:加消歧符号的字典fst(可以被kaldi识别的字典)
L.fst:字典fst(可以被kaldi识别的字典)
topo:音素状态转移图(HMM)Y,N每个音素为三种状态;SIL为五种状态
oov:词汇表之外的单词会映射到该文件中
phones:该目录下有许多关于音素集的信息。同一类信息可能有三种不同的格式,分别以.csl、.int和.txt结尾。感兴趣的话可以逐个打开查看!~~~
local/prepare_lm.sh
该脚本其实很简单,将已经生成好的语言模型(s5/input/task.arpabo)转化为Kaldi格式的G.fst,其结果在s5/data/lang_test_tg目录下,有关语言模型创建可参考语音识别-SRILM安装与使用。
for x in train_yesno test_yesno; do
steps/make_mfcc.sh --nj 1 data/$x exp/make_mfcc/$x mfcc
steps/compute_cmvn_stats.sh data/$x exp/make_mfcc/$x mfcc
utils/fix_data_dir.sh data/$x
done
结果在s5/mfcc/目录下
其中ark文件为MFCC的特征向量;scp文件是音频文件或说话人与相应ark文件的对应关系;前缀cmvn为说话人,raw为音频文件。有关MFCC可以参考语音识别-MFCC特征提取。
steps/train_mono.sh --nj 1 --cmd "$train_cmd" \
--totgauss 400 \
data/train_yesno data/lang exp/mono0a
该步的输出在s5/exp/mono0a/目录下,该步骤将生成声学模型。
utils/mkgraph.sh data/lang_test_tg exp/mono0a exp/mono0a/graph_tgpr
该步骤生成最终的HCLG.fst.
steps/decode.sh --nj 1 --cmd "$decode_cmd" \
exp/mono0a/graph_tgpr data/test_yesno exp/mono0a/decode_test_yesno
结果在s5/exp/mono0a/decode_test_yesno/目录下
for x in exp/*/decode*; do [ -d $x ] && grep WER $x/wer_* | utils/best_wer.sh; done
egs下面各个文件夹的脚本不一样,但步骤都差不多。天气太热了,坐不住,其有些细节方面未涉及,也算是详解吧,哈哈!~~~