語音識別演算法原理文件整理(九)
資料檔案內容簡介
資料準備階段的輸出包含兩部分。一部分與―資料相關(儲存在諸如data/train/之類的目錄下),另一部分則與語言相關(儲存在諸如data/lang/之類的目錄下)。 資料部分與資料集的錄音相關,而―語言部分則與語言本身更相關的內容,例如發音字典、音素集合以及其他Kaldi需要的關於音素的額外資訊。如果你想用已有的識別系統和語言模型對你的資料進行解碼,那麼你只需要重寫―資料部分。接下來看看data/lang/目錄下的有關內容。
“lang” 目錄
現在我們關注一下資料準備的“lang”語言資料這個目錄。
s5# ls data/lang
L.fst L_disambig.fst oov.int oov.txt phones phones.txt topo words.txt
1)首先是有檔案phones.txt 和 words.txt。這些都是符號表(symbol-table)檔案,符合 OpenFst 的格式定義。其中每一行首先是一個文字項,接著是一個數字項:
s5# head -3 data/lang/phones.txt
0
sil 1
a1 2
s5# head -3 data/lang/words.txt
0
1
2
在 Kaldi 中,這些檔案被用於在這些音素符號的文字形式和數字形式之間進行轉換。大多數情況下,只有指令碼 utils/int2sym.pl、 utils/sym2int.pl 和 OpenFst 中的程式fstcompile 和 fstprint 會讀取這些檔案。
2)檔案L.fst是FST形式的發音字典。其中,輸入是音素,輸出是詞。
3)檔案L_disambig.fst也是發音字典,但是還包含了為消歧而引入的符號,諸如#1、#2之類,以及為自環(self-loop) 而引入的#0。#0能讓消岐符號“通過”(pass through)整個語法,這些都不用手動新增這些符號。
4)檔案 data/lang/oov.txt 僅僅只有一行:
s5# cat data/lang/oov.txt
在訓練過程中,所有詞彙表以外的詞都會被對映為這個詞(UNK 即unknown)。“” 本身並沒有特殊的地方,也不一定非要用這個詞。重要的是需要保證這個詞的發音只包含一個被指定為“垃圾音素”(garbage phone)的音素。該音素會與各種口語噪聲對齊。在我們的這個特別設定中,該音素被稱為,就是“spoken noise” 的縮寫:
s5# grep -w UNK data/local/dict/lexicon.txt
SPN
5)檔案 oov.int 包含的整數形式(從 words.txt 中提取的)
6)檔案/lang/topo 則含有如下資料:
你不用手動建立data/lang/topo。這個檔案指明瞭我們所用 HMM 模型的拓撲結構。在這個例子中,一個“真正”的音素內含 3 個發射狀態,呈標準的三狀態從左到右拓撲結構——即“Bakis” 模型。(發射狀態即能“發射”特徵向量的狀態,與之對應的就是那些“假”的僅用於連線其他狀態的非發射狀態)。
7) phones目錄下有許多關於音素集的資訊, 幸運的是,作為一個 Kaldi 使用者,你沒有必要去一一手動建立所有這些檔案,因為我們有一個指令碼“utils/prepare_lang.sh”能夠根據更簡單的輸入為你建立所有這些檔案。
s5# ls data/lang/phones
context_indep.csl disambig.txt nonsilence.txt roots.txt silence.txt context_indep.int extra_questions.int optional_silence.csl sets.int word_boundary.int context_indep.txt extra_questions.txt optional_silence.int sets.txt word_boundary.txt disambig.csl nonsilence.csl optional_silence.txt silence.csl
這些檔案大多數有三個不同版本:一個“.txt”形式,如:
s5# head -3 data/lang/phones/context_indep.txt
sil
一個“.int” 形式,如:
s5# head -3 data/lang/phones/context_indep.int
1
以及一個“.csl” 形式,如:
s5# cat data/lang/phones/context_indep.csl
1
三種形式的檔案包含的是相同的資訊,所以我們只關注人們更易閱讀的“.txt”形式。”context_indep.txt”包含一個音素列表,用於建立文字無關的模型。也就是說,對這些音素,我們不會建立需要參考左右音素的上下文決策樹。實際上,我們建立的是更小的決策樹,只參考中心音素和 HMM 狀態。這依賴於“roots.txt”。
Phones資料夾裡:
a) silence.txt 和 nonsilence.txt 分別包含靜音音素列表和非靜音音素列表。這兩個集合是互斥的,且如果合併在一起,應該是音素的總集。在本例中,silence.txt與 context_indep.txt 的內容完全一致。我們說“非靜音”音素,是指我們將要估計各種線性變換的音素。所謂線性變換是指全域性變換,如 LDA 和 MLLT,以及說話人自適應變換,如 fMLLR。根據之前的實驗,我們相信,加入靜音對這些變換沒有影響。
s5# head -3 data/lang/phones/silence.txt
SIL
s5# head -3 data/lang/phones/nonsilence.txt
a1
a2
a3
b) disambig.txt 包含一個“消岐符號” 列表 (見 Disambiguation symbols):
s5# head -3 data/lang/phones/disambig.txt
1
#1
#2
這些符號會出現在 phones.txt 中,被當做音素使用。
c) optional_silence.txt 只含有一個音素。該音素可在需要的時候出現在詞之間:
s5# cat data/lang/phones/optional_silence.txt
SIL
(可選靜音列表中的)音素出現在詞之間的機制是,在發音字典的 FST 中,可選地讓該音素出現在每個詞的詞尾(以及每段發音的段首)。該音素必須在phones/中指明而不是僅僅出現在 L.fst 中。
d) sets.txt包含一系列的音素集,在聚類音素時被分組(被當做同一個音素),以便建立文字相關問題集(在Kaldi 中,建立決策樹時使用自動生成的問題集,而不是具有語言語義的問題集)。本設定中,sets.txt 將每個音素的所有不同詞位的變體組合為一行:
s5# head -3 data/lang/phones/sets.txt
sil
a1
a2
e) extra_questions.txt 包含那些自動產生的問題集之外的一些問題:
s5# cat data/lang/phones/extra_questions.txt
sil
a1 ai1 an1 ang1 ao1 e1 ei1 en1 eng1 i1 ia1 ian1 iang1 iao1 ie1 in1 ing1 iong1 iu1 ix1 iy1 o1 ong1 ou1 u1 ua1 uai1 uan1 uang1 ueng1 ui1 un1 uo1 v1 van1 ve1 vn1
a2 ai2 an2 ang2 ao2 e2 ei2 en2 eng2 er2 i2 ia2 ian2 iang2 iao2 ie2 in2 ing2 iong2 iu2 ix2 iy2 o2 ong2 ou2 u2 ua2 uai2 uan2 uang2 ui2 un2 uo2 v2 van2 ve2 vn2
你可以看到,所謂一個問題就是一組音素。第一個問題是關於“靜音音素”的,被作為發音字典中可選的靜音詞的表示,即不會出現在某個詞中,而是單獨成詞,後面則是關於普通音素的詞位資訊。在具有語調和語氣的設定中,extra_questions.txt 可以包含與之相關的問題集。
f) roots.txt 檔案包含如何建立音素上下文決策樹的資訊:
head data/lang/phones/roots.txt
shared split sil
shared split a1
shared split a2
shared split a3
shared split a4
shared split a5
shared split aa
shared split ai1
shared split ai2
shared split ai3
暫時你可以忽略“shared”和“split”——這些與我們建立決策樹時的具體選項有關。
一個HMM 中的 3 個狀態(對靜音來說有 5 個狀態)共享一個根,且決策樹的建立過程需要知道狀態(的共享情況)。HMM 狀態間共享決策樹根節點,這就是 roots檔案中“shared” 代表的意思。
Prepare _lang.sh指令碼解讀