刚入门ASR的时候一直能听到HMM模型的相关字眼,这里就补一下用GMMs-HMMs进行语音识别的原理,虽然这个方法很古老,而且已经近乎被神经网络所取代,但它背后的思想仍然值得我们去了解和学习~
笔者看了一些教程,包括课程讲义、博客还有一些工具书,总算大致理清了思路,相信至少在文章逻辑上比一些没有相关背景设定、无厘头、不知所云的教程要好,原理上至少也是能用到的都有介绍。而有些地方太深入的原理笔者也没有去细究,感兴趣的读者根据笔者的逻辑自己去深入探索即可。
整体的行文思路按照“结果导向”,需要什么数学知识和原理再去介绍什么,而不是上来就用GMM和HMM进行轰炸,导致前后脱节。在数学原理上,也是尽量做到通俗易懂,加入自己的理解,而不是甩一堆高深莫测的公式。
文章目录
一. 最简单的场景:孤立词识别
1.1 整体思路
孤立词识别是语音识别中最简单的场景,即一个音频文件里面只包含一个词的语音。训练和识别的整体思路为:
(1)训练阶段:对于每个词,用不同人录制的这个词的音频特征作为训练样本,构建一个生成模型 P ( X ∣ W ) P(X|W) P(X∣W), W W W表示词, X X X表示音频文件提取出的特征(如FBank、MFCC等,参见这篇博客)。
(2)识别阶段:给定一段音频特征,经过上面学习到的每个词的 P ( X ∣ W ) P(X|W) P(X∣W)模型,看哪个词生成这段音频特征的概率最大,取最大的那个词作为识别词。
形象化的图如下:

这里的重点就是 P ( X ∣ W ) P(X|W) P(X∣W)这个生成模型的建立。因为对于每个孤立词都是分别采用一个生成模型来独立建模的,所以后面介绍的原理都是以一个孤立词为例讲解。
1.2 模型结构
对于这种时间序列的建模,自然就是采用HMM模型。其结构图如下:

不大张旗鼓地讲那么多关于HMM没用的东西,就看这个图来讲解。它的构建思路就是认为音频特征是由一些隐藏状态生成的,这些状态内部会有转移,并且满足马尔可夫性,状态个数是超参数,需要自己设置(一般3~5个)。
对于除了开始( s I s_I sI)和结束( s E s_E sE)这两个状态之外的状态,都有两种转移选择,要么就转向自己,要么就转向下一个状态。因为音频特征的序列长度往往要比状态个数多,所以这里要有转向自己的,因此每个状态可能对应多个音频特征的“帧”。
以这个图里面的3个状态和对齐为例,生成模型可展开为: P ( X ∣ W ) = P ( x 1 ∣ s 1 ) P ( s 1 ∣ s 1 ) P ( x 2 ∣ s 1 ) P ( s 1 ∣ s 1 ) P ( x 3 ∣ s 1 ) P ( s 2 ∣ s 1 ) P ( x 4 ∣ s 2 ) P ( s 2 ∣ s 2 ) P ( x 5 ∣ s 2 ) P ( s 3 ∣ s 2 ) P ( x 6 ∣ s 3 ) P(X|W)=P(x_1|s_1)P(s_1|s_1)P(x_2|s_1)P(s_1|s_1)P(x_3|s_1)P(s_2|s_1)P(x_4|s_2)P(s_2|s_2)P(x_5|s_2)P(s_3|s_2)P(x_6|s_3) P(X∣W)=P(x1∣s1)P(s1∣s1)P(x2∣s1)P(s1∣s1)P(x3∣s1)P(s2∣s1)P(x4∣s2)P(s2∣s2)P(x5∣s2)P(s3∣s2)P(x6∣s3)。
这里主要有两部分概率需要学习:
(1) a i j a_{ij} aij: P ( s j ∣ s i ) P(s_j|s_i) P(sj∣si),状态转移概率
(2) b j ( x t ) b_j(x_t) bj(xt): P ( x t ∣ s j ) P(x_t|s_j) P(xt∣sj),输出生成概率
其中 b j ( x t ) b_j(x_t) bj(xt)一般采用GMM进行建模,这也就是为什么叫GMM-HMM。直接给出GMM的公式:
b j ( x t ) = ∑ m = 1 M c j m N ( x t ; μ j m , Σ j m ) b_j(x_t) = \sum_{m=1}^M c_{jm} N(x_t; \mu_{jm}, \Sigma_{jm}) bj(xt)=m=1∑McjmN(xt;μjm,Σjm)
N ( x ; μ , Σ ) = 1 ( 2 π ) D / 2 ∣ Σ ∣ 1 / 2 e x p ( − 1 2 ( x − μ ) T Σ − 1 ( x − μ ) ) N(x_; \mu, \Sigma) = \frac{1}{(2\pi)^{D/2}|\Sigma|^{1/2}}exp(-\frac{1}{2}(x - \mu)^T \Sigma^{-1}(x - \mu)) N(x;μ,Σ)=(2π)D/2∣Σ∣1/21exp(−21(x−μ)TΣ−1(x−μ))
即认为输出生成概率由高斯混合模型生成,先根据概率 c j m c_{jm} cjm选择一个高斯模型,然后根据这个模型的概率分布 N ( x t ; μ j m , Σ j m ) N(x_t; \mu_{jm}, \Sigma_{jm}) N(xt;μjm,Σjm)生成 x t x_t xt。
总结一下,要学习的参数有:
- a i j a_{ij} aij:HMM的状态转移概率矩阵
- c j m c_{jm} cjm:各状态对应的GMM中的混合权重(如果是单高斯建模,则不用学习)
- μ j m \mu_{jm} μjm:各状态对应的GMM中各高斯分量的均值向量
- Σ j m \Sigma_{jm} Σjm:各状态对应的GMM中各高斯分量的协方差矩阵
建立好这样的模型之后,后面就是如何根据样本进行训练了。
1.3 训练过程
这里的训练,确切来讲应该叫参数估计,用一定的算法来估计参数,使其能够拟合数据分布(即最大化数据的似然概率)。下面循序渐进地来讲这种参数估计算法:
1.3.1 单样本、单高斯
这是一种最简单的情况,假设一个词的训练样本只有一个音频文件,并且对于输出概率 b j ( x t ) b_j(x_t) bj(xt)采用单高斯建模,即 m = 1 m=1 m=1, c j m = 1 c_{jm}=1 cjm=1。此时需要估计的参数为:
- a i j a_{ij} aij:HMM的状态转移概率矩阵
- μ j \mu_{j} μj:各状态对应的单高斯模型的均值向量
- Σ j \Sigma_{j} Σj:各状态对应的单高斯模型的协方差矩阵
这里进行参数估计的一大难点就是:各个状态对应哪些音频帧是不知道的,不像1.2里面给出的那个图那样具有对齐信息。所以输出概率 b j ( x t ) b_j(x_t) bj(xt)根本不知道具体去拟合哪些音频帧数据。
为了解决这个问题,引入一种软对齐策略,即给出各个音频帧属于各个状态的概率(各个时刻处于各个状态的概率) γ t ( j ) = P ( s t = j ∣ X ) \gamma_t(j) = P(s_t = j|X) γt(j)=P(st=j∣X),此时对于各个单高斯模型的参数估计就可以写为:
μ ^ j = ∑ t = 1 T γ t ( j ) x t ∑ t = 1 T γ t ( j ) \hat \mu_j = \frac{\sum_{t=1}^T \gamma_t(j) x_t}{\sum_{t=1}^T \gamma_t(j)} μ^j=∑t=1Tγt(j)∑t=1Tγt(j)xt
Σ ^ j = ∑ t = 1 T γ t ( j ) ( x t − μ ^ j ) ( x t − μ ^ j ) T ∑ t = 1 T γ t ( j ) \hat \Sigma_j = \frac{\sum_{t=1}^T \gamma_t(j) (x_t - \hat \mu_j) (x_t - \hat \mu_j) ^ T}{\sum_{t=1}^T \gamma_t(j)} Σ^j=∑t=1Tγt(j)∑t=1Tγt(j)(xt−μ^j)(xt−μ^j)T
这个地方不好理解的话,再说得深入一些:
如果最理想情况下给出了各个状态对应的音频帧,像1.2节的图那样。则每个状态对应的高斯模型需要拟合的数据就确定了,此时根据最大似然概率,均值和方差分别应该估计为:
μ ^ j = ∑ t = 1 T z j t x t ∑ t = 1 T z j t \hat \mu_j = \frac{\sum_{t=1}^T z_{jt} x_t}{\sum_{t=1}^T z_{jt}} μ^j=∑t=1Tzjt∑t=1Tzjtxt
Σ ^ j = ∑ t = 1 T z j t ( x t − μ