triphone训练

转载1:https://blog.csdn.net/fengzhou_/article/details/78066589

转载2:https://blog.csdn.net/fengzhou_/article/details/78070595

目录

决策树部分

1. acc-tree-stats

2. cluster-phones

3. compile-question

4. build-tree

训练部分

1. gmm-init-model

2. gmm-mixup

3. convert-ali


决策树部分

1. acc-tree-stats

Usage:  acc-tree-stats [options] <model-in> <features rspecifier> <alignments-rspecifier> <tree-accs-out>

输入:模型,特征,对齐序列
输出:决策树的统计量

首先读入Transition Model,从 contex_indep.csl中读取要训练的所有三音素, 保存在 AccumulateTreeStatsInfo 对象的ci_phones中。然后对于每帧语音特征和与其相应的对齐序列,进行统计量的计算。调用以下函数:

 AccumulateTreeStats(trans_model,
                     acc_tree_stats_info,
                     alignment,
                     mat,
                     &tree_stats);

该函数累计统计量,保存在BuildTreeStatsType中。
BuildTreeStatsType也就是 vector <EventType, GaussClusterable*> stats
EventTpye也是一个vector,里面存的是一个pair<EventKeyType, EventValueType>, EventKeyType是一个int,表示三音素位置(0,1,2)或者HMM的state(-1),EventKeyValue也是int,表示三音素的phone-ID或者对应HMM(-1)的state-id(通常为0,1,2 )。
例如: EventType e = { (-1, 1), (0, 10), (1, 11), (2,12) }中,表示三音素为(10,11,12)中第一个HMM state。
对于每帧语音,由其对齐序列可以得知transition-id,也就知道了对应哪个phone。因此我们可以统计phone出现的次数以及该条特征的均值方差等统计量存放在GaussClusterable的结构体中。因此,对所有的特征数据、对齐数据执行这个函数后,我们得到了所有的EventType和每个EventType对应的统计量,我们之后用它来进行决策树,问题集的构建。 

2. cluster-phones

Usage:  cluster-phones [options] <tree-stats-in> <phone-sets-in> <clustered-phones-out>

输入:决策树统计量,音素集 
输出:问题的文本表示

该命令的核心函数如下,根据统计量stats,问题集phones,输出问题集phone_sets_out。pdf-class-list和P表示用于过滤的phone或者state。

AutomaticallyObtainQuestions(stats,
                             phone_sets,
                             pdf_class_list,
                             P,
                             &phone_sets_out);

pdf-class-list = 1表示只用中间状态的统计量,其他都抛弃

  BuildTreeStatsType retained_stats;
  FilterStatsByKey(stats, kPdfClass, all_pdf_classes,
                   true,  // retain only the listed positions
                   &retained_stats); 

P = 1表示中间音素,我们累加某一固定中间音素的所有三音素的统计量 
得到split_stats

std::vector<BuildTreeStatsType> split_stats;  // split by phone.
SplitStatsByKey(retained_stats, P, &split_stats);

依照sets.int 音素集文件将每行共享的统计量累加,再调用TreeCluster用Kmeans算法依照统计量对所有三音素进行聚类

  TreeCluster(summed_stats_per_set,
              summed_stats_per_set.size(),  // max-#clust is all of the points.
              NULL,  // don't need the clusters out.
              &assignments,
              &clust_assignments,
              &num_leaves,
              topts);

最后如下用ObtainSetsOfPhones输出树中每个节点所含的phones。这里包含叶子节点和它的parent(非叶子节点),因此同一个phone可能在多个节点(多个问题)出现。注意kaldi里一个问题就是一个phone set。

  ObtainSetsOfPhones(phone_sets,
                     assignments,
                     clust_assignments,
                     num_leaves,
                     questions_out);

3. compile-question

Usage:  compile-questions [options] <topo> <questions-text-file> <questions-out>

输入:拓扑结构topo,question.txt
输出:question.qst

分为两个部分,音素位置相关的问题HMM状态位置的问题

当key为0,1,2时,问题是基于音素位置的问题,即对三音素中的每个音素分别问问题.

kaldi里用Questions 和 QuestionsForKey 这两个类来表示。Questions里面为音素位置和QuestionsForKey,QuestionsForKey为问题即一些音素集,初始化均为question.txt。

当key为-1时,问题是基于HMM的某个状态的,这和HMM的状态数目有关,通常为三个,得到的问题集为[[0],[0,1]], 如果为5个,则为[[0],[0,1],[0,1,2], [0,1,2,3]].

4. build-tree

Usage:  build-tree [options] <tree-stats-in> <roots-file> <questions-file> <topo-file> <tree-out>

输入:关于tree的统计量,root文件,问题集,topo文件

输出:决策树tree

主要调用如下函数

   to_pdf = BuildTree(qo,
                       phone_sets,
                       phone2num_pdf_classes,
                       is_shared_root,
                       is_split_root,
                       stats,
                       thresh,
                       max_leaves,
                       cluster_thresh,
                       P);

qo是问题集,phone_set是由roots文件得到,roots文件里说明了是否要share相同决策树根结点是否需要进一步进行划分的的phone

该函数由roots文件中的所有音素集首先用GetStubMap()递归构初始的决策树,总的来说GetStubMap()对每一个音素集创建一个初始的叶子结点,一个音素集就是roots.int中的一行中的音素的集合,每个节点其实都是一个小决策树的树根,之后会进一步由这个叶子节点划分

EventMap *tree_split = SplitDecisionTree(*tree_stub,
filtered_stats, q_opts, thresh, max_leaves,&num_leaves,&impr, &smallest_split);

首先对于EvenType的每一个key(-1,0,1,2),在该key对应的问题集中(由q_opts给出每个key的问题集)找到一个问题,使得对叶子结点划分后获得的似然提升最大

 

训练部分

前面已经提到了如何对三音素聚类,构建决策树,接下来进行对三音素中各个GMM进行训练。三音素训练部分和单音素大致相同,都是运用EM算法进行参数的更新,具体部分可以看单音素训练部分。同样也是用gmm-align-compiled,gmm-acc-stats-ali,gmm-est这三个进行参数更新,重新对齐等。本文因此主要介绍与单音素训练不同的初始化部分。 

1. gmm-init-model

Usage: gmm-init-model [options] <tree-in> <tree-stats-in> <topo-file> <model-out> [<old-tree> <old-model>]

输入:决策树,决策树统计量,topo文件
输出:三音素的模型

读取决策树的统计量计算mean,mean_invvar,gconst等建立声学模型am-gmm,运用该函数InitAmGmm()。用tree和topo初始化TransitionModel trans_model。将transition model和am-gmm 共同输入到1.mdl中作为初始化的三音素模型, 并用GetOccs()将每个pdf的occupancy输出为1.occ

2. gmm-mixup

Usage:  gmm-mixup [options] <model-in> <state-occs-in> <model-out>

输入:三音素模型,每个pdf所占的分量
输出:新的模型

这一步用MergeByCount()或者SplitByCount(), 分裂或者合并单高斯直到和指定的高斯数目一样,最后输出新的模型。其中用到的算法和单音素训练中gmm-est里提到的一样,这里不再详述。

3. convert-ali

Usage:  convert-ali  [options] <old-model> <new-model> <new-tree> <old-alignments-rspecifier> <new-alignments-wspecifier>

输入:训练好的单音素模型,三音素模型,tree,单音素的对齐序列
输出:三音素的对齐序列

之前由单音素GMM我们得到训练数据的对齐文件,但是单音素GMM中的模型和三音素GMM中模型不同,两者的每个数据成员都不一样,所以要把用单音素表示的对齐转换成三音素表示的对齐

根据每个单音素对齐序列中transition-id 我们可以直到表示单音素模型中哪个phone的哪个状态,因为虽然变成三音素了,中心位置phone和第几个状态没有变,根据决策树直接换成三音素模型中transition-id,输出新的对齐序列即可。

最后由convert-ali得到三音素中心的对齐后,后面的GMM参数更新就和单音素GMM一样,采用EM算法。

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值