![](https://img-blog.csdnimg.cn/20201014180756738.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
语音识别
文章平均质量分 67
hjx5200
这个作者很懒,什么都没留下…
展开
-
Visual Studio 2019编译HTKlib
HTKLib构建共享库原创 2022-09-28 15:52:20 · 276 阅读 · 0 评论 -
centos7按照kaldi遇到的问题
输入命令:lsb_release -aLSB Version: :core-4.1-amd64:core-4.1-noarchDistributor ID: CentOSDescription: CentOS Linux release 7.9.2009 (Core)Release: 7.9.2009Codename: Core系统是centos7输入命令:g++ -vUsing built-in specs.COLLECT_GCC=g++COL...原创 2021-12-13 20:35:19 · 554 阅读 · 1 评论 -
HTK的解码过程的理解又遇到瓶颈了
再次参考HTK book的12章、13章。重新捋一遍识别网络的构建过程和维特比解码过程。构建识别网络是重中之重,而它的基础是lattice,描述lattice的是Standard Lattice Format (SLF)文件。它的来源可能是Task Grammar或者bigram language model,用到的工具分别是HParse和HBuild。有了Word Net,发音字典dictionary和HMM模型集合,就可以进行识别了。可以从三个不同层次来看这个识别网络:词级别、模型级和状态级。原创 2021-06-30 17:52:51 · 147 阅读 · 0 评论 -
ProcessObservation代码解析
在解析ProcessObservation的代码过程中,遇到了些问题,比如tokenset和token的区别;在词内的状态间传递时,token的值如何变化。以及zhen原创 2021-06-16 00:17:27 · 110 阅读 · 0 评论 -
StartRecognition之ReOrderList函数解析
我的上一篇blog是关于AttachInst函数的代码解析,它的最后调用了ReOrderList,来重新排序待进入下一个识别的节点。下面接着看它是如何处理识别过程的。传入的can原创 2021-06-15 18:22:02 · 93 阅读 · 0 评论 -
HERest源码解析续
上一篇分析了HERest工具的大体流程,其中最主要的是它运用了前向后向算法来更新模型参数。只是捡了最重要的流程来梳理,目的是先有个大体的印象。这一篇就来详细的、从头到尾的解读HERest代码。分析它主要涉及的数据结构、StepBack和StepForward算法的具体计算过程,以及它们的背后的公式推导。 UttInfo *utt; /* utterance information storage */ FBInfo *fbInfo; /* forwar原创 2021-06-15 16:39:38 · 158 阅读 · 0 评论 -
HTK中Network的结构
Network是由lattice扩展而来的。除了依赖lattice,还有HMMSet、pronunciation等。在lattice中,每个节点是由一个Word指向一个DictEntry原创 2021-06-15 16:37:34 · 150 阅读 · 0 评论 -
StartRecognition之AttachInst函数解析
Network的initial数据类型是NetNode,它的类型是n_word。它是AddInitialFinal(Lattice *wnet, Network *net,int xc)函数中添加进入Network中的。原创 2021-06-15 16:31:06 · 121 阅读 · 0 评论 -
NetWork中NetNode的类型
/* Types of node that can appear in the network */enum { n_unused, /* Node Instance not yet assigned */ n_hmm=2, /* Node Instance represents HMM */ n_word=4, /* Node Instance represents word end (or null) */ .原创 2021-06-15 13:21:56 · 286 阅读 · 0 评论 -
StartRecognition代码解析
在此之前的十几篇Blog都是在介绍HTK的词典、词格网络、识别Phone网络、HMM参数训练过程等,都是为了在识别时有据可循。现在开始,如何一步一步的将观察序列幻化为ke原创 2021-06-15 13:20:17 · 169 阅读 · 0 评论 -
HTK中函数ProcessCrossWordLinks处理流程
首先说下这个函数的主要功能:第一遍调用时,heap!=null,会创建NetNode节点和links计数。怎么创建NetNode节点呢?它依据什么呢?就是Lattice中的元素。原创 2021-06-10 20:37:46 · 254 阅读 · 1 评论 -
HTK中!NULL节点和SENT_END以及SENT_START的区别与联系
SENT_END和SENT_START是两个单词,在系统词典里是有发音的"sil",是个单音子词。而!NULL是词格Lattice网络中的xu'ni原创 2021-06-10 18:04:27 · 359 阅读 · 1 评论 -
HTK的Network把所有的NetNode对象chain,并重新排序
涉及的代码如下: /* First disassemble wnHashTab and link to end nodes as necessary */ AddInitialFinal(lat,net,hci->xc); for (i=0; i<WNHASHSIZE; i++) { AddChain(net,wnHashTab[i]); } /* Finally chain all nodes together */ for (i=0;原创 2021-06-03 18:11:27 · 251 阅读 · 0 评论 -
Lattice的构建过程
我有一张地图,叫Lattice。它有多个成员叫LNode,数量是nn,成员之间有各种联系叫LArc,也有很多个na。原创 2021-06-03 13:32:01 · 479 阅读 · 0 评论 -
HTK中vocab的节点种类
分三种:一是nullWord,它是不发音的,也就是nullWord->pron==NULL,nullWord->nprons==0且LabId为“!NULL”,原创 2021-06-03 06:57:38 · 250 阅读 · 0 评论 -
HTK中的那些哈希表
第一个介绍的是LabId的hashtable#define HASHSIZE 250007 /* size of hash table */static NameCell *hashtab[HASHSIZE]; /* the actual table */一般HTK中的h原创 2021-06-02 23:02:44 · 153 阅读 · 0 评论 -
再谈Lattice如何扩展为Network
在解读解码过程中,发现在令牌如何在Network上传递还有些模糊。从而发现自己对Network的结构还没到无比熟悉的程度,所以这篇博客开始,重新、重头梳理HMMsLattice,到Network、原创 2021-06-01 17:37:18 · 299 阅读 · 0 评论 -
HTK解码过程
首先,调用StartRecognition函数。它的主要作业是设置一个识别的初始值,构建一个network和一个全局的PRecInfo对象,它保存识别过程中的一系列中间结果,比如jing原创 2021-06-01 07:20:05 · 163 阅读 · 2 评论 -
HTK模型扩展CreateWIModels函数
构建单词发音词内环境依赖音子,如果发音序列包含的音子数少于2,则为零。void CreateWIModels(PronHolder *pInst,int p,int q, Network *net,HMMSetCxtInfo *hci){ NetNode *node; HLink hmm; int j; for(j=q-1;j>p;j--) { hmm=GetHCIModel(hci,FindLContext(hci,pInst,j,0), .原创 2021-05-31 19:09:48 · 97 阅读 · 0 评论 -
HTK中Lattice词格的结构
Lattice是非常重要的数据结构,它是语音识别系统支持的高层次的抽象语法。一般由定义的gram生成。typedef struct lattice{ MemHeap *heap; /* Heap lattice uses */ LatFormat format; /* indicate which fields are valid */ Vocab *voc; /* Dictionary lattice原创 2021-05-27 21:44:31 · 454 阅读 · 0 评论 -
HTK中Vocab字典的结构
在语音识别系统中,发音字典是必备的元素之一。系统通过提供的发音字典在内存中构建一个字典对象,会在后续的训练、解码中使用到。本期blog就来跟踪下这个Vocab的细节是什么样的。首先贴一下这个Vocab的struct代码,大家有个直观的印象。typedef struct { int nwords; /* total number of words */ int nprons; /* total number of prons */ Word原创 2021-05-27 08:01:45 · 327 阅读 · 0 评论 -
HVite源码解析续
下面看看函数Network *ExpandWordNet(MemHeap *heap,Lattice *lat,Vocab *voc,HMMSet *hset)的处理流程。Network *ExpandWordNet(MemHeap *heap,Lattice *lat,Vocab *voc,HMMSet *hset){ HMMSetCxtInfo *hci; Network *net; NetNode *node,*wordNode,*chainNode; NetLink原创 2021-05-19 17:39:48 · 176 阅读 · 0 评论 -
HVite源码解析
HVite是解码工具,输出语音信号,和字典信息、声学模型、语言模型等条件下,输出对应的转录文本(transcription)。首先,字典(Vocab)的结构如下:typedef struct { int nwords; /* total number of words */ int nprons; /* total number of prons */ Word nullWord; /* dummy null word/node *原创 2021-05-17 21:54:54 · 342 阅读 · 1 评论 -
HERest源码解析续二
一直有个疑问在我心头,就是为什么有MacroDef这个概念,它和HMMDef是什么关系。从上一篇博客,我们知道MacroDef中的一个指针指向具体的HMMDef,在MacroDef中指定当前的HMM是什么类型。为什么要这样设计?带着这个疑问,看《HTK Book》第七章。HMM模型定义时,实现了一套形式语言,就是指定了包含哪些Token。这些就是这个形式语言的“单词”,把这些单词按照既定语法规则组织起来,就成了special domain language。Token包括<BeginHMM&g原创 2021-05-11 08:45:55 · 115 阅读 · 0 评论 -
HERest源码解析续
上一篇博客介绍了整个HERest工具最重要的功能,就是实现前向-后向算法(Baum-Welch)算法。并简单介绍了涉及的几个重要的数据结构,以及输入和输出。现在开始从头开始,了解这个实现过程,以前了然于心。 UttInfo *utt; /* utterance information storage */ FBInfo *fbInfo; /* forward-backward information storage */ HMMSet hset;原创 2021-05-09 20:21:16 · 124 阅读 · 0 评论 -
HERest源码解析
前面解析了HCompV源码,它主要功能是初始化hmm模型,定义一些宏。还没接触到模型训练。HMM模型训练算法是语音识别的算法中的难点之一。它的输入包括所有hmm模型的名称、以及初始的模型参数(在hmmdefs设置好了),特征参数文件(train.scp)和特征文件对应的MLF转写文件(phone0.mlf)。输出就是包含更新后的hmmdefs。先写最重要,也是比较难的,然后再分析一些程序流程、配置等。这样避免喧宾夺主。/* Load data and call FBFile: apply fo原创 2021-05-06 15:41:01 · 259 阅读 · 1 评论 -
HCompV源码再解析续三
希望这篇是这一轮最后一篇关于HCompV的博客。上一篇续二分析到通过LoadFile函数加载所有特征向量(MFCC_0_D_A)文件,然后把它们按维度累计分别列举measSum和squareSum。接下来就是如何计算单独的mean和variance了,其实就是一个简单的除法,再有一些加减。已经统计过了totalCount是计数一共多少帧(特征向量),看SetCovs函数。/* SetCovs: set covariance values in hmm */void SetCovs(void)原创 2021-05-05 23:54:29 · 378 阅读 · 0 评论 -
HCompV源码再解析续二
代码逻辑到这里是个分水岭,因此另开一个博客来继续下面的源码分析。之前一直是在为了最终目的做准备,主要包括创建HMMSet、读取proto模型文件、观察向量的配置文件,分配了内存累加器空间,其目的都是为了接下来的计算全局的方差和均值。/* LoadFile: load whole file or segments and accumulate variance */void LoadFile(char *fn){ ParmBuf pbuf; BufferInfo info; c原创 2021-05-05 00:18:40 · 279 阅读 · 0 评论 -
HCompV源码再解析续
上一篇博客介绍了到CreateHMM函数,它完成了创建名为“proto”的hmm,并且为HMMSet创建了mtab以及其他基础设施,例如NameCell指针的hashtable数组。顺着CreateHMM函数执行结束,HCompV调用LoadHMMSet。下面分析该函数的流程。它的函数签名为下所示: LoadHMMSet(HMMSet *hset, char *hmmDir, char *hmmExt)其中hmmDir,和hmmExt是命令行参数指定的hmm原型“***/proto”文件的目录原创 2021-05-04 00:55:38 · 268 阅读 · 0 评论 -
HCompV源码再解析
在还没开始讲解源码之前,我先贴出一个数据结构HMMSet:/* ---------------------- HMM Sets ----------------------------- */typedef struct _HMMSet{ MemHeap *hmem; /* memory heap for this HMM Set */ Boolean *firstElem; /* first element added to hmem durin...原创 2021-04-30 21:45:32 · 235 阅读 · 1 评论 -
HTK搜索与解码search&decode
上一篇博客说了,前向算法在解码过程中也有涉及的。其实解码中过程的viterbi维特比算法,与前向算法(forward algorithm)很类似,不同点在与前向算法是计算求和,而维特比算法是求最大路径,并记录下来,以便回溯。 (1)其实除了求最大值外,跟前向算法的计算过程依赖的参数都相似。同时,viterbi过程还需要另一个矩阵来保存中间参数,就是backpointer,它来指示每个viterbi网格节点的值是前一时刻的哪个状态计算得来的。而且,在初始步骤...原创 2020-12-17 18:35:09 · 265 阅读 · 0 评论 -
HMM之前向算法forward algorithm
前向算法在HMM模型的训练、解码和评估过程中都涉及到。掌握前向算法对彻底理解HMM非常必要。前向算法掌握之后,后向算法也就不再话下。首先给出前向算法的公式,然后一步一步解析它的计算过程。 (1)表示由代表的HMM模型,所有可能的状态下,在t时刻状态为j,且时间片1,2,…,t,产生的观察向量分别为的概率。现在就是要设计一个算法来计算该数值,并且时间和空间复杂度合理。利用动态规划法,通过一张表记录当前的计算结果,供下一时刻使用,避免了暴力求解的时间消耗。...原创 2020-12-16 23:39:00 · 719 阅读 · 0 评论 -
HTKbook翻译之第十三章HVite解码(维特比)
第十三章 HVite解码前一章描述了如何构建识别网络,指定什么是合法的语音输入,以及每个词是怎么发音的。有了这样一个网络和它对应的HMM集合,输入一段语音,就可以通过网络计算该语音片段经过的所有路径的概率。解码的任务就是从中找出概率最大的路径。前面提到过,在HTK中HRec模块实现了解码功能。它是利用令牌传递(token passing)的范式实现寻找最优路径,可以选择提供多个替代路径。后一种情况下,它会通过格栅的形式给出多个可能的假设,然后转换为N-best最优识别结果。HTK通过..翻译 2020-11-14 01:08:32 · 629 阅读 · 0 评论 -
HTKbook翻译之第十二章网络、词典及语言模型
第十二章 网络、词典及语言模型前几章描述了如何处理语音数据和训练各种HMM模型参数。本章及后面几章将集中描述如何通过HTK工具构建语音识别器。本章聚焦在网络和字典。一个词级网络描述了一系列可能被识别的词;对子词(sub word)模型而言,词典描述了构成每个词的系列子词。词级网络的典型代表是通过任务语法(Task Grammar)显示定义的所有合法词序列,或者一个“词循环(Word-loop)”,即把所有词放置于一个循环中,允许任意词之间相连接。词循环网络通常会被扩展会随机语言模型。网络还可以.翻译 2020-11-11 00:26:13 · 690 阅读 · 2 评论 -
语音识别之HTK入门(十)——HTK解码工具HVite源码分析
这一节讲的内容又是语音识别系统非常重要的一环——veterbi解码,前面我们经过了配置文件,处理音频数据,处理标注文本数据、通过Baum-Welch(前向-后向)算法评估模型参数等多个环节,目的都是为了在这一步通过已知的模型来把音频解码成对应的文字,实现对语音的识别功能。这篇如何通俗地讲解 viterbi 算法讲的比较入门,一看就懂,viterbi的实质也的确如此。现在就是要看它在HTK中是如何应用的,因为实际系统中涉及到很多细节,比如语法、剪枝优化、词的边界处理等等,会增加理解的复杂度,但是细心加耐心原创 2020-11-03 20:53:24 · 690 阅读 · 0 评论 -
语音识别之HTK入门(九)——绑定静音中间状态
前面几篇都是关于Baum—Welch算法及其在HTK中的实现。重点介绍了 HERest命令是如何通过B-W算法来更新模型参数的。总体感觉,我对模型“学习”的流程大体清楚了,但是若了解更多的细节还得花更多时间、精力分析。但是,作为一个入门系列,如果在这里继续纠缠,可能后面的步骤就得虎头蛇尾了,那样得不偿失。现在回顾下前面的步骤,尤其是如何处理【标注文本】的。标注后,我们拿到的文件格式是这样的。S0001 DIAL EIGHT FIVES0002 DIAL ZERO ZERO EIGHT SIX .原创 2020-11-03 15:47:07 · 661 阅读 · 0 评论 -
语音识别之HTK入门(八)——HTK中涉及的数据结构以及它们之间的包含关系
HTK里面涉及很多数据结构,前面断断续续提到HMMSet、HMM、Macro、StateElem、UttInfo等等,非常多,而且关系组合比较复杂。现在用图示的方式展示下,供参考。该图是通过Visio画的,转换成pdf之后效果不好。现在通过网盘下载:链接:https://pan.baidu.com/s/1iB-M6n7glAqg51j4PU_GwA提取码:ause这只是昨天(2020年10月30日)画的,后面随着代码分析,还会不断更新。...原创 2020-10-30 15:48:52 · 339 阅读 · 0 评论 -
语音识别之HTK入门(七)——HERest训练模型之Baum-Welch算法
上一个博客为B-W算法准备了基础,也就是前向算法和后向算法以及EM模型。现在看看到底Baum-Welch算法是如何利用上述算法及模型来更新HMM的参数的。之前也分析过多次了,在语音识别领域HMM模型之所以这么复杂,是因为观察向量对应的隐含转态不可得。存在隐藏数据,如果能得知这些标注数据,那么无论是计算初始概率,还是状态转移概率还是混淆概率都异常的简单、直接。隐藏向量,假设它为I,观察向量为O,(O,I)表明为完全数据。现在假设表示当前模型下,完全数据的联合概率,分别表示完全数据的对数似然概率原创 2020-10-26 17:23:55 · 1059 阅读 · 0 评论 -
语音识别之HTK入门(六)——HERest训练模型
我们利用HCompV工具初始化了一个全局的hmm模型,也熟悉了HTK的一些重要的数据结构。它的输出是更新后的proto和vFloor1两个文件,供下一步使用。在进入下一步之前,需要手工在hmm0目录下制作两个文件hmmdefs和macro,一个是为所有的既定hmm模型复制一个初始参数(除了sp),另一个macro宏文件。下面列出hmmdefs头两个模型参数,其实都一样的。~h "sil" <BEGINHMM> <NUMSTATES> 5 <STATE>原创 2020-10-14 21:06:55 · 635 阅读 · 0 评论 -
语音识别之HTK入门(五)——HCompV总结
前面几篇博客详细看了下HCompV工具是如何初始一个全局的HMM模型,刚接触的人可能会比较乱,我也是。现在做个总结、梳理,试图做到“心中有丘壑”。主要是看下涉及的几个重要的数据结构和函数,这也是C语言这种过程式语言主要的思维方式。首先我觉得最重要的数据结构就是sturct _HMMSet:/* ---------------------- HMM Sets ----------------------------- */typedef struct _HMMSet{ MemHeap *h原创 2020-10-13 20:51:56 · 758 阅读 · 0 评论