Kaldi的三音子模型训练(源码解析)

单音子模型的假设是一个音素的实际发音与其左右的音素无关 。这个假设与实际并不符合 。由于单音子模型过于简单 , 识别结果不能达到最好 , 因此需要继续优化升级 。就此引入多音子的模型 。最为熟悉的就是三音子模型 , 即上下文相关的声学模型 。以kaldi的thchs30为例 。
总过程
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
三音子模型训练
通过单音素模型得到单音素各个状态所有对应的特征集合 。然后做上下文的扩展得到三音素的各个状态所有对应的特征集合 。我们可以把训练数据上所有的单音素的数据对齐转为三音素的对齐 。
问:为什么要做状态绑定?
答:假如有218音素 , 若使用三音子模型则有218的3次方个三音子 。
如果不进行聚类 , 需要建立218*218*218*3个混合gmm模型(假设每个triphone有3个状态) 。一方面计算量巨大 , 另一方面会引起数据稀疏 。所以会根据数据特征对三音子的状态进行绑定 。
train_deltas.sh
源码解析:
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
需要的文件:
$alidir/final.mdl$alidir/ali.1.gz$data/feats.scp$lang/phones.txt
过程:
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
累计相关统计量
统计量:phone的特征均值、方差、phone所出现的语音帧数量 。
问:为什么需要累计相关统计量?
答:为自动产生问题集做准备 , 问题集又是为了构建决策树做准备 。
自动产生问题集时决策树分裂是依据似然增益最大原则来进行的 。分裂前和分裂后的似然变化(增益)为D=L(Sl)+L(Sr)-L(S) , 似然增益越大 , 说明分裂后的两部分数据之间的差距越大 , 则越应该使用两个单独的GMM分别建模 。
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
状态集S的似然L(S) , 根据L(S)的计算公式 , 需要知道状态集S产生的所有观测的协方差 , 对角协方差的对角线上是特征向量集每一维的方差 。
想知道每一维的方差就需要知道特征向量集的和以及特征向量集的平方和(D(X)=E(X^2)-(EX)^2) 。计算L(S)除了要知道协方差 , 还需要知道状态集S产生的特征向量的个数 , 也就是状态集S出现的次数 。
acc-tree-stats.cc
功能:为决策树的构建累积相关的统计量 。
输入:声学模型、特征、对齐
输出:统计量 。
源码解析:
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
其中 , 在得到统计量之前 , 我们需要对每个句子进行维特比强制对齐 。
Kaldi的三音子模型训练(源码解析)
文章图片

文章图片
有了强制对齐结果 , 就可以得到每一帧是属于哪个EventType 。对齐训练里面保存的数字是transition-id , 根据transition-id可以得到三音素及其对应的状态 。根据EventType的所有帧对应的特征得到这个EventType的统计量(出现次数count_ , 特征向量的均值和均值的平方) 。统计量的结果保存在treeacc文件中:
Kaldi的三音子模型训练(源码解析)