1. 程式人生 > 實用技巧 >ASR中常用的語音特徵之FBank和MFCC(原理 + Python實現)

ASR中常用的語音特徵之FBank和MFCC(原理 + Python實現)

ASR中常用的語音特徵之FBank和MFCC(原理 + Python實現)

一步一步講解和實現ASR中常用的語音特徵——FBank和MFCC的提取,包括演算法原理、程式碼和視覺化等。

完整Jupyter Notebook連結:https://github.com/Magic-Bubble/SpeechProcessForMachineLearning/blob/master/speech_process.ipynb

文章目錄

語音訊號的產生

語音通常是指人說話的聲音。從生物學的角度來看,是氣流通過聲帶、咽喉、口腔、鼻腔等發出聲音;從訊號的角度來看,不同位置的震動頻率不一樣,最後的訊號是由基頻和一些諧波構成。

之後被裝置接收後(比如麥克風),會通過A/D轉換,將模擬訊號轉換為數字訊號,一般會有采樣、量化和編碼三個步驟,取樣率要遵循奈奎斯特取樣定律:f s > = 2 f fs >= 2ffs>=2f,比如電話語音的頻率一般在300Hz~3400Hz,所以採用8kHz的取樣率足矣。

下面採用一個30s左右的16位元PCM編碼後的語音wav為例。

預加重(Pre-Emphasis)

預加重一般是數字語音訊號處理的第一步。語音訊號往往會有頻譜傾斜(Spectral Tilt)現象,即高頻部分的幅度會比低頻部分的小,預加重在這裡就是起到一個平衡頻譜的作用,增大高頻部分的幅度。它使用如下的一階濾波器來實現:

y ( t ) = x ( t ) − α x ( t − 1 ) , 0.95 &lt; α &lt; 0.99 y(t) = x(t) - \alpha x(t-1), \ \ \ \ 0.95 &lt; \alpha &lt; 0.99y(t)=x(t)αx(t1),0.95<α<0.99

筆者對這個公式的理解是:訊號頻率的高低主要是由訊號電平變化的速度所決定,對訊號做一階差分時,高頻部分(變化快的地方)差分值大,低頻部分(變化慢的地方)差分值小,達到平衡頻譜的作用。

pre_emphasis = 0.97
emphasized_signal = np.append(signal[0], signal[1:] - pre_emphasis * signal[:-1])
  • 1
  • 2
plot_time(emphasized_signal, sample_rate)
  • 1

plot_freq(emphasized_signal, sample_rate)
  • 1

從下面這個圖來看,確實起到了平衡頻譜的作用。

分幀(Framing)

在預加重之後,需要將訊號分成短時幀。做這一步的原因是:訊號中的頻率會隨時間變化(不穩定的),一些訊號處理演算法(比如傅立葉變換)通常希望訊號是穩定,也就是說對整個訊號進行處理是沒有意義的,因為訊號的頻率輪廓會隨著時間的推移而丟失。為了避免這種情況,需要對訊號進行分幀處理,認為每一幀之內的訊號是短時不變的。一般設定幀長取20ms~40ms,相鄰幀之間50%(+/-10%)的覆蓋。對於ASR而言,通常取幀長為25ms,覆蓋為10ms。

加窗(Window)

在分幀之後,通常需要對每幀的訊號進行加窗處理。目的是讓幀兩端平滑地衰減,這樣可以降低後續傅立葉變換後旁瓣的強度,取得更高質量的頻譜。常用的窗有:矩形窗、漢明(Hamming)窗、漢寧窗(Hanning)

快速傅立葉變換(FFT)

對於每一幀的加窗訊號,進行N點FFT變換,也稱短時傅立葉變換(STFT),N通常取256或512,然後用如下的公式計算能量譜:

FBank特徵(Filter Banks)

經過上面的步驟之後,在能量譜上應用Mel濾波器組,就能提取到FBank特徵。

在介紹Mel濾波器組之前,先介紹一下Mel刻度,這是一個能模擬人耳接收聲音規律的刻度,人耳在接收聲音時呈現非線性狀態,對高頻的更不敏感,因此Mel刻度在低頻區分辨度較高,在高頻區分辨度較低,與頻率之間的換算關係為:

m = 2595 l o g 10 ( 1 + f 700 ) m = 2595 log_{10} (1 + \frac{f}{700})m=2595log10(1+700f)

f = 700 ( 1 0 m / 2595 − 1 ) f = 700(10^{m/2595} - 1)f=700(10m/25951)

Mel濾波器組就是一系列的三角形濾波器,通常有40個或80個,在中心頻率點響應值為1,在兩邊的濾波器中心點衰減到0,如下圖:

具體公式可以寫為:

PS:“log mel-filter bank outputs”和“FBANK features”說的是同一個東西。

MFCC特徵(Mel-frequency Cepstral Coefficients)

前面提取到的FBank特徵,往往是高度相關的。因此可以繼續用DCT變換,將這些相關的濾波器組係數進行壓縮。對於ASR來說,通常取2~13維,扔掉的資訊裡面包含濾波器組係數快速變化部分,這些細節資訊在ASR任務上可能沒有幫助。

DCT變換其實是逆傅立葉變換的等價替代:

所以MFCC名字裡面有倒譜(Cepstral)。

一般對於ASR來說,對MFCC進行一個正弦提升(sinusoidal liftering)操作,可以提升在噪聲訊號中最後的識別率:

從公式看,猜測原因可能是對頻譜做一個平滑,如果D DD取值較大時,會加重高頻部分,使得噪聲被弱化?

FBank與MFCC比較

FBank特徵的提取更多的是希望符合聲音訊號的本質,擬合人耳接收的特性。而MFCC特徵多的那一步則是受限於一些機器學習演算法。很早之前MFCC特徵和GMMs-HMMs方法結合是ASR的主流。而當一些深度學習方法出來之後,MFCC則不一定是最優選擇,因為神經網路對高度相關的資訊不敏感,而且DCT變換是線性的,會丟失語音訊號中原本的一些非線性成分。

還有一些說法是在質疑傅立葉變換的使用,因為傅立葉變換也是線性的。因此也有很多方法,設計模型直接從原始的音訊訊號中提取特徵,但這種方法會增加模型的複雜度,而且本身傅立葉變換不太容易擬合。同時傅立葉變換是在短時上應用的,可以建設訊號在這個短的時間內是靜止的,因此傅立葉變換的線性也不會造成很嚴重的問題。

結論就是:在模型對高相關的訊號不敏感時(比如神經網路),可以用FBank特徵;在模型對高相關的訊號敏感時(比如GMMs-HMMs),需要用MFCC特徵。從目前的趨勢來看,因為神經網路的逐步發展,FBank特徵越來越流行。

其他特徵

  1. PLP(Perceptual Linear Prediction)

另外一種特徵,與MFCC相比有一些優勢,具體提取方式見下圖:

  1. 動態特徵

加入表現幀之間變化的特徵,用如下公式:

d ( t ) = c ( t + 1 ) − c ( t − 1 ) 2 d(t) = \frac{c(t+1) - c(t-1)}{2}d(t)=2c(t+1)c(t1)

一般在ASR中使用的特徵(用於GMM相關的系統),是39維的;包括(12維MFCC+1維能量) + delta + delta^2

具體提取過程見下圖:

標準化

其目的是希望減少訓練集與測試集之間的不匹配。有三種操作:

  1. 去均值 (CMN)

為了均衡頻譜,提升信噪比,可以做一個去均值的操作

filter_banks -= (np.mean(filter_banks, axis=0) + 1e-8)
  • 1
plot_spectrogram(filter_banks.T, 'Filter Banks')
  • 1

mfcc -= (np.mean(mfcc, axis=0) + 1e-8)
  • 1
plot_spectrogram(mfcc.T, 'MFCC Coefficients')
  • 1

  1. 方差歸一(CVN)

除以標準差,從而使得方差為1

  1. 標準化(CMVN)

y t ( j ) = y t ( j ) − μ ( y ( j ) ) σ ( y ( j ) ) y_t(j) = \frac{y_t(j) - \mu (y(j))}{\sigma (y(j))}yt(j)=σ(y(j))yt(j)μ(y(j))

PS:這些操作,還可以針對speaker/channel做;在實時情景下,可以計算moving average。

總結

最後引用文末slide裡面的一個總結:

傳送門

Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What’s In-Between一個很優質,講的很清楚的英文部落格
Speech Signal Analysis英國愛丁堡大學一門ASR課程的講義
python_speech_features一個很成熟的python提取這些特徵的包
ASR中常用的語音特徵之FBank和MFCC(原理 + Python實現)個人部落格