网站首页 > 开源技术 正文
三音素GMM与单音素GMM的主要差别在于决策树状态绑定,与GMM参数更新相关的原理、程序和类两者都是一样的。
在这个笔记中,我会首先介绍表示HMM的类HmmTopology和TransitionModel,然后介绍三音素GMM训练脚本train_deltas.sh用到的几个程序,这几个程序与单音素GMM的不同或者只在三音素GMM训练中出现。与GMM相关的其余部分请参考单音素GMM学习笔记。
HmmTipology
为什么要介绍HmmTopology(后简称HT)和TransitionModel(后简称TM)?前面我们几乎一直在讲GMM和决策树,那么HMM用什么表示?在Kaldi中用TM表示HMM,TM中包含一个HT对象,用来表示HMM拓扑结构。
在Kaldi数据准备阶段,Kaldi会在data/lang目录下自动生成表示HMM拓扑结构的文件topo,HT对象就保存topo中的信息。一是topo中都有哪些音素,保存在HT的数据成员phone_中;二是每个音素的HMM结构是什么,由HT的数据成员phone2idx_和entries_共同决定。我们用下面一个图来解构HmmTopology的数据成员。
TransitionModel
在单音素GMM初始化程序gmm-init-mono和三音素GMM初始化程序gmm-init-model中都会调用TM构造函数TransitionModel(const ContextDependencyInterface &ctx_dep,const HmmTopology &hmm_topo)来初始化TM。我们也就以此构造函数为切入口,来学习TransitionModel中各数据成员是怎么构造出来的。
我们先来看看TM都有哪些数据成员以及各自的作用:
HmmTopology topo_;
构造函数的调用过程如下两图所示:
下面我们对train_deltas.sh中与三音素GMM相关的几个程序逐个进行说明。
gmm-init-model
?示例:gmm-init-model tree treeacc topo 1.mdl
?作用:使用决策树tree和决策树统计量treeacc初始化GMM。
?流程:
1.读取tree, treeacc, topo。
2.用tree和topo初始化TransitionModel trans_model,trans_model中保存着每个音素和其每个状态对应的pdf-id的Tuple(实际为Triple).
3.调用InitAmGmm()初始化am_gmm;若提供old_tree_filename和old_model_filename,调用InitAmGmmFromOld()初始化am_gmm。在InitAmGmm()中,将stats划分到决策树的每个叶子上(对应一个pdf),用该pdf对应的stats的count_、x、x^2初始化该pdf对应的DiagGmm的参数weight_、means_invvars_、inv_vars_和gconsts_。
4.若指定参数--write-occs=1.occs,调用GetOccs()得到每个pdf对应的state occupancies(也就是该pdf对应的观测的数量,或者说该pdf对应的帧数),将state occupancies写到1.occs
5.将trans_model和am_gmm写到1.mdl,得到初始GMM模型。
gmm-mixup
?示例:gmm-mixup --mix-up=4000 1.mdl 1.occs 2.mdl
gmm-mixup --merge=2000 1.mdl 1.occs 2.mdl
?作用:用来增加GMM混合分量的个数,或合并GMM混合分量。
?流程:
1.从1.mdl里读取trans_model, am_gmm,从1.occs里读取occs。
2.若mixdown!=0,对am_gmm调用MergeByCount();若mixup!=0,对am_gmm调用SplitByCount()。
3.将trans_model和改变后的am_gmm写到1.mdl。
AmDiagGmm::SplitByCount()
根据occs,调用AmDiagGmm::GetSplitTargets()得到am_gmm中每个DiagGmm i应该增加到的混个分量个数targets[i]。GetSplitTargets()对观测数最多的pdf优先增加混合分量个数(使用优先队列实现)。对每个DiagGmm i,根据targets[i],调用DiagGmm::Split()增加该DiagGmm i的混合分量。Split()对混合分量中weights_最大的分量优先进行分割,将其权值对半分,一半留给自己一半分给新的分量,被分割分量的均值、方差相关参数直接复制给新分量,复制完后对新分量的均值、方差相关参数加一个随机的扰动。
convert-ali
由单音素GMM我们得到训练数据的对齐文件,但是单音素GMM中的TransitionModeltm1和三音素GMM中的TransitionModeltm2不同,两者的每个数据成员都不一样,所以要把用tm1的tid(transition-id)表示的对齐转换成tm2的tid表示的对齐。这就是convert-ali的作用。
要看懂convert-ali,首先要对TransitionModel理解得比较清楚。建议先搞明白TM再去看该程序的代码。
我个人觉得这里的核心在于:根据tid能知道当前是哪个音素的哪个HMM状态(知道tid和对应的TM,由id2state_知道t-state,由state2id和tid只能t-idx,由t-state索引tuple_知道tuple,tuple保存音素、HMM state-id,也就知道了这两者),而无论该特征向量所对应的tid编号怎么变化,该特征向量对应的音素和HMM状态都是不变的。
从旧的tid转换成新的tid的流程大致如下:
明白了上述流程之后,convert-ali的代码就容易看懂了,这里我不再讲述细节,只把自己当时学习的手写笔记草稿放在这里,希望能有一定启发。
由convert-ali得到基于新的TransitionModel的对齐后,后面的GMM参数更新就和单音素GMM一样,GMM参数更新就是对每一个GMM(也就是每一个pdf)更新相应的参数。由对齐序列(tid序列),我们就能找到属于每一个pdf的特征向量,用这些特征向量更新该pdf的每个分量的均值、方差和权值即可。
猜你喜欢
- 2024-10-11 kaldi合并HI-MIA唤醒recipe(pdf合并在线免费)
- 2024-10-11 萌妹的最爱,又可爱又好喝的KALDI 限定低酒精水果味鸡尾酒
- 2024-10-11 kaldi语音识别工具集(kaldi中文语音识别)
- 2024-10-11 Vosk开源语音识别引擎kaldi的开发套件支持Asterisk
- 2024-07-05 语音识别工具包Kaldi的学习和使用(二):安装前的准备
- 2024-07-05 kaldi合并出门问问唤醒recipe(hello和hi的区别)
- 2024-07-05 纯PyTorch语音工具包开源,Kaldi:我压力有点大
- 2024-07-05 日本零食分享第二弹:KALDI(日本,零食)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)