应用HTK搭建语音拨号系统3:创建绑定状态的三音素HMM模型
选自:http://maotong.blog.hexun.com/6261873_d.html
苏统华
哈尔滨工业大学人工智能研究室
2006年10月30日
声明:版权所有,转载请注明作者和来源
该系统能够识别连续说出的数字串和若干组姓名。建模是针对子词(sub-word, eg. 音素),具有一定的可扩充性。当加入一个新名字时,只需修改发音词典和任务语法即可。模型为连续混合高斯输出,运用语音决策树聚类形成的绑定状态式三音素。
3. 创建绑定状态的三音素HMM模型
目的是加入上下文依赖(context-dependent)三音素模型并得到稳健的训练。包括两步,先由单音素得到三音素并重估参数,第二步就是绑定三音素的状态以使输出分布更加稳健。
[step 9]得到三音素HMM
上下文依赖三音素模型可以用单音素作为初始,再进行重估。由于重估时要三音素级标注文本,就先生成标注文本。
HLEd -n .\lists\triphones1 -l * -i .\labels\wintri.mlf mktri.led .\labels\aligned.mlf
编辑脚本mktri.led包括如下命令:
文件名:mktri.led |
WB sp WB sil TC |
其中文件wintri.mlf是由单音素标注文本文件aligned.mlf转换成的等价三音素标注文本。一个三音素的列表保存到了triphones1。
下面利用HMM编辑器初始化三音素模型。所用命令为:
HHEd -H .\hmms\hmm9\macros -H .\hmms\hmm9\hmmdefs -M .\hmms\hmm10 mktri.hed .\lists\monophones1
其中的mktri.hed文件由perl脚本生成:
perl .\scripts\maketrihed .\lists\monophones1 .\lists\triphones1
修改mktri.hed文件,把第一行的.\lists\triphones1改成./lists/triphones1。
运行HHEd得到如下警告,没有大碍的:
WARNING [-2631] ApplyTie: Macro T_sp has nothing to tie of type t in HHEd
WARNING [-2631] ApplyTie: Macro T_sil has nothing to tie of type t in HHEd
重估两次:
HERest -C .\config\config1 -I .\labels\wintri.mlf -t 250.0 150.0 1000.0 -S train.scp -H .\hmms\hmm10\macros -H .\hmms\hmm10\hmmdefs -M .\hmms\hmm11 .\lists\triphones1
HERest -C .\config\config1 -I .\labels\wintri.mlf -t 250.0 150.0 1000.0 -s stats -S train.scp -H .\hmms\hmm11\macros -H .\hmms\hmm11\hmmdefs -M .\hmms\hmm12 .\lists\triphones1
两次均会有如下警告,不用理会:
Pruning-On[250.0 150.0 1000.0]
WARNING [-2331] UpdateModels: ax-n[7] copied: only 1 egs in HERest
WARNING [-2331] UpdateModels: l-y+ax[26] copied: only 1 egs in HERest
WARNING [-2331] UpdateModels: y-ax+n[39] copied: only 1 egs in HERest
WARNING [-2331] UpdateModels: uw-l+y[43] copied: only 1 egs in HERest
试着执行一下识别任务,看看怎么样:
HVite -H .\hmms\hmm12\macros -H .\hmms\hmm12\hmmdefs -S test.scp -l * -i recout_step9.mlf -w wdnet -p 0.0 -s 5.0 .\dict\dict2 .\lists\triphones1
暂时未通过,报错:
ERROR [+8231] GetHCIModel: Cannot find hmm [y-]uw[+???]
FATAL ERROR - Terminating program HVite
令config2在config1基础上加入FORCECXTEXP=T,ALLOWXWRDEXP=F,仍没有改善。通过分析dict2,发现y-uw+?出现在单词SUE的第二种发音上。注释掉这一行,仍然报错,但跟上次的错误有了可喜的差别:
ERROR [+8231] GetHCIModel: Cannot find hmm [ao-]r[+???]
FATAL ERROR - Terminating program HVite
看来路子是对的。ao-r+?出现在单词FOUR的第二种发音上,再次注释掉,把进行了如上两行注释的字典存为dict4。重新运行HVite,不再出错:
HVite -H .\hmms\hmm12\macros -H .\hmms\hmm12\hmmdefs -S test.scp -l * -i .\results\recout_step9.mlf -w wdnet -p 0.0 -s 5.0 .\dict\dict4 .\lists\triphones1
dict4字典如下所示:
文件名:.\dict\dict4 |
CALL k ao l sp DAVE d ey v sp DIAL d ay ax l sp EIGHT ey t sp FIVE f ay v sp FOUR f ao sp #FOUR f ao r sp JULIAN jh uw l ia n sp JULIAN jh uw l y ax n sp LAW l ao sp LEE l iy sp NINE n ay n sp OH ow sp ONE w ah n sp PHIL f ih l sp PHONE f ow n sp SENT-END [] sil SENT-START [] sil SEVEN s eh v n sp SIX s ih k s sp STEVE s t iy v sp SUE s uw sp #SUE s y uw sp THREE th r iy sp TWO t uw sp TYLER t ay l ax sp WOOD w uh d sp YOUNG y ah ng sp ZERO z ia r ow sp |
进行识别验证:
HResults -I .\labels\testwords.mlf .\lists\monophones1 .\results\recout_step9.mlf
所得结果如下:
====================== HTK Results Analysis ======================= Date: Mon Oct 30 22:45:31 2006 Ref : .\labels\testwords.mlf Rec : .\results\recout_step9.mlf ------------------------ Overall Results -------------------------- SENT: %Correct=93.33 [H=14, S=1, N=15] WORD: %Corr=100.00, Acc=97.06 [H=68, D=0, S=0, I=2, N=68] ============================================================== |
可以看出,基于三音素的HMM比基于单音素的HMM有较大的性能提升。
我们进一步进行讨论dict4的由来。由于在step 8中对标记文本和语音数据进行了校准,对于象FOUR,SUE这样有多个发音的单词,在Vitebi算法的作用下,会选择最大化似然率的单词,而不是象step 4那样选择第一种读音。结果使dict2中的发音在扩展成三音素时在音素级真值文本中没有实例,当然也就找不到该三音素的HMM模型。这时会报错。根据这个原理,可以编一个Perl脚本自动对字典中没用到的单词注释掉。我把这个脚本命名为makedict.pl,包含在scripts文件夹里。它可以代替上面的手工注释工作,使用下面的命令可以得到dict4:
perl .\scripts\makedict.pl .\dict\dict2 .\dict\dict4 .\lists\triphones1
注8:hmm11下的模型文件并没有包含在压缩包里。
[step 10]绑定三音素
在上一步估计模型时,因数据不足导致很多分布的方差只好用截至方差vFloors。这一步就是通过绑定状态来共享数据,使输出分布更加的稳健。HHEd提供两种聚类状态的机制,这里采用的是决策树:
HHEd -H .\hmms\hmm12\macros -H .\hmms\hmm12\hmmdefs -M .\hmms\hmm13 tree.hed .\lists\triphones1 > log
上面的tree.hed用perl脚本mkclscript.prl (.\scripts\目录下)生成:
perl mkclscript.prl TB 350.0 .\lists\monophones1>tree.hed
这时候的tree.hed的内容:
文件名:中间tree.hed |
TB 350 "k_s2" {("k","*-k+*","k+*","*-k").state[2]} TB 350 "ao_s2" {("ao","*-ao+*","ao+*","*-ao").state[2]} …… TB 350 "z_s4" {("z","*-z+*","z+*","*-z").state[4]}
|
还要往tree.hed中插入问题集和trace等信息。最终形式如下:
文件名:最终tree.hed |
RO 100.0 stats TR 0 QS "R_NonBoundary" { *+* } …… QS "L_z" { z-* } TR 2 TB 350 "k_s2" {("k","*-k+*","k+*","*-k").state[2]} TB 350 "ao_s2" {("ao","*-ao+*","ao+*","*-ao").state[2]} …… TB 350 "z_s4" {("z","*-z+*","z+*","*-z").state[4]} TR 1 ST trees CO ./lists/tiedlist AU ./lists/fulllist |
在tree.hed中,tiedlist是绑定后的不同三音素列表。fulllist是输入参数,代表绑定前的所有三音素列表,所以要事先制作。HTK book的制作方法:
HDMan -b sp -n .\lists\fulllist -g global2.ded -l flog .\dict\beep-tri .\dict\beep
其中,文件global2.ded是在global.ded基础上加入了TC命令:
文件名:global2.ded |
AS sp RS cmu MP sil sil sp TC |
HDMan这里所做的工作包括1)按照global.ded的配置把beep字典中的发音扩展成(词内)三音素形式,保存到beep-tri字典;2)提取beep-tri中出现的所有不同三音素保存到fulllist列表中。但是你会发现,按照上述方式制作的fulllist在执行HHEd时会引发错误,下面是我得到的一个例子:
ERROR [+2662] FindProtoModel: no proto for k-b+l in hSet
FATAL ERROR - Terminating program HHEd
这是什么原因呢?其实上面错误提示中的k-b+l并没在我们的演示任务中出现。正因为没出现,所以HMM模型文件里没它的位置。要解决这个错误,有两种解决途径。第一个路子,既然提示模型文件里没有三音素的模型,那就给它制作一个。可以把单音素*-b+*的模型复制一份给k-b+l,对于其他没模型的三音素也这样处理。我们这里不用这个路子,因为工作量太大了一点点。我们走第二条路,这条路在htk的maillist中有人提到过,详见2006年4月24日的一封信,作者是Moustafa Nabil。这条路不用beep字典,而使用我们制作的任务字典。我们对dict2进行修改,另存为dict5,其中去掉了下述两项:
SENT-END [] sil
SENT-START [] sil
执行HDMan生成fulllist:
HDMan -b sp -n .\lists\fulllist -g global3.ded -l flog .\dict\dict5-tri .\dict\dict5
上面的global3.ded是在global2.ded基础上去掉了AS sp一行,因为dict5中的每一单词发音后已经存在sp了。文件global3.ded的内容如下:
文件名:global3.ded |
RS cmu MP sil sil sp TC |
重新执行HHEd,不会再出错了。我们重估两次:
HERest -C .\config\config1 -I .\labels\wintri.mlf -t 250.0 150.0 1000.0 -S train.scp -H .\hmms\hmm13\macros -H .\hmms\hmm13\hmmdefs -M .\hmms\hmm14 .\lists\tiedlist
出现如下错误:
ERROR [+5010] InitSource: Cannot open source file sil
ERROR [+7010] LoadHMMSet: Can't find file
ERROR [+2321] Initialise: LoadHMMSet failed
FATAL ERROR - Terminating program HERest
在fulllist中加入sil。重新运行HHEd一次,这时的HERest只有一个警告:
Pruning-On[250.0 150.0 1000.0]
WARNING [-2331] UpdateModels: ax-n[7] copied: only 1 egs in HERest
再重估一次:
HERest -C .\config\config1 -I .\labels\wintri.mlf -t 250.0 150.0 1000.0 -S train.scp -H .\hmms\hmm14\macros -H .\hmms\hmm14\hmmdefs -M .\hmms\hmm15 .\lists\tiedlist
这次的警告与上次相同,没有关系的。