點擊上方“AI大道理”,選擇“置頂”公眾號
為了讓識別出來的語音符合常規語言表達,引入了語言模型作為約束。
為了加速解碼識別效率又引入了WFST解碼機制。
解碼本質:解碼就是在網絡中尋找最優路徑。
(注:on-the-fly Rescoring 歸為動態解碼有待商榷)
1 基於Viterbi的原始動態解碼
無HCLG、一次解碼
基於Viterbi的動態解碼是最基礎的解碼。
線性詞典:動態解碼網絡僅僅把詞典編譯為狀態網絡,構成搜索空間。編譯的一般流程為:首先把詞典中的所有單詞並聯構成並聯網絡;然后把單詞替換為音素串;接着把每個音素根據上下文拆分為狀態序列;最后把狀態網絡的首尾根據音素上下文一致的原則進行連接,構成回環。
編譯出來的網絡一般稱為線性詞典(Linear Lexicon)。
每個單詞的狀態序列保持嚴格獨立,不同單詞的狀態之間沒有節點共享,因此內存占用比較大,解碼過程中的重復計算比較多。
將上圖狀態拉成直線,做為Y軸,X軸為時間T。
隨着時間的推移,幀的移動,逐漸對齊到詞的最后一個音素的最后一個狀態,比如第7幀對齊到“北京”、“北極”、“南京”等詞典中每個詞的HMM的最后狀態,對比累計概率,挑選出“北京”。繼續進行下去,結合語言模型,加入語言模型概率,得到最優路徑“北京是首都”,即解碼結束。
可見,從狀態序列到詞序列的整個轉化過程十分復雜,且詞匯量很大的話,計算量很大,解碼效率不高。
樹型詞典:一般把單詞首尾發音相同的部分進行合並,稱為樹型詞典(Tree Lexicon)。由於大量相同狀態的節點被合並在一起,因此可以顯著降低搜索空間的規模,減少解碼過程的運算量。
(該方法基本不用)
2 基於WFST的Viterbi靜態解碼
HCLG、一次解碼
為了加快解碼速度,可以把動態知識源提取編譯好,形成靜態網絡,在解碼時直接調用。
從輸入HMM狀態序列,直接得到詞序列及其相關得分。
用H、C、L、G分別表示上述HMM模型、三音子模型、字典和語言模型的WFST形式。
一般網絡構建的流程為:
或者
聲學得分依然還要根據輸入特征單獨計算,其他知識源詞典、語言模型、上下文依賴不需要再考慮,已經融入整個靜態網絡中,通過網絡的轉移弧輸入、輸出、權重來整體代替。
由於靜態網絡已經把搜索空間全部展開,它只需要根據節點間的轉移權重計算聲學概率和累計概率即可,因此解碼速度非常快。
基於WFST的Viterbi靜態解碼過程:
解碼過程使用了令牌傳播機制Token passing,其實就是viterbi解碼的通用版本。
1)解碼第一幀時,從狀態節點0出發,首先進行ProcessEmitting處理的發射狀態轉移弧,節點0轉移到節點3、2、6。接着ProcessNonemitting沿着虛線非發射轉移弧將6傳播到同一時刻下的狀態節點1。
2)解碼第二幀時首先切換Token列表,把cur_toks列表轉變到pre_toks列表后,將cur_toks置空。然后再進行ProcessEmitting、ProcessNonemitting。
3)隨着時間的推移,幀的進行,到達最后一幀,選擇最低累計代價的Token,然后以次Token回溯最優路徑。
其中:
Emitting Arc 表示發射轉移弧,類似HMM的發射狀態,觀察值產生聲學得分
aoustic_cost;
Nonemitting Arc表示非發射轉移弧,類似HMM的非發射狀態,不產生觀察值,沒有聲學得分;
每條轉移弧對應的權重為圖代價graph_cost(語言模型得分、轉移概率、發音詞典)。
Swap(prev_toks,cur_toks) :
直到最后一幀,選擇最低累計代價的Token,根據該Token回溯最優路徑。
3 基於WFST的Lattice靜態解碼
HCLG、一次解碼
Viterbi解碼識別只保留一條最優路徑,若要保存多種候選識別結果,就需要Lattice。
(靈魂的拷問:為什么要保存多種候選結果呢?viterbi識別出一條最優路徑不夠嗎?
AI大語音:不能保證viterbi給的最優路徑就是真正的對的路徑,錯誤的路徑一樣可能成為viterbi算法跑出來的最優路徑)
Lattice解碼需要保存多條搜索路徑,Token間需要有鏈表信息。
前向鏈接ForwardList與轉移弧不同,用來鏈接前后兩幀之間的發射轉移弧之間的Token,或同一時刻非發射轉移弧之間的Token。
令牌列表TokenList每幀一個,可以和幀索引建立關聯。
基於WFST的Lattice靜態解碼過程:
問題與解決:
在HCLG中,G的大小對最終的HCLG的大小起主要作用。
靜態圖HCLG問題:
1)靜態圖HCLG自身占用空間大,難以使用大的語言模型,其在解碼運行過程中占用內存也大,難以在移動端直接使用HCLG。
2) 靜態圖HCLG構建過程速度慢,消耗內存高。
為了解決該問題,有兩種方法:
1)on-the-fly Composition;
2)Rescoring(常規Rescoring、on-the-fly Rescoring)。
4 on-the-fly Composition
HCL/G、一次解碼、動態解碼
on-the-fly Composition動態解碼思路是把HCLG分開成HCL和G,稱之為HCL/G。構圖時分別構建HCL和G,分別構建的HCL和G。因為不是完全展開的圖,這兩個圖的大小遠比其展開的靜態圖HCLG小,這樣就節省了空間。
另一方面無需再進行HCL和G的Compose這一過程,而這一步恰恰是靜態圖HCLG構建過程中最為耗時的一步,所以又節省了構圖時間。
在解碼時,分別加載HCL和G,然后根據解碼動態的對HCL和G進行按需動態Compose,而無需完全Compose展開。
動態圖有什么問題呢?
動態圖HCL/G要在解碼時動態的做Compose,也就加大了解碼時的計算量,所以解碼速度會相對降低。
5 Rescoring
HCLG1和G2、二次解碼
Rescoring,其思路是在構建時使用小的LM1構建G1,使用G1構建靜態圖HCLG1,然后使用小的LM1和大的LM2構建G2(G2中LM的weight為LM2的weight減去LM1的weight)。解碼時根據HCLG1和G2的使用方式,又可以做進一步細分:
1)常規Rescoring:利用HCLG1先全部解碼,生成lattice或者nbest,然后在G2上做lattice和nbest的Rescoring。
2)on-the-fly Rescoring:使用HCLG1做解碼,在解碼過程中,每當解碼出word時,立即再加上G2中的LM weight,所以稱之為on-the-fly Rescoring。Kaldi中的BigLM Decoder即為on-the-fly Rescoring。
6 總結
基於Voiterbi的原始動態解碼詞典一旦很大,計算量就會很大,解碼速度很慢。
為了加速解碼速度,一方面可以進行剪枝處理,在解碼中選出最優路徑,超過剪枝閾值的路徑則直接刪除,不再后續運算。
另一方面可以把知識源預先編譯成一個靜態網絡,在解碼中直接使用。其中一般基於WFST的Viterbi靜態解碼得到的一條最優路徑可能並不是實際上真正的最優路徑,為了得到更多的候選結果使用基於WFST的Lattice靜態解碼。
靜態解碼HCLG占用空間大,難以使用大的語言模型,HCLG在構建過程中速度慢,消耗內存高。
為了解決靜態一次解碼的問題,可以進行on-the-fly composition動態解碼和rescoring解碼。
下期預告
AI大語音(十二)——WFST解碼器(下)(深度解析)
往期精選
AI大語音(十)——N-gram語言模型
AI大語音(九)——基於GMM-HMM的連續語音識別系統
AI大語音(八)——GMM-HMM聲學模型
AI大語音(七)——基於GMM的0-9語音識別系統
AI大語音(六)——混合高斯模型(GMM)
AI大語音(五)——隱馬爾科夫模型(HMM)
AI大語音(四)——MFCC特征提取
AI大語音(三)——傅里葉變換家族
AI大語音(二)——語音預處理
AI大語音(一)——語音識別基礎
——————
淺談則止,細致入微AI大道理
掃描下方“AI大道理”,選擇“關注”公眾號
—————————————————————
—————————————————————