(九)kaldi thchs30 三音子模型(line 71-76)

2023-11-16

概览

首先放代码:

#triphone
steps/train_deltas.sh --boost-silence 1.25 --cmd "$train_cmd" 2000 10000 data/mfcc/train data/lang   exp/mono_ali exp/tri1 || exit 1;

#test tri1 model
local/thchs-30_decode.sh --nj $n "steps/decode.sh" exp/tri1 data/mfcc &

#triphone_ali
steps/align_si.sh --nj $n --cmd "$train_cmd" data/mfcc/train data/lang exp/tri1 exp/tri1_ali || exit 1;
  1. 其中第一行steps/train_deltas.sh就是三音子模型的训练部分,三音子的训练和单音素模型的主要区别是状态绑定部分,也是本讲的主要内容。

  2. 第二行是解码测试部分,可以看到该代码和单音素的解码测试是一样的,只是少了–mono选项,因此这里将略过它。

  3. 第三行是利用第一行训练得到的三因子模型来做强制对齐。代码也是和单音素时是一样的,只是输入模型的变化,因此也不再赘述。

因此总结以上来看实际上我们主要关注的就是第一行的train_deltas.sh部分,我在参考中放了很多关于状态绑定的链接,我在这里只是把大体它做了什么,大体的原理写出来,更深入的代码级别解释还请看参考。

train_deltas.sh

先看看代码的用法:

Usage: steps/train_deltas.sh <num-leaves> <tot-gauss> <data-dir> <lang-dir> <alignment-dir> <exp-dir>

其中num-leaves是叶子节点数目,tot-gauss是总高斯数目,data-dir是数据文件夹,lang-dir是存放语言的文件夹,alignment-dir是存放之前单音素对齐后结果的文件夹,exp-dir是存放三音子模型结果的文件夹.

line 75之前都是之前介绍过的比较简单的处理,包括设置环境、任务数,进行cmvn处理,定义feats变量等。下面讲集中精力在状态绑定的步骤上。

acc-tree-stats 与 sum-tree-stats 累积相关统计量

它的作用是为决策树的构建累积相关的统计量。,输入是声学模型、特征、对齐序列,输出为统计量。它的执行流程为:

  1. 打开声学模型,并从中读取TransitionModel,打开特征文件和对其文件。

  2. 对每一句话的特征和对应的对齐状态,调用程序AccumulateTreeStats()累积统计量tree_stats。

  3. 将tree_stats(累积统计量)转移到BuildTreeStatsType类型的变量stats中,将stats写到文件JOB.treeacc。

下面详细写一下这个统计量是怎么算的。首先我们要知道三音子及HMM状态据在Kaldi中的存储方式:

typedef std::vector<std::pair<EventKeyType,EventValueType> > EventType; 

其中EventKeyType用来表示HMM的状态信息,长pair<int, int>这样。其中第一个数取-1来标记它是HMM的状态信息而不是三音子的。第二个数可以取0,1,2用来表示这是该三音素是第几个HMM的状态.后面的EventValueType就用来表示三音子三个位置上的音素是什么,如(0, 10), (1, 11), (2,12)就表示最左面的(0)的音素为10(音素到数字映射后的数字),中间的音素为11,最右侧的是12这样。

在强制对齐之后,从左到右扫描对齐数据,我们能从中得到(三音素及HMM状态)和其对应的特征向量,也就是得到一个EventType和其对应的特征向量。在扫描过所有训练数据后,出现的每个EventType会对应多个特征向量。 于是,我们就可以发现,与一个EventType相关的统计量包括该EventType对应的特征向量的个数、这些特征向量的累加、这些特征向量的平方的累加。这三个值,就是GuassClusterable中需要保存的统计量,并且根据这三个统计量可以计算该EventType的似然。如果把多个EventType的统计量累加在一起,就可以计算这些EventType组成的状态集的似然,因为一个EventType实际就是一个状态state。

在扫描对齐数据累积统计量时,一个EventType对应一个Clusterable对象(确切来说是GaussClusterable对象)。在这个GaussCluterable对象中,成员count_保存着该EventType出现的次数,成员stats_矩阵的第一行保存着该EventType对应的所有特征向量的和,stats_矩阵的第二行保存着该EventType对应的所有特征向量的平方之和。

在构建决策树时,我们需要知道的所有信息就是从训练数据的对齐中得到的所有EventType(三音素+HMM状态id),和每个EventType对应的Clusterable对象。很自然的,我们可以把这两者的对应关系保存成一个对 pair<EventType, Clusterable*>,然后把所有的这些对保存成一个vector,所以构建决策树所用到的统计量可以表示成:

typedef std::vector<std::pair<EventType, Clusterable*> > BuildTreeStatsType;

cluster-phones 自动生成问题集

它的作用是对多个音素或多个因素集进行聚类。输入为决策树相关统计量treeacc、多个音素集sets.int。输出为自动生成的问题集(每个问题由多个音素组成)。用法为:

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

其执行的流程为:

  1. 从treeacc中读取统计量到BuildTreeStatsType stats;读取vector pdf_class_list,该变量指定所考虑的HMM状态,默认为1,也就是只考虑三状态HMM的中间状态;从sets.int读取vector > phone_sets;默认的三音素参数N=3,P=1。

  2. 若指定的mode为questions,调用AutomaticallyObtainQuestions()自动生成问题集vector > phone_sets_out;若指定的model为k-means,调用KMeansClusterPhones()。thchs30里只涉及questions模式。

  3. 将上述函数自动生成的phone_sets_out写到questions.int。

可以看到主要的问题就是如何根据相关统计量和音素集通过聚类的方式生成决策树。以下对该问题的处理流程做简述:

  1. 读取sets.int中的所有音素,保存在phones中。

  2. 调用FilterStatsByKey()把stats中只属于三音素第二个HMM状态的统计量留下(即只保留中间音素的统计量)。

  3. 调用SplitStatsByKey(),根据三音素的中间音素对retained_stats进行划分,把属于每个音素的统计量放在一个BuildTreeStatsType中。由参数P指定根据三音素的第几个音素进行划分,因为此处P是1,所以是三音素的中间音素。举个例子,我们实验室的所用的音素一共有215个,假设每个音素都出现在三音素的中间位置,对retained_stats进行划分之后,split_stats的元素个数是215,每一个元素保存着(中间音素都是x的所有三音素对应的所有统计量)。

  4. 调用SumStatsVec()把split_stats每个元素中的所有统计量加起来,得到每个中间音素的统计量,也就是summed_stats,其维数为音素个数。简单来说,从上一步我们知道,split_stats的每一个元素保存着中间音素都是x的所有三音素对应的所有统计量,因为音素x左右音素的不同,所以split_stats这个元素中保存的统计量有很多,现在把中间音素都是x的所有三音素对应的所有统计量累加起来(就是把这些GaussClusterable的count_相加、stats_相加);对split_stats的每个元素都执行这样的操作后,就得到了summed_stats。

  5. 根据sets.int指定的集合,累加同一个集合中音素的统计量。

  6. **调用TreeCluster(),对summed_stats_per_set进行聚类,生成相关信息。**TreeClusterer是使用自顶向下的树进行聚类的一个对象。points_中保存着初始化TreeClusterer对象时传递进来的每个点的统计量,该对象的聚类过程,就是为了把这些点分成一簇簇(cluster)。queue_是一个优先队列,队列中的每个元素是一个pair,这个pair的第二个数据保存着结点信息,这个pair的第一个数据是对该结点进行划分时所获得的似然的最大提升。使用优先队列则说明,对似然提升最大的结点优先进行划分,直到queue_为空。这个划分不是传统决策树的那种直接分裂,而是采用了聚类的方式进行。

  7. 调用ObtainSetsOfPhones(),由上一步得到的信息,生成问题集。大体流程为:
    a. 得到每个cluster(叶子结点)中的音素集;
    b. 将子结点的音素集加入到其父结点的音素集中(实现了“把从该结点可以到达的所有叶子结点合在一起构成一个问题”);
    c. 把原始的phone_set插入到问题集;
    d. 过滤问题集的重复项、空项,生成最终的问题集。

compile-question 编译question

它的输入为HMM的拓扑结构文件topo和上一步得到的question.txt,输出为question.qst。当key=0,1,2时,问题是对三音素中的每个音素分别问问题。当key=-1时问题是基于HMM的某个状态的,这和HMM的状态数目有关,通常为三个,得到的问题集为[[0],[0,1]], 如果为5个,则为[[0],[0,1],[0,1,2], [0,1,2,3]]。

build-tree 建立决策树tree

它的输入为关于tree的统计量、root文件、问题集和topo文件,输出为决策树。它主要调用to_pdf函数,该函数由roots文件中的所有音素集首先用GetStubMap()递归构初始的决策树,总的来说GetStubMap()对每一个音素集创建一个初始的叶子结点,一个音素集就是roots.int中的一行中的音素的集合,每个节点其实都是一个小决策树的树根,之后会进一步由这个叶子节点划分。

对于EvenType的每一个key(-1,0,1,2),在该key对应的问题集中(之前得到的对于HMM和音素的问题集)找到一个问题,使得对叶子结点划分后获得的似然提升最大。而后根据该问题进行分裂,直到叶子节点的类别满足要求或似然度提升小于阀值时停止分裂。此时每个叶子节点的音素集实现了状态绑定。

三音素的训练

三音素的训练和单音素模型的训练步骤之后就较为相似了,唯一需要注意的就是由于我们之前得到的是单音素模型的对齐序列,因此我们在使用它时要将其转换为三音素的,这个转换由convert-ali进行操作。根据每个单音素对齐序列中transition-id 我们可以直到表示单音素模型中哪个phone的哪个状态,因为虽然变成三音素了,中心位置phone和第几个状态没有变,根据决策树直接换成三音素模型中transition-id,输出新的对齐序列即可。从旧的tid转换成新的tid的流程大致如下:

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(九)kaldi thchs30 三音子模型(line 71-76) 的相关文章

随机推荐

  • 【leetcode刷题】最长回文子串

    题目描述 给你一个字符串 s 找到 s 中最长的回文子串 示例1 输入 s babad 输出 bab 解释 aba 同样是符合题意的答案 示例2 输入 s cbbd 输出 bb 方法一 暴力枚举 param string s return
  • 单片机概述习题以及答案

    一 填空 除了单片机这一名称之外 单片机还可称为 或 答 微控制器 嵌入式控制器 2 单片机与普通微型计算机的不同之处在于其将 和 三部分 通过内部 连接在一起 集成于一块芯片上 答 CPU 存储器 I O 口 总线 AT89S52 单片机
  • 线性代数期末抱佛脚

    1 Row operations steps for finding solution if possible in linear systems many linear equations 求解的方法有两种 第一种 如 若要求该矩阵的解
  • LSTM对比Bi-LSTM的电力负荷时间序列预测(Matlab)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 0 概述 1 电力负荷预测 2 滑动窗输入结构的构建 3 LSTM 4 Bi LSTM 5 运行结果 6 Matla
  • jQuery MiniUI 开发教程 树形控件 树形:懒加载树(五)

    b 懒加载树 b img http www miniui com docs api images lazytree gif img 参考示例 url http www miniui com demo tree lazytree html 懒
  • C++:读写INI文件

    C 读写INI文件 INI文件是一种常见的配置文件格式 用于存储应用程序的配置信息 在C 中 我们可以使用一些库来读取和写入INI文件 在本文中 我将向您展示如何使用C 读取和写入INI文件 读取INI文件 对于INI文件的读取 我们可以使
  • Spring Data JPA 多数据源的使用

    p 项目中使用多个数据源在以往工作中比较常见 微服务架构中不建议一个项目使用多个数据源 在微服务架构下 一个微服务拥有自己独立的一个数据库 如果此微服务要使用其他数据库的数据 需要调用对应库的微服务接口来调用 而不是在一个项目中连接使用多个
  • U盘安装redhat 7.4的最终解决方案

    U盘安装redhat 7 4的最终解决方案 终于将redhat 7 4装上x3650 M5服务器了 过程无比艰辛 因为与CentOS7有一定区别 与redhat6 8完全不同 遇到的问题有 A 刻录镜像的时候只能刻录一个4MB EFI文件夹
  • 详解TCP为什么不能是两次握手

    三次握手的过程 注意不要遗漏全双工下两缓存 读 写缓存 的分配和变量的分配 CLOSED 表示初始状态 LISTEN 该状态表示服务器端的某个SOCKET处于监听状态 可以接受连接 SYN SENT 这个状态与SYN RCVD遥相呼应 当客
  • 【golang】for range中取地址操作的陷阱

    Tips for range创建了每个元素的副本 而不是直接返回每个元素的引用 例子1 package main import fmt func main slice int 0 1 2 3 myMap make map int int f
  • ZooKeeper之Java客户端API使用—创建节点。

    客户端可以通过ZooKeeper的API来创建一个数据节点 有如下两个接口 String create final String path byte data List
  • LeetCode-1604. 警告一小时内使用相同员工卡大于等于三次的人【哈希表,排序,数组】

    LeetCode 1604 警告一小时内使用相同员工卡大于等于三次的人 哈希表 排序 数组 题目描述 解题思路一 时间转换成分钟数 直接解决跨天问题 用哈希表记录每个员工的名字以及对应的时间 然后遍历哈希表 对于每个员工 我们将该员工的所有
  • 跟我学Java设计模式第7天:行为型设计模式

    Java设计模式文章目录 跟我学Java设计模式第一天 设计模式概述和软件设计原则 跟我学Java设计模式第二天 简单工厂模式 工厂方法模式 抽象工厂模式 跟我学Java设计模式第三天 代理模式 适配器 装饰者等其中模式结构 跟我学Java
  • Qt安装(Windows平台)

    Qt 的安装组件分为两部分 一部分是 Qt 5 9 分类下的 该分类包含的是真正的 Qt 开发库组件 另一部分是 Tools 分类下的 该分类包含的是集成开发环境和编译工具 Qt 5 9 分类下的开发组件 组件 说明 MinGW 5 3 0
  • 【elementplus】解决el-table设置固定高度后,横向滚动条消失的问题

    消失的原因 因为我给el scrollbar bar设置了position static 覆盖了它原本的样式position absolute 解决 把position static删掉
  • hbase region 分配方式

    参与 Region 分配的重要对象 在 Region 分配过程当中 起着重要做用有以下一些对象 安全 HMaster 是 HBase 中的 Master server 仅有一个 HRegionServer 负责多个 HRegion 使之能向
  • Java调用ffmpeg进行视频.H264抽帧,并保存为图片

    Java调用ffmpeg进行视频 H264抽帧 并保存为图片 1 需求 2 解决 3 源码 参考 1 需求 对视频 D data 01 test H264进行抽帧并保存为图片 图片命名为1 jpg 2 jpg 图片保存在D data 01
  • 【华为OD机试】找朋友(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 在学校中 N个小朋友站成一队 第i个小朋友的身高为height i 第i个小朋友可以看到的第
  • 【第六期】人工智能工程师培养计划招生

    前 言 学院第四期课程在2019年10月结课 第一至第四期具有求职意向的同学中 目前已经有80 的同学拿到了国内外名企的AI算法岗位offer 或者国外名校的AI 硕士 全奖博士录取 offer 在大家的认可下 我们开始了第六期的课程 在本
  • (九)kaldi thchs30 三音子模型(line 71-76)

    概览 首先放代码 triphone steps train deltas sh boost silence 1 25 cmd train cmd 2000 10000 data mfcc train data lang exp mono a