http://www.voxforge.org/home/dev/acousticmodels/linux/create/htkjulius/tutorial
目标:
该系统能够识别连续说出的数字串和若干组姓名。建模是针对子词(sub-word,eg..音素),具有一定的可扩充性。当加入一个新名字时,只需修改发音词典和任务语法即可。模型为连续混合高斯输出,运用语音决策树聚类形成的绑定状态式三音素。
内容:
1.数据准备
(1) 任务语法定义
(2) 字典定义
(4) 标注数据,得到真值文件
(5) 数据特征的提取
2.创建单音素HMM模型
(7) 修补哑音素模型
(8) 重新校正数据
3.创建绑定状态的三音素HMM模型
(9) 得到三音素HMM
(10) 绑定三音素
4.识别器评估
(11)验证测试结果
步骤:
1.数据准备
需要录制训练数据和测试数据。为了进行校准,还需要数据的标注文本。这里用任务语法(task grammar)产生真值文本(ground truth).为了处理训练数据,需要定义一个语音集合和一个字典用以涵盖训练和测试数据中涉及的单词。
(1) 任务语法定义
任务语法以包含变量的正则表达式形式定义,存储在文件gram(手工制作,在Notepad++或UltraEdit环境下进行,最后要空一行)里:
上面的语法是高层表示,必须通过HParse转换成HTK的底层表示。
运行指令:HParse gram wdnet
底层表示存于文件wdnet(HParse工具生成 )中。
(2) 字典定义
利用BEEP语音词典(现成的),除去其中的重音符。
在每个发音后加入sp(short pause).如果有哑音标志,就用MP命令把sil和sp合并成sil,这些处理命令放在global.ded(手工制作)的脚本中。
文件wlist(此系统由于涉及的单词较少,于是手工制作即可)是出现在任务语法中的所有单词的有序列表。
文件names是专有人名的发音(手工制作,包括SEND-START,SENT-END)。
执行HDMan:
HDMan -m -w lists/wlist -g global.ded -n lists/monophones0 -l dlog dict/dict1 dict/beep dict/names
生成的文件monophones0是用到的音素列表(包括sp),生成的dlog是参数文件,其中包含生成的字典dict1的相关统计信息,还会提示是否丢失单词。生成的与任务相关的发音词典dict1,需要手工修改,为SENT-END和SENT-START加上无输出标志。
为了避免在dlog里出现warnning,可在names和beep同一目录下分别建立同名的编辑脚本,内容为空即可。
(3) 录制语音数据
HSGen工具可以生成符合task grammar 的句子,用来指导录音:
HSGen -l -n 10 wdnet dict/dict1>labels/trainprompts
HSGen -l -n 10 wdnet dict/dict1>labels/testprompts
根据上述生成的指令文件,录制相应的10个训练用语音数据文件和10个测试用语音数据文件。一个录制例子如下:
HSLab ./data/Train/speech/S0001
(4) 标注数据,得到真值文件
perl脚本prompts2mlf(现成的)可以把录音文本截成单词级真值文件trainwords_2.mlf,testwords_2.mlf:
perl scripts/prompts2mlf labels/trainwords_2.mlf labels/trainprompts
perl scripts/prompts2mlf labels/testwords_2.mlf labels/testprompts
注:将生成的文件trainwords_2.mlf(testwords_2.mlf) 按trainwords_1.mlf(testwords_1.mlf) 的格式"*/S0*.lab"添加到其文件末尾,并保存为trainwords.mlf(testwords.mlf)
标注编辑器HLEd 可把单词级真值文本(word level MLF)转成音素级真值文本(phone level MLF)phones0.mlf:
HLEd -l * -d dict/dict1 -i labels/phones0.mlf mkphones0.led labels/trainwords.mlf
编辑脚本mkphones0.led 的内容如下:
其中EX 命令表示按照字典dict1 进行展开,IS 表示在每个话语的前后插入标志,DE 一行表示phones0.mlf 中单词间不用sp 隔开。
(5) 数据的特征提取
这里所用特征为MFCC。工具HCopy 可以实现提取特征的工作。
HCopy -T 1 -C config/config1 -S codetr.scp
其中,配置文件config1要设置转换参数(红色标出),config内容如下:
# Coding parameters
TARGETKIND = MFCC_0_D_A //目标文件参数类型
TARGETRATE = 100000.0 //目标速率,100帧/秒,即帧移0.01ms
SOURCEFORMAT = WAV //源文件格式
SAVECOMPRESSED = T //以压缩的方式存储
SAVEWITHCRC = T //附加校验和到输出参数中
ZMEANSOURCE=TRUE
SOURCERATE=208 //源文件的速率
WINDOWSIZE = 250000.0 //以25ms为一帧进行分帧处理
USEHAMMING = T //采用汉明窗,进行加窗处理
PREEMCOEF = 0.97 //预加重系数
NUMCHANS = 26 //26组滤波器
CEPLIFTER = 22 //倒谱滤波系数
NUMCEPS = 12 //参数个数
实现该命令所需的脚本文件codetr.scp可采用如下方式生成:在DOS环境下进入到wav文件所在路径,用dir/b/s > wav.scp指令将所有的wav文件名写入到wav.scp文件中(注意删除多出的一行),然后在Notepad++中构造下图所示的文件, 存为coder.scp。(注:生成的wav.scp中的文件路径是绝对路径,可以手动改成相对路径)
codetr.scp指定训练及输入和输出文件列表。执行结果,HCopy 对codetr.scp 文件左侧的语音数据按config 1的配置提取特征并存入codetr.scp 文件右侧特征文件中。
对于测试数据如法炮制。
HCopy -T 1 -C config/config1 -S codete.scp
2.创建单音素HMM模型
(6)一致初始化法创建单音素模型
定义一个原始模型proto:
训练文件train.scp的生成也是在DOS环境下进入到MFCC特征的文件路径下,执行 dir/b/s> train.scp。需要注意的是要在Nodepad++或UltraEdit下把多余的一行删除掉。
用全局均值和方差来初始化HMM模型的高斯参数:
HCompV -T 1 -C config/config1 -f 0.01 -m -S train.scp -M hmms/hmm0 proto
在目录hmm0 下生成了更新后的proto和一个截至宏vFloors。基于./hmms/hmm0/下的两个文件,手工制作主宏文件hmmdefs和与vFloors相关的宏macro,具体制作过程参见HTKbook。
由于暂时不使用sp模型,删除monophones0中的sp,构成monophones1文件,重估参数:
HERest -C config/config1 -I labels/phones0.mlf -t 250.0 150.0 1000.0 -S train.scp -H hmms/hmm0/macros -H hmms/hmm0/hmmdefs -M hmms/hmm1 lists/monophones1
同上,重复估计两次:
HERest -C ./config/config1 -I ./labels/phones0.mlf -t 250.0 150.0 1000.0 -S train.scp -H ./hmms/hmm1/macros -H ./hmms//hmm1/hmmdefs -M ./hmms/hmm2 ./lists/monophones1
HERest -C ./config/config1 -I ./labels/phones0.mlf -t 250.0 150.0 1000.0 -S train.scp -H ./hmms/hmm2/macros -H ./hmms/hmm2/hmmdefs -M ./hmms/hmm3 ./lists/monophones1
(6) 修补哑音素模型
将hmm3中的macros复制到hmm4中,hmmdefs中的sil复制到文件末尾并将sil改为sp及状态改为3放到hmm4。
(1)利用HHEd 加入回溯转移概率:
HHEd -T 1 -H hmms/hmm4/macros -H hmms/hmm4/hmmdefs -M hmms/hmm5 sil.hed lists/monophones0
修改mkphones0.led,去掉最后一行,存为mkphones1.led,利用HLEd 工具得到包含sp
的音素级真值文本:
HLEd -l * -d ./dict/dict1 -i ./labels/phones1.mlf mkphones1.led ./labels/trainwords.mlf
(2)重估两次:
HERest -C config/config1 -I labels/phones0.mlf -t 250.0 150.0 1000.0 -S train.scp -H hmms/hmm5/macros -H hmms/hmm5/hmmdefs -M hmms/hmm6 lists/monophones0
HERest -C config/config1 -I labels/phones0.mlf -t 250.0 150.0 1000.0 -S train.scp -H hmms/hmm6/macros -H hmms/hmm6/hmmdefs -M hmms/hmm7 lists/monophones0
(8)重校准训练数据
确认trainwords.mlf 中的路径为”*/S0*.lab”并且加上前面的140句话,修改dict1 加入silence sil 一项,另存为dict2,执行HVite 进行Viterbi 校准:
HVite -l * -o SWT -b silence -C config/config1 -a -H hmms/hmm7/macros -H hmms/hmm7/hmmdefs -i labels/aligned.mlf -m -t 350.0 -y lab -I labels/trainwords.mlf -S train.scp dict/dict2 lists/monophones0
利用HERest重估两次,最后保存到hmm9
HERest_3.4 -C config/config1 -I labels/aligned.mlf -t 250.0 150.0 1000.0 -S train.scp -H hmms/hmm7/macros -H hmms/hmm7/hmmdefs -M hmms/hmm8 lists/monophones0
HERest_3.4 -C config/config1 -I labels/aligned.mlf -t 250.0 150.0 1000.0 -S train.scp -H hmms/hmm8/macros -H hmms/hmm8/hmmdefs -M hmms/hmm9 lists/monophones0
来看看这时的识别率怎么样:
HVite -H ./hmms/hmm9/macros -H ./hmms/hmm9/hmmdefs -S test.scp -l * -i ./results/recout_step9.mlf -w wdnet -p 0.0 -s 5.0 ./dict/dict2 ./lists/monophones0
HResults -I ./labels/testwords.mlf ./lists/monophones0 results/recout_step9.mlf