Kaldi官方github地址:https://github.com/kaldi-asr/kaldi
Kaldi目錄結構
./tools, ./src, ./egs 這三個目錄是比較重要的。
./tools目錄下面全部都是Kaldi依賴的包。其中主要有:
- OpenFST:Weighted Finite State Transducer library,是一個用來構造有限狀態自動機的庫。我們知道隱馬爾科夫模型就可以看成是一個有限狀態自動機的。這是最終要的一個包,Kaldi的文檔裏面說:If you ever want to understand Kaldi deeply you will need to understand OpenFst.誒,要學的好多。
- ATLAS:這是一個C++下的線性代數庫。做機器學習自然是需要很多矩陣運算的。
- IRSTLM:這是一個統計語言模型的工具包。
- sph2pipe:這是賓夕法尼亞大學linguistic data consortium(LDC)開發的一款處理SPHERE_formatted數字音頻文件的軟件,它可以將LDC的sph格式的文件轉換成其它格式。
./src目錄存放的是Kaldi的源代碼。
./egs存放的是Kaldi提供的一些例子。
Kaldi的編譯安裝:
按照README.md中說明進行操作即可
運行yesno實例
該實例是一個非常小的數據集,每一條記錄都是一系列yes或者no的語音,標註是由文件名來標註的。先運行一下。
切換到./egs/yesno/s5目錄下,運行sudo./run.sh命令。
經過一段時間的訓練和測試,可以看到運行結果。
WER爲0.00。看來這個例子識別的還是挺準的。
PS:WER(WordError Rate)是字錯誤率,是一個衡量語音識別系統的準確程度的度量。其計算公式是WER=(I+D+S)/N,其中I代表被插入的單詞個數,D代表被刪除的單詞個數,S代表被替換的單詞個數。也就是說把識別出來的結果中,多認的,少認的,認錯的全都加起來,除以總單詞數。這個數字當然是越低越好。
下面進入./yesno/s5/waves_yesno目錄瞧一瞧。
全部都是.wav格式的音頻文件。可以打開一個文件聽一聽,發現是一個老男人連續不停地說yes或者no,每個文件說8次。文件名中,0代表那個位置說的是no,1代表說的是yes。這個實驗沒有單獨的標註文件,直接採用的是文件名來標註的。
那個waves_yesno.zip.gz數據可以在http://www.openslr.org/resources/1/waves_yesno.tar.gz上下載,解壓到s5下面。也可以不下載,run.sh裏就幫你做好了。你在實驗前可以看下里面的說明文檔。
運行thchs30(清華大學中文語料庫)
https://blog.csdn.net/snowdroptulip/article/details/78943748
HCLG
L.fst: The Phonetic Dictionary FST
L maps monophone sequences to words.
The file L.fst is the Finite State Transducer form of the lexicon with phone symbols on the input and word symbols on the output.
L_disambig.fst:The Phonetic Dictionary with Disambiguation Symbols FST
A lexicon with disambiguation symbols
G.fst:The Language Model FST
FSA grammar (can be built from an n-gram grammar).
C.fst:The Context FST
C maps triphone sequences to monophones.
Expands the phones into context-dependent phones.
H.fst:The HMM FST
H maps multiple HMM states (a.k.a. transition-ids in Kaldi-speak) to context-dependent triphones.
Expands out the HMMs. On the right are the context-dependent phones and on the left are the pdf-ids.
HCLG.fst: final graph
總結一下:
構圖過程 G -> L -> C -> H
G: 作爲 acceptor (輸入 symbol 與輸出相同),用於對grammar 或者 language model 進行編碼
L: Lexicon, 其輸出 symbol 是 words, 輸入 symbol 是 phones
C: context-dependency 其輸出 symbol 是 phones, 其輸入 symbol 爲表示context-dependency phones
如: vector<int32> ctx_window = { 12, 15, 21 };
含義:id = 15 的 phone 爲 中心 phone, left phone id = 12, right phone id = 21
H: 包括HMM definitions,其輸出 symbol 爲context-dependency phones, 其輸入 symbol 爲transitions-ids(即 對 pdf-id 和 其它信息編碼後的 id)
asl=="add-self-loops”
rds=="remove-disambiguation-symbols”,
and H' is H without the self-loops:
HCLG = asl(min(rds(det(H' o min(det(C o min(det(L o G))))))))
ark文件與txt文件互相轉換
這個很簡單,也只需要用到copy-feats命令
copy-feats ark:train.ark ark,t:/train.txt ark轉化爲txt
copy-feats ark,t:train.txt ark:train.ark txt轉化爲ark
總結:主要的文件轉化是通過copy-feats這個命令,它的主要功能是將文件變成數據流,這樣方便對數據進行處理。
比如你想查看kaldi中提取的mfcc特徵到底是什麼樣子,同樣可以用copy-feats,如:
copy-feats ark:train.ark ark,t:- | less
通過一個管道用less來查看ark裏面的內容。
https://blog.csdn.net/by21010/article/details/51776447
命令行級 I/O 機制
命令行 I/O 是指在 shell 上調用編譯好的 Kaldi 工具的方法。比如,如果想查看音頻文件的時長,就可以使用這樣的命令
wav-to-duration scp:wav.scp ark,t:-
其中,wav-to-duration 是 Kaldi 中的查看時長的工具,後面兩個是參數。下面具體介紹命令行級 Kaldi 的 I/O。
非表格型I/O
非表格型的 I/O 一般比較簡單,一般是輸入輸出只包含一個或兩個對象的文件或流(比如,聲學模型文件,變換矩陣)。使用方式就是 shell 命令的使用方式。其中值得注意的有:
- Kaldi 採用一種擴展的文件名進行輸入輸出。讀取文件的文件名稱爲 rxfilename , 寫入的文件名稱爲 wxfilename。
- 在 rxfilename/wxfilename 處採用 “-” 來表示標準輸入輸出。
- rxfilename/wxfilename 處可以使用管道命令,比如先用gunzip將壓縮文件解壓,再輸入到 Kaldi 程序中,即可在文件輸入路徑處填入 “gunzip -c foo.gz|”。
- rxfilename/wxfilename 後可以通過 “:” 來描述偏移量,如 “foo:1045” 表示從 foo 文件偏移 1045 個字節開始讀取。
- 使用 –binary=true/false 來控制是否使用二進制輸出。默認是true。
- 有一組 copy* 命令,可以用來查看文件。如,copy-matrix –binary=false foo.mat -。
- Log 信息和輸出會混在一起顯示,但是 Log 信息是 stderr 上,所以不會傳到管道中。可以通過添加 2>/dev/null 命令,將log信息重定向到 /dev/null。
下面列舉一些例子:
echo ‘[ 0 1 ]’ | copy-matrix –binary=false - -
將矩陣 [ 0 1 ] 輸入到 copy-matrix 中,再顯示出來。亦可以將其表示爲
copy-matrix –binary=false ‘echo [ 0 1 ]|’ -
表格型I/O
對於一系列數據的集合,比如對應於每一句話的特徵矩陣,或者每一條音頻文件對應的路徑,Kaldi 採用表格形式的數據表示。表格中,以沒有空格的字符串爲索引。Kaldi 中,稱從表格文件中讀取的一個字符串爲 rspecifier, 寫入表格文件的一個字符串爲wspecifier。有兩種表格文件格式:archive 和 script 。其讀取方式和非表格型數據類似,也是使用 rxfilename/wxfilename的格式,其格式爲[options]:path:[offset]。需要在 options 中註明是archive文件還是script文件。例如
wav-to-duration scp:wav.scp ark,t:-
rspecifiers 和 wspecifier
rspecifiers 和 wspecifier 是 Kaldi 中定義的兩種術語,是存在於表格文件中的文件名,格式類似於 rxfilename/wxfilename, 亦可以採用管道命令呢,對於ark文件,可以添加選項,如ark,s,cs:-等。
兩種存儲格式:script-file 和 archive-file
script-file 是一種文件指針,裏面包含的是具體文件所在路徑,其格式爲
key rspecifier|wspecifier
key 是字段名字,rspecifier/wspecifier則是文件路徑,rspecifier/wspecifier 可以有空格。例如 “utt1 gunzip -c /foo/bar/utt1.mat.gz”。
archive-file 裏面裝的是實際的數據。其文件格式是
key1 object1 key2 object2 key3 object3 …
ark文件可以連接在一起,依然是一個有效的ark文件。但是如果需要的文件時有序的話,連接的時候應該要注意。
ark文件和scp文件有可能同時寫,這時可以這麼寫:ark,scp:foo.ark,foo.scp。
特徵提取
對data下的train、dev和test數據分別調用下面兩個腳本
steps/make_mfcc.sh
特徵存在feats.scp
中,存儲的特徵是每一幀13維,當用到mfcc特徵的時候才計算deltas和deltas-deltas,轉爲39維。
腳本主要爲下面幾行
$cmd JOB=1:$nj $logdir/make_mfcc_${name}.JOB.log \
compute-mfcc-feats $vtln_opts --verbose=2 --config=$mfcc_config \
scp,p:$logdir/wav_${name}.JOB.scp ark:- \| \
copy-feats --compress=$compress ark:- \
ark,scp:$mfccdir/raw_mfcc_$name.JOB.ark,$mfccdir/raw_mfcc_$name.JOB.scp \
|| exit 1;
其中$cmd爲run.pl
以data/train爲例
- 檢查。檢查一些文件是否存在等
- 根據變量$nj的大小,將data/train/wav.scp平分爲$nj份
- 調用
run.pl
,提取特徵。一個JOB處理一份wav.scp,共$nj個JOB。用到程序compute-mfcc-feats
和copy-feats
,生成mfcc/raw_mfcc_train.JOB.ark
和對應的mfcc/raw_mfcc_train.JOB.scp
文件,JOB爲1到$nj的數字。 - 將$nj個
mfcc/raw_mfcc_train.JOB.scp
文件合成一個data/train/feats.scp
文件 - 檢查。檢查是否正確提取所有文件
steps/compute_cmvn_stats.sh
- 對每個說話人計算cmvn(cepstral mean and variance normalization)。
- 對每個說話人,對每一維(共13維)分別計算
count/sum/sum-squared
三組statistics,分別爲1維、13維、13維。count
代表該說話人所有音頻文件的總幀數,sum
代表所有幀裏每一維的和,sum-square
代表所有幀裏每一維的平方的和。然後根據這三組statistics,計算均值和方差。 - 可用
copy-matrixs
程序查看cmvn.scp或cmvn.ark文件,對每一個說話人,有一個28維的矩陣,前十三維是sum,然後是count,接着十三維是sum-squared,最後一個0。 - 該腳本有三個選項:
--fake
、--two-channel
、--fake-dims
調用compute-cmvn-stats
生成mfcc/cmvn_train.ark
和mfcc/cmvn_train.scp
,然後將後者複製到data/train/cmvn.scp
https://blog.csdn.net/Xwei1226/article/details/80491538
https://blog.csdn.net/u010731824/article/details/69668765
ASR指標:
正確率:只要和原來的標籤相同就算正確。
準確率:除了要正確,還需要加上因爲插入其它詞造成的錯誤。
Correct(cor) = ( N − D − S )× 100% / N = H× 100% / N
Accurac(acc) = ( N− D− S− I )× 100% / N = (H - I)× 100% / N
N- total number of labels (總標籤數)
D- deletion errors (刪除錯誤)
S- substitution errors (替換錯誤)
I- insertion errors (插入錯誤)
ASR指標統計工具:HTK HResults