歡迎大家關注我的博客 pelhans.com/ ,所有文章都會第一時間發布在那裡哦~


Kaldi是一個語音識別工具包,基於C++並遵循Apache v2.0協議。它包含語音信號處理、聲學模型訓練、解碼等一系列工具,同時內部還帶有各種語言的源代碼實例。非常強大。

thchs30 的運行

程序到手,當然是先跑起來看看長什麼樣子,功能是什麼。所以本部分先介紹Kaldi的運行。

1) 從github上Clone 倉庫: git clone github.com/kaldi-asr/ka

2) 進入Kaldi目錄後查看INSTALL文件,它會告訴你怎麼安裝Kaldi,需要注意的是 extras/check_dependencies.sh這裡檢查依賴,一定要確保滿足相關要求,否則後面會很麻煩。編譯的話根據自己的CPU數目選擇make -j n

3) 下載語音預料,thchs30的語料是公開的,可以在openslr.org/18/ 裏下載並解壓。

4) Kaldi安裝好後就可以進入到egs/thchs30/s5/目錄了。首先加入你是本地運行的話,需要講cmd.sh文件內的queue.pl替換為run.pl。然後再修改第11行的thchs= 的路徑為你自己存放語音語料的路徑,到此Kaldi程序就可以運行了。後面DNN那裡可能會出一點問題,這個後面再說。

生成text wav.scp utt2pk spk2utt

負責此處的是run.sh中的第22行,即:

local/thchs-30_data_prep.sh $H $thchs/data_thchs30 || exit 1;

其中$H 是當前目錄名,$thchs指的是語音語料庫位置。這倆是thchs-30_data_prep.sh 腳本的參數。(這個local我一開始以為是bash裡面的local命令,想了半天也沒有想懂,後來才發現這貨就一文件夾。。。)

該程序的答題執行流程是讀取語料庫中的{train, dev, test}文件夾下的.wav文件和.trn文件。利用wav文件的名字和所在路徑生成wav.scp文件,利用wav.trn文件中的第1行和第3行生成word.txt 和phone.txt。這裡的word和phone都是直接從文件中讀取的。同時由於此處沒有說話人識別,因此對於utt2spk(語段到說話人)和spk2utt(說話人到語段)裏的內容都是兩列相同的wav文件名。

提取MFCC特徵

對應代碼為:

steps/make_mfcc.sh --nj $n --cmd "$train_cmd" data/mfcc/$x exp/make_mfcc/$x mfcc/$x || exit 1;

其中$n是make的cpu線程數目,$train_cmd 是cmd.sh裏的train_cmd變數,$x就是循環裏的{train,dev,test}了。

關於梅爾倒譜係數(MFCC)我們之前講過,在Kaldi裏它本身設置了合理的默認值,同事保留了一部分用戶最有可能想調整的選項,如梅爾濾波器的個數,最大和最小截止頻率等等.它通常需要讀取wav文件或.pcm文件,假如數據源不是wav文件,我們就得使用工具來轉化,Kaldi中有的sph2pipe工具能滿足一般的情況.

命令工具 compute-mfcc-feats用來計算MFCC特徵,若直接運行不帶參數的話就會給出一個參數列表.改程序需要兩個參數,rspecifier是用來度.wav數據, wspecifier是用來寫特徵的(就是r 和w啦).典型的用法是,將數據寫入一個大的"archive"文件,也寫到一個"scp"文件以便隨機讀取.

MFCC的計算由Mfcc類型的對象完成,它有Compute()函數可以根據波形計算特徵.一個完整的MFCC計算如下:

1) 計算出一個文件中幀的數目(通常幀長25ms,幀移10ms)

2) 對每一幀提取數據,可選做Dithering,預加重和去除直流偏移,還可以和加窗函數想成(此處支持多種選項,如Hanmming 窗).

3)計算該點能量(假如用對數能量則沒有 C_{0} ).

4) 做快速傅裏葉變換(FFT)並計算功率譜.

5)計算每個梅爾濾波器的能量,如23個部分重疊的三角濾波器,其中心在梅爾頻域等間距.

6) 計算對數能量病作宇軒變換,根據要求保留係數(如13個).

7) 選做倒譜變;它僅僅是比例變換,確保係數在合理範圍內.

上下截止頻率根據三角濾波器界定,由選項–low-freq和–high-freq控制,通常分別設置為0Hz和奈奎斯特頻率附近,如對16kHz採樣的語音設置為–low-freq=20 和 –high-freq=7800。

Kaldi的特徵和HTK的特徵在很多方面不同,但是幾乎所有這些不同歸結於有不同的默認值。用選項–htk-compat=true並正確設置參數,能得到同HTK非常接近的特徵。一個可能重要的選項是我們不支持能量最大歸一化。這是因為Kaldi希望能把無狀態方式應用到歸一化方法,且希望從原理上計算一幀幀特徵仍能給出相同結果。但是程序compute-mfcc-feats裏有–subtract-mean選項來提取特徵的均值。對每個語音做此操作;每個說話人可以有不同的方式來提取特徵均值。(如compute_cmvn_stats.sh,表示倒譜均值和方差歸一化)。

倒譜均值方差歸一化(CMVN)

代碼為

steps/compute_cmvn_stats.sh data/mfcc/$x exp/mfcc_cmvn/$x mfcc/$x || exit 1;

在實際情況下,受不同麥克風及音頻通道的影響,會導致相同音素的特徵差別比較大,通過CMVN可以得到均值為0,方差為1的標準特徵。均值方差可以以一段語音為單位計算,但更好的是在一個較大的數據及上進行計算,這樣識別效果會更加robustness。Kaldi中計算均值和方差的代碼在compute-cmvn-stats.cc, 歸一化在apply-cmvn.cc

濾波器組(FilterBank, FBank)

人耳對聲音頻譜的響應是非線性的,經驗表明:如果我們能夠設計一種前端處理演算法,以類似於人耳的方式對音頻進行處理,可以提高語音識別的性能。FilterBank分析就是這樣的一種演算法。FBank特徵提取要在預處理之後進行,這時語音已經分幀,我們需要逐幀提取FBank特徵。

語音感知線性預測(Perceptual Linear Prediction,PLP)

PLP和MFCC一樣都是一種聲學特徵,且它們的前期計算工作也是一樣的。PLP在Kaldi的手冊中沒有找到,此處再用HTK手冊中的敘述。As implemented in HTK the PLP feature extraction is based on the standard mel-frequency

filterbank (possibly warped). The mel filterbank coefficients are weighted by an equal-loudnesscurve and then compressed by taking the cubic root. 5 From the resulting auditory spectrum LPcoefficients are estimated which are then converted to cepstral coefficients in the normal way (see above).

特徵級聲道長度歸一化(VTLN)

聲道長度是脣到聲門之間的距離.成年女性在13cm左右,成年男性在18cm左右.其語音的共振峯頻率的變化可高達20~25%.而聲道長度歸一化的目的就是通過對特徵參數空間進行變換,使得源說話人源說話人與目標說話人之間的聲道長度不匹配的程度最小化,尤其是異性之間的聲道長度差異.聲道長度歸一化通過摺疊或平移語音信號的短時譜來改變聲道的長度,令說話人的共振峯頻率相匹配.

聲道長度歸一化通過在頻域上對MFCC參數進行線性摺疊實現.該方法是基於聲道傳輸模型,假設聲道為單一均勻的聲道管:

VTL=frac{(2i-1)c}{4F_{i}}

其中,VTL為聲道長度,c為聲速;f1為第i階的共振峯頻率.聲道長度與共振峯頻率成反比,用線性摺疊的方法來近似聲道特徵的轉換.而線性摺疊可以表示為:

f^{`} = alpha f

其中f 和 f^{`} 為摺疊後和摺疊前的頻率. alpha 為頻率彎折因子.但由於信號頻率帶寬改變的問題,實際使用中則採用分段線性摺疊的方法,也就是在不同的頻率區間內使用不同的摺疊因子.

Kaldi官網對VTLN的解釋

程序compute-mfcc-feats和compute-plp-feats接收一個VTLN彎折因子選項。在目前的腳本中,這僅用作線性版的VTLN的初始化線性轉換的一種方法。VTLN通過移動三角頻率箱的中心頻率的位置來實現。移動頻率箱的彎折函數是一個在頻域空間分段線性的函數。為理解它,記住以下數量關係:

0 <= low-freq <=vtln-low < vtln-high < high-freq <= nyquist

此處,low-freq和high-freq分別是用於標準MFCC或PLP計算的最低和最高頻率(忽略更低和更高的頻率)。vtln-low和vtln-high是用於VTLN的截止頻率,它們的功能是確保所有梅爾濾波器有合適的寬度。

Kaldi實現的VTLN彎折函數是一個分段線性函數,三個部分映射區間[low-freq,high-freq]至[low-freq, high-freq]。記彎折函數為W(f),f是頻率。中段映射f到f/scale,scale是VTLN彎折因子(通常範圍為0.8到1.2)。x軸上低段和中段的連接點是滿足min(f,W(f)) = vtln-low的f點。x軸上中段和高端的連接點是滿足max(f, W(f)) = vtln-high的f點。要求低段和高段的斜率和偏移是連續的且W(low-freq)=low-freq,W(high-freq)=high-freq。這個彎折函數和HTK的不同;HTK的版本中,"vtln-low"和"vtln-high"的數量關係是x軸上可以不連續的點,這意味著變數"vtln-high"必須基於彎折因子的可能範圍的先驗知識謹慎選擇(否則梅爾濾波器可能為空)。

一個合理的設置如下(以16kHz採樣的語音為例);注意這反映的是我們理解的合理值,並非任何非常細緻的調試實驗的結果。

low-freq | vtln-low | vtln-high | high-freq | Nyquist

40 | 60 | 7200 | 7800 | 8000

Hanmming窗

前面說過,我們要處理的語音信號一般在10ms到30ms之間,我們可以把它看作是平穩的。為了處理語音信號,我們要對語音信號進行分段,即每次僅處理一段數據。

那怎麼能夠獲取一段數據呢?一種方式就是構造一個函數。這個函數在某一區間有非零值,而在其餘區間皆為0.漢明窗就是這樣的一種函數。它主要部分的形狀像sin(x)在0到pi區間的形狀,而其餘部分都是0.這樣的函數乘上其他任何一個函數f,f只有一部分有非零值。

為什麼漢明窗這樣取呢?因為之後我們會對漢明窗中的數據進行FFT,它假設一個窗內的信號是代表一個週期的信號。(也就是說窗的左端和右端應該大致能連在一起)而通常一小段音頻數據沒有明顯的週期性,加上漢明窗後,數據形狀就有點週期的感覺了。

因為加上漢明窗,只有中間的數據體現出來了,兩邊的數據信息丟失了,所以等會移窗的時候,只會移1/3或1/2窗,這樣被前一幀或二幀丟失的數據又重新得到了體現。

簡單的說漢明窗就是個函數,它的形狀像窗,所以類似的函數都叫做窗函數。

Ref

Feature extraction

利用聲道歸一化提高語音轉換效果的方法


推薦閱讀:
相關文章