天天看点

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

近期上了付费的语音识别相关课程,算是第一次系统学习语音识别相关知识,关于GMM-HMM模型还是没有理解得很透彻,写出来捋一捋思路。

一.单音素GMM-HMM模型

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图一

一段2秒的音频信号,经过【分帧-预加重-加窗-fft-mel滤波器组-DCT】,得到Fbank/MFCC特征作为输入信号,此处若以帧长为25ms,帧移为25ms为例,可以得到80帧的输入信号,这80帧特征序列就是观察序列

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

1.如何得到这段音频的标注?

1.1

音素(Phone)

级别的标注

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图二

音素级别的标注是训练HMM-GMM模型所需要的标注,可以直接拿来训练GMM-HMM模型。

1.2 字/词级别的标注

实际上我们更多时候拿到是的字/词级别的标注,因为音素级别的标注工作量很大。但我们可以通过发音词典,将字级别的标注转换成音素级别的标注。下图是词到音素序列的映射,其中0~9 10个数字的词典如下:

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图三

如果本文中示例的2秒音频标注是单词“six”,对应的音素标注就是“S IH K S”这四个单音素。

2. 如何使用GMM-HMM对“S IH K S”这四个单音素建模?

2.1 对每个音素使用经典的3状态HMM拓扑结构

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图4

图4表示的是左右模型的HMM,状态只能跳到自身或者下一个状态,所以每个state只有两条outgoing arc。如图所示,“S IH K S”这四个单音素有12个状态,我们给每个状态标了编号,对于观察概率(发射概率),使用高斯分布建模。为了方便说明,我们在本例中使用

单高斯分布

2.2 给定观察序列*O*,估计GMM-HMM模型的参数,属于

学习问题

(1)形式化该问题:

  • 输入:
    python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)
    ,本文中即80帧MFCC/Fbank特征;
  • 目标: 估计GMM-HMM模型参数
    python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)
    , 使得
    python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)
    值最大。
  • 输出:通过模型计算每一帧属于“S IH K S”这四个单音素中某一个状态(3状态)的概率

A 是转移概率,B 是观察概率,也就是发射概率。我们使用GMM模型对观察概率建模,所以实际参数就是高斯分布中的

均值

方差

(如果我们使用DNN对观察概率建模,实际参数就是DNN网络参数,下一篇文章再讨论)。

模型参数就是转移概率、高斯分布的均值、方差(单高斯的情况)

(2)训练过程

在刚开始学习的时候,有个问题困扰了我好久:虽然说对于这段音频,我们有了音素级别的标注“S IH K S”,但是我们并不知道哪一帧输入特征对应哪个音素的哪一个状态。这并不像有监督学习中的一样,每一个输入数据(即每一帧)都有一个lable。连怎么对应的都不知道,那怎么估计每个状态的观察概率GMM呢??之前学习的通过EM算法估计GMM参数,该用哪些数据来更新参数呢?

答 :通过

嵌入式训练(embedding training)即EM算法

,把“S IH K S”对应的GMM模型嵌入到整段音频中去训练,算法包括4个步骤:

step1:初始化对齐

输入特征:$O=[o_1,o_2,...,o_T],T=80$,刚开始的时候不知道哪一帧对应哪个音素的哪一个状态,所以就均分。在这个例子中,第1-20帧对应音素“S”,第21-40帧对应音素“IH”,第41-60帧对应音素“K”,第61-80帧对应音素“S”。同时每个音素有3个状态,就又进行均分,把第1-6帧对应状态①,第7-12帧对应状态②,第13到20帧对应状态③,之后也是如此将输入数据特征帧与状态进行对应。如此就初始化了每个状态所对应的输入数据。本例子中使用的是单高斯,如果是使用混合高斯对观察概率进行建模,则需要使用K-means算法来对每个高斯分量进行初始化。

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图5

step2: 更新模型参数

使用EM算法更新模型参数,分为E步和M步,E步进行count操作,M步进行normalize操作。

a) 转移概率:

我们可以count从状态①->①的转移次数,状态①->②的转移次数,这是一个统计过程;在count步得到各个状态自跳转和相互转移的数目,除以总的转移次数,就可以得到每种转移的概率。

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图6

b) 观察概率:

计算每个状态对应的GMM的均值和方差。以图6中状态①为例,我们在初始化中使得第1-6帧对应状态①,我们使用这1-6帧的数据,计算均值和均方误差(本例中假设为单高斯),得到的

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

,以此类推,可以计算得到所有12个状态所对应的GMM的均值

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

和方差

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

.

step3: 重新对齐

根据step2 得到的参数,重新对音频进行 【观察序列-状态序列】的对齐。step1初始化是通过均分进行了一次暴力对齐,step3的重新对齐是在step2得到的参数的基础上,使用算法对齐的。对齐方式有两种:

采用viterbi算法的硬对齐

采用Baum-Welch学习算法(前向后向算法)的软对齐

(这两个算法的实现细节,下一节介绍)。重新对齐之后,可能变成了下图所示,第5、6帧从对应状态1变成了对应状态2了。

python gmm em算法 2维数据_基于GMM-HMM的语音识别系统(1)

图7

step4: 重复step2-step3多次

直至收敛。则该GMM-HMM模型训练完成。

(3)思考

在本例子中四个音素“S IH K S”的“S”出现了两次,是不是可以将该音素对应的帧都放在一起共享使用同一个参数的GMM?如果分开计算的话,可以发现计算得到的GMM参数并不相同。因为上下文音素发音的影响,这两个音素“S”的发音并不相同。所以单音素模型虽然可以完成基本的大词汇量连续语音识别的任务,但是存在以下缺点:

  • 建模单元数目少,如图二所示,一般英文系统的音素数量在30~60个,中文系统音素数目在100个左右。这么少的建模单元难以做到精细化的建模,所以识别率不高。
  • 音素发音受其所在上下文的影响,同样的音素,在不同的上下文环境中,数据特征也有明显的区分性。

所以就考虑音素所在的上下文(context)进行建模,一般的,考虑当前音素的前一个(左边)音素和后一个(右边)音素,称之为三音素,并表示为A-B+C的形式,其中B表示当前音素,A表示B的前一个音素,C表示B的后一个音素。

【下一篇讲

三音素GMM-HMM模型】