最近在学习工具包HTK的使用,看了官网提供的htkbook,对工具包的使用有很多不清楚,对HMM模型及语音识别的过程还没有一个比较清晰的认识,所以想通过实践来加深理解。搜了网上关于HTK的入门资料,比较多的是介绍如何建立一个Yes/No的识别系统,有本pdf叫HTK basic tutorial就是讲如何建立该系统。但由于页数比较多,本人较懒,我就直接参考一些博客所说的步骤来执行。在这过程中,遇到了一些“坑”,让我执腾了一下,因此写这篇文章来记录下。我是在Windows下使用HTK工具包的,接下来简单介绍下建立Yes/No识别系统的步骤。
1、 建立一个工作目录,在该目录下打开命令窗口(在该目录下按shit+鼠标右键可看到“在此处打开命令窗口”)。输入hslab yes.sig,打开UI界面,选择rec,对着Mic说“Yes”,说完后选stop,此时可在波形窗口看到所录的波形。
接下来需要对这段波形标签,我们将波形分成三段:“sil”,“yes”,“sil”(yes前后有两个静音段,标签名称都为sil)。通过界面很容易标签,首先选择Mark,选择该标签的起点终点,再选择Labelas,输入标签名,注意标签名之间不能重叠。标签完后,选择save保存,可以看到有yes_0.sig,yes_0.lab两个文件,我们需要将文件重命名,比如yes_00.sig,yes_00.lab,防止被覆盖。然后选择new,开始录新的“Yes”。重复上面的步骤,生成yes_00.sig ~ yes_09.sig,yes_00.lab ~ yes_09.lab,注意录音和标签文件需足够多,否则后面则行Hinit时会报Error。
同样建立no_00.sig ~ no_09.sig,no_00.lab ~ no_09.lab
我分别建立了sig_dir和label_dir,用来放*.sig和*.lab文件
2、 对*.sig进行前处理及特征提取,建立文件analysis.conf,文件内容为:
SOURCEFORMAT = HTK
TARGETKIND = MFCC_0_D_A
WINDOWSIZE = 250000.0
TARGETRATE = 100000.0
NUMCEPS = 12
USEHAMMING = T
PREEMCOEF = 0.97
NUMCHANS = 26
CEPLIFTER = 22
建立mfcc_dir,用来存放生成的mfcc文件,还需建文件targetlist.txt,内容为:
sig_dir/yes_00.sig mfcc_dir/yes_00.mfcc
sig_dir/yes_01.sig mfcc_dir/yes_01.mfcc
sig_dir/yes_02.sig mfcc_dir/yes_02.mfcc
sig_dir/yes_03.sig mfcc_dir/yes_03.mfcc
sig_dir/yes_04.sig mfcc_dir/yes_04.mfcc
sig_dir/yes_05.sig mfcc_dir/yes_05.mfcc
sig_dir/yes_06.sig mfcc_dir/yes_06.mfcc
sig_dir/yes_07.sig mfcc_dir/yes_07.mfcc
sig_dir/yes_08.sig mfcc_dir/yes_08.mfcc
sig_dir/yes_09.sig mfcc_dir/yes_09.mfcc
sig_dir/no_00.sig mfcc_dir/no_00.mfcc
sig_dir/no_01.sig mfcc_dir/no_01.mfcc
sig_dir/no_02.sig mfcc_dir/no_02.mfcc
sig_dir/no_03.sig mfcc_dir/no_03.mfcc
sig_dir/no_04.sig mfcc_dir/no_04.mfcc
sig_dir/no_05.sig mfcc_dir/no_05.mfcc
sig_dir/no_06.sig mfcc_dir/no_06.mfcc
sig_dir/no_07.sig mfcc_dir/no_07.mfcc
sig_dir/no_08.sig mfcc_dir/no_08.mfcc
sig_dir/no_09.sig mfcc_dir/no_09.mfcc
sig_dir/no_10.sig mfcc_dir/no_10.mfcc
在命令窗口中输入:Hcopy -A -D -C analysis.conf -S targetlist.txt,可看到在mfcc_dir目录下生成*.mfcc文件
3、 得到了特征参数,我们需要建立HMM模型,我们需要建立yes,no,sil的HMM模型,我们需要建立三个文件,hmm_yes、hmm_no、hmm_sil,内容如下:
文件hmm_yes:
~o <VecSize> 39 <MFCC_0_D_A>
~h "yes"
<BeginHMM>
<NumStates> 6
<State> 2
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 3
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 4
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 5
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<TransP> 6
0.0 0.5 0.5 0.0 0.0 0.0
0.0 0.4 0.3 0.3 0.0 0.0
0.0 0.0 0.4 0.3 0.3 0.0
0.0 0.0 0.0 0.4 0.3 0.3
0.0 0.0 0.0 0.0 0.5 0.5
0.0 0.0 0.0 0.0 0.0 0.0
<EndHMM>
文件hmm_no:
~h "no"
<BeginHMM>
<NumStates> 6
<State> 2
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 3
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 4
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 5
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<TransP> 6
0.0 0.5 0.5 0.0 0.0 0.0
0.0 0.4 0.3 0.3 0.0 0.0
0.0 0.0 0.4 0.3 0.3 0.0
0.0 0.0 0.0 0.4 0.3 0.3
0.0 0.0 0.0 0.0 0.5 0.5
0.0 0.0 0.0 0.0 0.0 0.0
<EndHMM>
文件hmm_sil:
~o <VecSize> 39 <MFCC_0_D_A>
~h "sil"
<BeginHMM>
<NumStates> 6
<State> 2
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 3
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 4
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<State> 5
<Mean> 39
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
<Variance> 39
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
<TransP> 6
0.0 0.5 0.5 0.0 0.0 0.0
0.0 0.4 0.3 0.3 0.0 0.0
0.0 0.0 0.4 0.3 0.3 0.0
0.0 0.0 0.0 0.4 0.3 0.3
0.0 0.0 0.0 0.0 0.5 0.5
0.0 0.0 0.0 0.0 0.0 0.0
<EndHMM>
4、 对模型初始化,需要用到命令Hinit和Hcompv。建立文件trainlist_sil.txt,内容如下:
mfcc_dir/yes_00.mfcc
mfcc_dir/yes_01.mfcc
mfcc_dir/yes_02.mfcc
mfcc_dir/yes_03.mfcc
mfcc_dir/yes_04.mfcc
mfcc_dir/yes_05.mfcc
mfcc_dir/yes_06.mfcc
mfcc_dir/yes_07.mfcc
mfcc_dir/yes_08.mfcc
mfcc_dir/yes_09.mfcc
mfcc_dir/no_00.mfcc
mfcc_dir/no_01.mfcc
mfcc_dir/no_02.mfcc
mfcc_dir/no_03.mfcc
mfcc_dir/no_04.mfcc
mfcc_dir/no_05.mfcc
mfcc_dir/no_06.mfcc
mfcc_dir/no_07.mfcc
mfcc_dir/no_08.mfcc
mfcc_dir/no_09.mfcc
mfcc_dir/no_10.mfcc
建立hmm0目录保存HMM模型初始化结果,分别输入以下命令
hinit -A -D -T 1 -S trainlist.txt -M hmm0 -H hmm_yes -l yes -L label_dir yes
hinit -A -D -T 1 -S trainlist.txt -M hmm0 -H hmm_no -l no -L label_dir no
hinit -A -D -T 1 -S trainlist.txt -M hmm0 -H hmm_sil -l sil -L label_dir sil
在执行第三条命令时,遇到如下错误:
我是通过以下方式解决,具体原因不清楚。建立trainlist_sil.txt文件,内容如下:
mfcc_dir/yes_00.mfcc
mfcc_dir/yes_01.mfcc
mfcc_dir/yes_02.mfcc
mfcc_dir/yes_03.mfcc
mfcc_dir/yes_04.mfcc
mfcc_dir/yes_05.mfcc
mfcc_dir/yes_06.mfcc
mfcc_dir/yes_07.mfcc
mfcc_dir/yes_08.mfcc
mfcc_dir/yes_09.mfcc
将命令换成hinit -A -D -T 1 -S trainlist_sil.txt -M hmm0 -H hmm_sil -l sil -L label_dir sil
顺利执行这三条命令后,在hmm0目录下生成hmm_yes,hmm_no,hmm_sil,这三个文件与我们自己建立的内容是不一样的。
我们还需要用Hcompv生成vFloors,建立hmm0flat目录,输入以下命令:
Hcompv -A -D -T 1 -S trainlist.txt -M hmm0flat -H hmm_yes -f 0.01 yes
运行后可在hmm0flat下看到vFloors文件,将其拷贝到工作目录下
5、 接下来要做的就是对模型进行训练。新建hmm1,hmm2,hmm3这三个文件夹,分别保存三次训练的结果。
第一次训练yes:
HRest -A -D -T 1 -S trainlist.txt -M hmm1 -H vFloors -H hmm0\hmm_yes -l yes -L label_dir yes
执行这条命令时,发生如下错误
改命令的顺序可以解决问题,修改后为:
HRest -A -D -T 1 -S trainlist.txt -M hmm1 -H hmm0\hmm_yes -H vFloors -l yes -L label_dir yes
第二次训练yes:
HRest -A -D -T 1 -S trainlist.txt -M hmm2 -H hmm1\hmm_yes -H vFloors -l yes -L label_dir yes
第三次训练yes:
HRest -A -D -T 1 -S trainlist.txt -M hmm3 -H hmm2\hmm_yes -H vFloors -l yes -L label_dir yes
同样的方法,可以对no及sil进行训练,输入:
HRest -A -D -T 1 -S trainlist.txt -M hmm1 -H hmm0\hmm_no -H vFloors -l no -L label_dir no
HRest -A -D -T 1 -S trainlist.txt -M hmm2 -H hmm1\hmm_no -H vFloors -l no -L label_dir no
HRest -A -D -T 1 -S trainlist.txt -M hmm3 -H hmm2\hmm_no -H vFloors -l no -L label_dir no
HRest -A -D -T 1 -S trainlist.txt -M hmm1 -H hmm0\hmm_sil -H vFloors -l sil -L label_dir sil
HRest -A -D -T 1 -S trainlist.txt -M hmm2 -H hmm1\hmm_sil -H vFloors -l sil -L label_dir sil
HRest -A -D -T 1 -S trainlist.txt -M hmm3 -H hmm2\hmm_sil -H vFloors -l sil -L label_dir sil
6、 建立句法文件gram.txt,文件内容如下:
$WORD = YES | NO;
( { START_SIL } [ $WORD ] { END_SIL } )
建立词典文件dict.txt,内容如下:
YES [yes] yes
NO [no] no
START_SIL [sil] sil
END_SIL [sil] sil
用如下命令将句法文件gram.txt编译成网络:
HParse -A -D -T 1 gram.txt net.slf
用如下命令查字典文件中的错误:
HSGen -A -D -n 10 -s net.slf dict.txt
7、 建立文件hmmlist.txt,其内容为:
yes
no
sil
建立文件input.mfcc(通过步骤1、2的方式)或直接用已经产生的yes_xx.mfcc或no_xx.mfcc。执行如下命令:
HVite -A -D -T 1 -H hmm3\hmm_yes -H hmm3\hmm_no -H hmm3\hmm_sil -I reco.mlf -w net.slf dict.txt hmmlist.txt input.mfcc
reco.mlf保存了识别结果,如果提示没有文件reco.mlf,那就先建个reco.mlf空文件。
8、 交互式识别
建立文件derectin.conf:
SOURCERATE = 625.0
SOURCEKIND = HAUDIO
SOURCEFORMAT = HTK
TARGETKIND = MFCC_0_D_A
WINDOWSIZE = 250000.0
TARGETRATE = 100000.0
NUMCEPS = 12
USEHAMMING = T
PREEMCOEF = 0.97
NUMCHANS = 26
CEPLIFTER = 22
AUDIOSIG = -1
输入命令:
HVite -A -D -T 1 -C directin.conf -g -H hmm3\hmm_yes -H hmm3\hmm_no -H hmm3\hmm_sil -w net.slf dict.txt hmmlist.txt