HTK Book 第二篇 HTK深度探索.docx
《HTK Book 第二篇 HTK深度探索.docx》由会员分享,可在线阅读,更多相关《HTK Book 第二篇 HTK深度探索.docx(56页珍藏版)》请在冰豆网上搜索。
HTKBook第二篇HTK深度探索
第一章HTK基础
1.5识别和Viterbi解码
前面介绍了HMM参数估计所使用的BW算法。
在前向算法中,
表示的是对于特定模型M,观察到向量o1到ot,并且在时刻t处于状态j的概率。
这是一个确定的值,通过累加所有的前一个状态到状态j的转移,可以得到前向概率的计算方式
这里介绍Viterbi算法。
识别,基于最大似然的状态序列,这种方法可以很好地用于连续语音,如果使用总概率就很难做到。
这个概率的计算,本质上和前向概率的计算一样,只不过,前向概率在每一步都是求和操作,这里每一步都是一次最大化操作。
对于给定的模型M,假定
表示给定模型M,观察到向量o1到ot,并且在时刻t处于状态j的概率最大,
就是这个最大概率。
这个概率可以使用下面的迭代公式计算。
也许要问了,难道这个值不是固定的吗?
怎么还存在一个最大概率?
难道还有其它值吗?
答:
在前向概率计算中,每个观察向量都对每个状态作出某种程度的贡献,这个程度,也就是该观察向量,处于状态i的概率。
假设有N个状态,那么每个时间点t的观察向量,都对N个状态有所贡献,因此对每一个状态,需要将每个时间点的贡献累积起来,计算均值和协方差。
但是,每个时间点t的观察向量,对每个状态的贡献程度是不同的,肯定有一个最大的概率,也就是说,最可能对应的是哪个状态?
这样,就认为这个观察向量只属于此状态,只用于此状态的参数计算。
这就是Viterbi算法的思想。
上面公式的含义,是对于所有的状态i∈N,求时间t处观察向量概率最大的状态j。
在时间t处,观察到o1到ot,并且处于某状态的概率是所有状态中的最大值。
这么理解也不完全正确。
对于任何状态j∈N,在每个时间t处,都可以计算
的值,也就是说,每个状态都有这个值。
最大化操作,实际上是针对前一个时间点t-1的,要找一个t-1时刻使得
最大的状态i,使用这个状态i的
和aij的乘积,作为比较依据,取一个最大值得i。
这里的最大化操作,是针对状态i的,也就是说,从一个唯一的t-1时刻的状态i,来得到状态j的
值。
以上理解错误,最大化操作还是针对时间t的,也就是当前步骤的。
其中
那么,对于模型M,观察的数据O的最大似然概率
则是
这种形式的迭代就是Viterbi算法的基础。
如下图所示,这个算法可以看做是寻找最佳路径的过程。
矩阵中的Y轴表示模型的各状态,X轴表示语音帧(即时间)。
图中的每个原点表示在时间t处观察到该语音帧的概率,点之间的弧表示一个转移概率。
那么,任何路径的概率都可以通过简单地将路径上的各点和弧的概率相乘(log运算则为相加)得到。
路径从左向右,逐列发展。
在时间点t,每个路径的
对所有的状态i都是已知的,那么就可以使用上面的公式来向右扩展一个时间帧,路径增长一步。
“路径”的概念非常重要,下面会将它通用化,用于连续语音识别。
没有HTK工具直接实现了上面的Viterbi算法。
但有一个HVite工具,以及它的支撑库HRec和HNet,用于连续语音识别。
问题:
即使对于待识别数据O,对于给定的模型M,可以计算出
,也没有办法确定O对应的到底是否M,无法进行识别?
答:
对于每个模型Mi,都可以计算出在该模型下,观察到数据O的最大可能性P(O|Mi),也就是每个模型,都能找到一条最大可能对应O的状态序列路径,进而得到观察到O的最大可能性。
那么对所有模型进行取最大值,就能得到O所对应的模型了。
即
M=argmax{P(O|Mi)}
问题:
对于连续语音识别,假设有50个模型,那么对于观察到的数据O,求其对应的模型序列。
如果按照上面的算法,就要首先把50个模型所组成的模型序列都排列出来,共有50的50次方个,比宇宙中所有物质的原子数目还要多!
!
根本无法为每个模型序列计算上面的最大似然概率,进而无法在这50的50次方个模型序列中寻找具有最大似然概率的那个序列。
那么怎样将上述的Viterbi算法引用到多个模型连续识别中呢?
答:
看下面。
如果知道观察数据O的每个音素的边界,即可以将O分成一段段的,每一段对应50个模型中的一个,那么上述问题很好解决,对每一段进行单独识别即可,每一段是孤立词识别,为该段数据计算50个模型的最大似然概率,取最大者即可。
1.6连续词语音识别
现在回到图1.1所示意的语音识别模型,可以清楚地知道,连续语音识别仅仅需要将多个HMM连接起来,而这个连接而成的HMM模型序列中的每个模型,都对应了其隐藏的符号,这个符号可能是一个单词,那么这称为“连接词语音识别”,这个符号也可能是一个音素,那么这称为“连续语音识别”。
另外,在每个模型中包括首尾两个不可观察的状态的原因,现在应该也清楚了,这是多个HMM模型连接在一起的粘合剂。
然而,依然有一些难点。
由孤立词过渡到连续词,对于模型训练算法Baum-Welch算法来说,所作的修改很小,只需要把所有模型连接成一个大模型,然后使用HERest的所谓“嵌入式”训练即可,原理和过程和HRest中类似。
然而,对于Viterbi识别算法来说,需要进行重大的扩展,这也是HVite中所做的。
在HTK中,使用了Viterbi算法的一个变种,叫做“令牌传送模型”,TokenPassingModel。
简单地说,令牌传送模型采用了状态路径对齐的概念。
想象一下,一个HMM中的每个状态j在时间t处,都拥有一个可移动的令牌,这个令牌中的信息,包含最大似然概率ψj(t),那么这个令牌就可以表示从o1到ot这个部分观察向量序列,和模型的匹配程度,限制条件是在时刻t必须处于状态j。
这样,上面的路径增长算法就可以使用新的“令牌传送”算法替代,这个算法也是在每个时间点t处执行,其中的关键步骤是:
1.将状态i处的令牌,传送到和状态i相连的每个状态j,然后递增上面的最大似然概率,使用对数运算时,递增的数值是log[aij]+log[bj(o(t)]。
2.在每个状态处,都检查令牌的值,只保留具有最大似然概率的那个令牌,丢弃其它的。
使用令牌传送模型的好处是,它可以非常容易地扩展到连续语音识别的情况中。
假设允许出现的HMM序列由一个有限状态网络定义,这个网络由识别任务的语法生成。
即HMM的序列是一个有限的集合。
例如,下图1.7中是一个简单的网络,其中每个单词都是一个音素的序列,每个音素有自己的HMM,并且所有单词处于一个环路中。
图1.7连续语音识别的网络
在这个网路中,椭圆形表示HMM的实例,而长方形表示“单词末尾(word-end)节点”。
这个组合网络实际上是一个大的HMM,因此可以利用上面的令牌传送算法。
唯一的区别是,除了最佳令牌的最大似然概率之外,还需要更多的信息。
当最佳的令牌到达语音的终点时,它所经过的网络中的路径信息需要保留下来,以得到所识别出来的模型序列。
问题:
这个网络实际上是许多单词序列,如果每个单词序列对应一个连接起来的大HMM,那么就应该有许多这种连接而成的HMM。
如果利用令牌传送算法的话,也只能计算出每个大HMM最终的最大似然概率。
如果要将着许多个单词序列看成一个大的HMM,那么就有一个问题,单词和单词之间的转移概率是如何设定的?
并且如果一个单词如果可能转移到多个单词上,整个HMM就不在是原来那种前后式的HMM了,可能出现分叉,成为一个更复杂的有向有环图。
问题是,在第一个单词的最大似然概率计算完成后,如何确定下一个单词?
使用什么,作为转移到下面哪一个单词的首个状态的判定依据?
答:
假设在第一个单词最后一个状态i处,最大似然概率为ψi(t),假设有n个单词可能是下一个单词,也就是说,在下一个时间点t+1处,从状态i处,有可能转移到n个状态(n个单词的首状态)。
到底转移到n个状态中的哪一个,依然根据log[aij]+log[bj(o(t+1))]这个值来判断,即转移到下个单词的概率,以及该单词的首状态观察到o(t+1)的联合概率。
假设转移到每个单词的概率是均等的,那么,就根据bj(o(t+1))的值来决定了。
令牌通过网络的历史路径,可以使用如下方法进行记录。
每个令牌携带一个指针,叫做“尾部单词链接”(wordendlink)。
当令牌从一个单词的退出状态(通过“单词末尾节点”时,即表明已经从退出状态转移了)转移到另外一个单词的入口状态时,这种转移表明刚刚经过一个单词边界。
这时生成一个名为“单词链接记录(wordlinkrecord)”的记录,其中保存了刚刚经过(emerge?
)的单词,以及当前令牌中“尾部单词链接”的值。
然后,将令牌的“尾部单词链接”指向这个新生成的WLR(单词链接记录)。
图1.18演示了这个过程。
图1.18记录单词边界的转移决策
说明:
图中的Before和After表示令牌在从单词one中转移出来之前,和之后的状态,令牌包含两部分信息,一是令牌当前的最大似然概率,以及一个指针,即“尾部单词链接”,指向当前最后一个识别出来的单词。
在Before时间点,这个指针指向下方左边第一个节点,即单词two。
令牌刚刚从单词“one”中转移出来,经过了图中的单词末尾节点
,这时就生成一个WLR,即下方最右边的一个节点,其中有四个字段,令牌的当前最大似然概率,时间点t,刚经过的单词“one”,以及一个指针。
这个指针指向令牌中的尾部单词链接,即最左边的单词two的WLR,然后修改令牌的指针,指向单词one,说明one是最后一个识别出来的单词。
问题:
不知道中间两个WLR,分别标以时间点t-2和t-1是什么含义?
一旦处理完了所有的语音数据,那么最佳令牌所指向的WLR链表,就是识别的单词序列结果。
可以从尾部的节点进行回朔,得到单词的最佳匹配序列。
同时,如果需要的话,可以将语音数据中的单词边界提取出来。
上面描述的令牌传送算法,记录了传送过程中的单词序列。
如果需要,可以记录更详细的音素序列,甚至状态序列。
另外,除了可以在每个单词边界处,记录最佳令牌的信息,还可以记录更多的路径信息,例如次优令牌,次次优令牌等。
这样,不仅可以生成一个最佳的识别单词序列,还能生成一个可能的单词网络。
基于这种思想的算法称为latticeN-Best。
它们是次优的,因为每个状态使用一个令牌,限制了可以保存的不同令牌的历史路径的数目。
可以通过让每个状态持有多个令牌,并且认为来自不同的前一个单词的令牌是不同的,来克服这个数目限制。
这是另一类算法,称为wordN-Best。
这种算法已经通过实验验证,其性能可以和其它任何最优N-Best算法相比。
上面大致描述了令牌传送算法的轮廓,它是HTK中实现的识别算法。
该算法在模块HRec和HNet中实现,通过工具HVite调用识别功能。
其中提供了单令牌和多令牌传送识别的算法、单个最佳令牌输出、网格(lattice)输出、N-Best列表等算法,并且支持跨单词的上下文依赖性,网格评分,以及强制对齐等特性。
第五章语音输入输出
许多工具需要参数化的语音数据作为输入,HTK为此提供了许多不同的方法:
*使用已经参数化的语音文件作为输入
*使用波形文件作为输入,在输入过程中进行参数化编码
*使用实时的音频流作为输入,在输入过程中进行参数化编码
使用波形文件的输入方式,支持很多不同的文件格式,包括所有通用的CD-ROM格式。
而使用参数化文件作为输入,只支持标准HTK文件格式和新的EntropicEsignal格式。
所有的HTK音频输入,都通过参数配置来控制对这些音频文件或者音频流进行什么处理操作。
本章描述HTK的音频输入和输入,解释通用的机制,并定义不同的配置参数。
用于信号预处理、基于线性预测的处理、基于FFT的处理、以及向量量化的方法,都一一做了介绍,并给出了所支持的文件格式。
还介绍了使用能量度量、一阶、二阶系数来增加基本语音参数的方法,以及将每个参数向量分割成多个数据流,来构成observation的方法,本章的结束描述了工具HList和HCopy的使用,它们可用于对语音文件进行观察、操作和编码。
5.1通用机制
HTK的语音输入输出功能由五个不同的模块提供,它们是HAudio,HWave,HParm,HVQ和HSigP,它们之间的相互关系如图5.1所示。
波形通过HWave从文件中读取,或者通过HAudio从音频设备直接输入,少数情况下只需要波形数据,比如波形显示工具HSLab,但大多数情况下都需要参数化的数据,参数化编码由HParm使用HSigP中定义的信号处理操作进行。
HParm的输出是observation形式的参数向量,而observation是HTK训练和识别工具数据处理的基本单元。
一个observation包含了一个原始参数向量的所有component,但它可能分为许多独立的部分,每个部分都被HTK工具认为是一个静态的独立的数据流。
Observation中还可以包含每个数据流中的VQindices,或者VQindices可以从参数化文件中直接读取,这种情况下,observation中仅包含VQindices。
图5.1语音输入子系统
通常HTK工具需要在命令行指定许多音频数据文件,大多数情况下,这些文件都需要是参数化的。
下面的例子中,调用嵌入式训练工具HERest,使用音频数据文件s1,s2,s3...对一组模型进行重估,这些输入文件必须是使用HParm进行了参数化的,符合HERest对输入数据的要求。
HERest...s1s2s3s4...
然而如果音频数据文件不满足所需要的格式要求,可以在输入的过程中进行处理,将它自动转换为所需的格式,为此,需要指定一些配置参数,这些参数明确定义了如何进行转换。
其中的关键,是有一个源数据类型和目标数据类型,源数据类型就是外部音频文件的数据格式,而目标数据类型则是HTK工具内部所要求的数据格式。
语音输入子系统的主要功能,就是将数据从源数据类型转换到目标数据类型。
数据类型包括一个基本类型,以及在基本类型的基础上,附加的一些可变属性。
这些可变属性通过说明符指定,说明符一般是一个字母,前面是下划线。
数据类型的一些例子如下:
WAVEFORM简单波形数据
LPC线性预测系数
LPC_D_E带有能量和一阶系数的线性预测
MFCC_C压缩的梅尔倒谱系数
所需的源数据类型和目标数据类型通过配置参数SOURCEKIND和TARGETKIND指定,因此,如果定义了如下的参数
SOURCEKIND=WAVEFORM
TARGETKIND=MFCC_E
那么语音输入子系统将期待波形数据输入,并将它转换为带有能量的梅尔倒谱系数格式。
而源数据类型并不一定是波形数据,比如配置
SOURCEKIND=LPC
TARGETKIND=LPREFC
将线性预测系数的输入转换为反射系数的输出。
为方便起见还定义了一种特殊的数据类型ANON,如果源类型为ANON,表示源数据格式由外部输入文件决定,如果目标类型为ANON,表示输出数据和源数据格式相同。
比如下面的配置
SOURCEKIND=ANON
TARGETKIND=ANON_D
不论源数据是什么格式,它将会仅仅添加一阶系数到源数据中。
源数据类型和目标数据类型的缺省值都是ANON,意味着不对输入数据进行格式转换。
需要注意的是,如果在命令行下指定了多个输入文件,ANON的含义不会依次对所有文件进行解释,因此,作为一个通用规则,任何工具的输入是多个音频数据文件时,这些数据文件必须具有相同的数据格式。
HTK输入子系统所作的数据转换可能是很复杂的,并非总能如你所愿,因此HTK提供了两个工具用于检查和调试数据转换参数的配置是否有效,首先,HList仅仅将音频数据文件的信息列在终端上,然而由于HList和其他HTK音频输入子系统的工具一样可以使用配置参数,如果对它指定了TARGETKIND,它显示的将是指定的目标格式,而不是源数据格式。
这是检查音频数据格式的最简单的方法。
在5.15节有对HList的详细介绍。
第二种方法,是为HParm模块指定TRACE配置参数,这样它可以生成跟踪输出,这种输入是一种位串,每个位表示了转换处理的不同部分,在参考一章中有详细介绍。
总而言之,HTK中的语音输入由配置参数控制,关键参数SOURCEKIND和TARGETKIND指定了源数据和目标数据的格式,它们决定了数据转换的最终结果,然而,要正确地设置数据转换中的每一步骤,需要定义更多的配置参数,这将在下面的内容中介绍。
5.2语音信号处理
5.10参数文件的存储
虽然HTK可以处理各种格式的波形文件,但参数化的音频数据只能以两种格式保存,一种是HTK自定义的格式,另一种是EntropicEsignal文件格式。
EntropicESPS格式不再直接支持,但可以在ESPS和ESignal格式之间转换时进行格式滤波。
5.10.1HTK参数文件格式
HTK格式的文件由连续的采样序列和文件头构成,每个采样是一个2字节的整型或者4字节的浮点向量,2字节整型一般用于数据压缩和向量量化。
HTK格式还可以用于保存波形文件。
HTK文件头共12字节长,包括下列数据:
nSamples,文件中采样数量(4字节整数)
sampPeriod,以100ns为单位的采样间隔(4字节整数)
sampSize,每个采样的字节数(2字节整数)
parmKind,采样类型的编码(2字节整数)
参数类型包括一个表示基本数据类型的6位编码,以及表示额外属性的附加位。
基本参数类型编码如下:
0WAVEFORM采样波形
1LPC线性预测滤波系数
2LPREFC线性预测反射系数
3LPCEPSTRALPC倒谱系数
4LPCDELCEPLPC带一阶系数的倒谱系数
5IREFCLPC反射系数(16位整型格式)
6MFCC梅尔频率倒谱系数
7FBANKlog梅尔滤波bankchannel输出
8MELSPEC线性梅尔滤波bankchannel输出
9USER用户定义采样类型
10DISCRETE向量量化数据
11PLPPLP倒谱系数
附加位(八进制)的含义如下:
_E
000100
带有能量
_N
000200
绝对能量suppressed
_D
000400
带一阶系数
_A
001000
带二阶系数
_C
002000
压缩格式
_Z
004000
带零均值静态系数
_K
010000
带CRC校验和
_O
020000
带第0个倒谱系数
_V
040000
带VQ数据
_T
100000
带三阶系数所
其中,_A只有当_D被使用时才能使用,_N只有当能量和一阶系数都存在时才有效。
采样类型LPDELCEP和LPCEPSTRA_D是相同的,它为了保持和HTK的历史版本兼容而存在。
_C和_K仅仅在外部文件中存在,压缩文件在载入时先进行解压缩,带校验和的文件首先进行CRC校验,然后其校验数据被去掉。
外部文件可以包含能量域和第0个倒谱系数,它们可以在文件载入时保留,但一般会抛弃其中之一。
[8]
注[8]:
有时需要0阶倒谱系数,以从倒谱系数恢复filterbank系数。
所有HTK参数化文件都有一系列向量构成,如图5.5中所示,每个向量是有序的组织,根据不同的附加属性定义,有不同的形式。
可以看出,能量值紧跟在基本系数之后,如果还有一阶系数,它会跟在能量值的后面。
上面的例子是使用的LPC格式,但是对于其它基本数据格式,也具有相同的布局。
如果除能量之外还有0阶倒谱系数,那么它会插入在能量值之前,或者替代能量值。
语音参数文件的外部存储,有两种压缩方法。
如对于LP编码,IREFC参数类型就利用了反射系数在-1到+1之间变化的事实,对其进行放大,使用整型范围-32767到32767来表示反射系数。
对于其它参数化数据类型,HTK使用_C来指定了一种通用的压缩方法,将参数向量压缩为short类型保存。
例如对于参数x:
其中系数A和B的定义为:
其中,Xmax和Xmin分别是整个文件中参数X的最大值和最小值,I是2字节整型的最大值32767,A和B的值作为浮点向量保存在文件中,紧跟在文件头之后,其它数据之前。
当HTK工具将数据输出到外部文件时,没有更多的信号处理操作。
因此,大多数情形,目标参数类型TARGETKIND同时指定了内部所需的数据格式,以及文件保存的格式。
然而在外部文件的存储方式是有区别的,首先,可以通过设置参数SAVECOMPRESSED为TRUE来指定对数据进行压缩存储,压缩方式如上所述,如果目标类型是LPREFC,那么通过将数据转换为IREFC格式进行压缩,如果目标类型是其他格式,将使用上述的通用压缩方法。
其次,为了避免数据损坏问题,外部存储的HTK参数文件可以有CRC数据,这通过指定_K附加属性标志,以及配置参数SAVEWITHCRC为TRUE,就会生成额外的CRC校验数据。
使用这些输出转换的主要工具是HCopy(见5.16节)。
5.10.2Esignal参数文件格式
5.11波形文件格式
为读取波形数据文件,HTK对一系列不同的格式提供了支持,这些将在本节进行简要介绍。
默认的音频格式是HTK,如果使用不同的格式,可通过指定参数SOURCEFORMAT来完成。
然而,由于文件格式经常需要进行转换,所以也可以通过命令行选项-F来指定格式,它会覆盖配置参数SOURCEFORMAT的值。
和波形输出类似,输出格式可以使用TARGETFORMAT配置参数,或者命令行选项-O指定,然而HTK仅支持三种输出格式,HTK自带格式(HTK),Esignal格式(ESIG),以及无文件头格式(NOHEAD)。
下面对HTK支持的波形文件格式逐次作一介绍。
5.11.1HTK文件格式
HTK的波形文件格式和参数文件格式一样,有12字节的文件头,如5.10节所述。
在文件头后面是2字节的整型音频采样数据,对于波形数据,sampSize为2,parmKind为0,sampPeriod以100纳秒为单位,例如,对于10KHz的采样数据,采样间隔是1000,对于16KHz的采样频率,采样间隔是625。
5.11.10WAV文件格式
WAV文件格式,是微软定义的多媒体文件格式系列RIFF中的一种,一个RIFF文件具有一个文件头,后面跟一系列的数据chunk,而WAV文件一般只有一个数据chunk,其中包含两个子块:
一个fmt块指定数据格式,一个data块包含了实际的采样数据。
WAV文件的头部如下:
’RIFF’–RIFF文件标志字符串(4bytes)
–长度(4bytes)
’WAVE’–WAVEchunk标志字符串(4bytes)
’fmt’–formatsub-chunk标志字符串(4bytes)
flength–formatsub-chunk长度(4byteinteger)
format–format标志符(2byteinteger)
chans–声道数目(2byteinteger)
sampsRate–采样频率Hz(4byteinteger)
bpsec–每秒字节数(4byteinteger)
bpsample–每采样字节数(2byteinteger)
bpchan–每声道位数(2byteinteger)
’data’–datasub-chunk标志字符串(4bytes)
dlength–datasub-chunk长度(4byteinteger)
对8位CCITTmu-law、8位CCITTa-law、8位