語音識別中的HMM-GMM模型:從一段語音說起
語音識別中的HMM-GMM模型:從一段語音說起
楊陽陽 想太多雖然現在端到端語音識別模型可以直接對後驗概率建模,可以不需要HMM結構了。但實際上目前很多state-of-the-art模型還是以HMM結構為主,比如chain model。而且掌握HMM-GMM結構,對於深入理解語音識別過程是由有一定好處的。
但對於外行或者剛接觸語音識別的人來說,要弄懂HMM-GMM結構還是要花不少時間的,特別是被一大推公式整懵了。語音識別任務有些特殊,比如語音識別中,標註只是針對整段音訊的,而不是針對每一幀;語音識別是針對每個音素都建立一個HMM模型,而不是所有音素用一個HMM模型描述。
當時為了弄懂HMM-GMM,看了不少資料,但感覺都不適合很初級的學習者。於是就萌生了寫一個通俗易懂版的HMM-GMM教程,從一個音訊例項說起,給大家一個感性的認識,也著重講下作為初學者可能會感同身受的問題,不涉及到具體公式。公式的推斷會給出參考資料,後續大家在研究,相信有了感性的認識之後,對這些公式的理解就不成問題了。
我們從下面這段音訊說起:
我們把上面2秒的音訊分幀,以幀長100ms,幀移100ms為例進行切分,這樣上面的音訊就被我們分成20幀。(ps:這裡主要是為了方便說明,正常情況下幀長是25ms,幀移是10ms)
一、得到這段音訊的標註
這裡的標註可以是兩種:
1、音素級別的標註。這是訓練HMM-GMM模型所需要的標註,也就是說可以直接拿來訓練的資料。
2、位元組別的標註。實際上我們更多時候拿到是的字級別的標註,因為音素級別的標註工作量很大。但我們可以通過發音詞典,將字級別的標註轉換成音素級別的標註。這種轉換沒辦法消除多音字的影響,但實際上不會對結果產生太大影響(這一部分可以參考kaldi的compile-train-graphs過程:
Decoding-graph creation recipe (training time)假設上面這段音訊的標註是”你好“,那麼對應的發音就是”n i2 h ao3“這四個聲韻母。這裡為了方便說明,我們就是用聲韻母作為建模單元(ps:實際應用中是使用音素作為建模單元)。
二、對”n“、”i2“、”h“、”ao3“這4個聲韻母分別使用HMM-GMM建模,使用3狀態建模,如下圖
為了方面說明,我們給每個狀態加了編號。從上圖我們可以看到,對於HMM的發射概率,我們是使用高斯分佈函式建模的。為了方便說明,這裡我們使用單高斯分佈函式(雖然上圖寫的是GMM)。
理解自環很重要,比如④這個狀態,因為有了自環,它可以出現多次,因此我們可以對任意長的音訊建模,這也是連續語音識別的基礎。
三、對”n“、”i2“、”h“、”ao3“對應的HMM-GMM模型進行訓練,得到模型引數
這一步屬於HMM三個問題中的學習問題,需要用到EM演算法。在開始訓練之前,我們需要明確每個HMM模型的引數、模型的輸入和模型的輸出。
- HMM-GMM模型的引數
1、轉移概率
2、發射概率:因為我們使用GMM對發射概率建模,所以實際引數就是高斯分佈中的均值和方差(這也是初學者容易迷糊的一個地方)。
總結:模型引數就是轉移概率、高斯分佈的均值、方差。
- 模型的輸入
輸入:每幀訊號的MFCC特徵(也可以是fbank,plp等)。具體應用中,我們通常取39維的MFCC特徵。這裡為了方便說明,我們取2維的MFCC特徵,也就是說輸入的特徵空間分佈是這樣的:
上圖中,每個黑點對應某一幀訊號的MFCC特徵。我們需要使用這些特徵值來更新GMM的引數,具體怎麼更新後續會講。
- 模型的輸出
輸出:每一幀屬於"n"、"i2"、"h"、"ao3"中的某一個狀態(3狀態)的概率。
同時,需要額外說明的是:雖然我們有了每段音訊對應的標註,但實際上HMM-GMM模型的學習過程並不是”有監督的“。因為監督學習任務應該是:"對於每一個輸入,都有對應的label"。而語音識別的任務比”傳統的監督學習“複雜一點。因為我們拿到的標註是音素級別的。比如上面那段音訊,它只告訴我們對應的標註是"n"、"i2"、"h"、"ao3",並沒有告訴我們每一幀(即每一個輸入)對應的label是啥?那麼應該怎麼訓練呢,相信是很多初學者的困惑。
對於這種無監督的任務,我們EM演算法來進行訓練(更專業的術語叫嵌入式訓練,embedding training。也就是說把“n”、“i2”、“h”、“ao3”對應的HMM模型嵌入到整段音訊中進去訓練,因為我們不知道音訊的哪一段是對應“n”、“i2”、“h”、“ao3”。嵌入式訓練本質還是EM演算法的思想):
- step1:初始化對齊。以上面的20秒音訊為例,因為我們不知道每一幀對應哪個聲韻母的某個狀態,所以就均分。也就是說1-5幀對應"n",6-10幀對應"i2",11-15幀對應"h",16-20幀對應"ao3"。同時"n"又有三個狀態,那麼就把1-2幀分給狀態①,3-4幀分給狀態②,第5幀分給狀態③。"i2"、"h"、"ao3"亦如此。這裡每個狀態只是用單高斯描述,如果是混合高斯,還需要進一步用k-means演算法來對每個高斯分量初始化。
初始化完成後,該段音訊對應的HMM模型如下:
- step2:更新模型引數。
1、轉移概率:通過上圖,我們可以得到①->①的轉移次數,①->②的轉移次數等等。然後除以總的轉移次數,就可以得到每種轉移的概率,這是一個統計的過程,無他。
2、發射概率:即均值和方差。以狀態①的均值和方差為例,由上圖我們可以知道第1幀和第2幀對應狀態①。假設第1幀的MFCC特徵是(4,3),第2幀的MFCC特徵的MFCC特徵是(4,7)。那麼狀態①的均值就是(4,5),方差是(0,8)
- step3:重新對齊。根據step2得到的引數,重新對音訊進行狀態級別的對齊。這一步區別於step1的初始化,step1的初始化我們是採用粗暴的均勻對齊,而這一步的對齊是根據step2的引數進行對齊的。這裡的對齊方法有兩種:a、硬對齊:採用維特比演算法;b、軟對齊:採用前後向演算法。
經過重新對齊後,可能變成這樣(第2幀已經不對應狀態①了):
- step4:重複step2和step3多次,直到收斂。
這一個過程就是EM演算法。step1和step3對應E步,step2對應M步。
這一過程涉及到的公式可以參考愛丁堡的語音識別課件:http://59.80.44.98/www.inf.ed.ac.uk/teaching/courses/asr/2018-19/asr03-hmmgmm-handout.pdf
到這裡,我們就從巨集觀層面把語音識別的HMM-GMM建模過程講完了。為了方便講解,我們這裡是用單音素為例。實際應用中,通常使用三音素,但過程幾乎是一樣的,只是三音素多了一步決策樹聚類,具體可以參考我之前的博文:[kaldi中基於決策樹的狀態繫結](https://blog.csdn.net/asrgreek/article/details/88139638)