在訊號處理中,梅爾倒頻譜(Mel-Frequency Cepstrum, MFC)係一個可用來代表短期音訊的頻譜,其原理基于用非線性的梅爾刻度(mel scale)表示的對數頻譜及其線性餘弦轉換(linear cosine transform)上。
梅尔频率倒谱系数(Mel-Frequency Cepstral Coefficients, MFCC)是一組用來建立梅爾倒頻譜的關鍵係數。由音樂訊號當中的片段,可以得到一組足以代表此音樂訊號之倒頻譜(Cepstrum),而梅爾倒頻譜係數即是從這個倒頻譜中推得的倒頻譜(也就是頻譜的頻譜)。與一般的倒頻譜不同 ,梅爾倒頻譜最大的特色在於,於梅爾倒頻譜上的頻帶是均勻分布於梅爾刻度上的,也就是說,這樣的頻帶相較於一般所看到、線性的倒頻譜表示方法,和人類非線性的聽覺系統更為接近。例如:在音訊壓縮的技術中,便常常使用梅爾倒頻譜來處理。
梅爾倒頻譜係數通常是用以下方法得到的:
#將一訊號進行傅立葉轉換
#利用三角窗函數(triangular overlapping window),將頻譜映射(mapping)至梅爾刻度
#取對數
#取離散餘弦轉換
#MFCC是轉換後的頻譜
取得梅爾倒頻譜的方法眾多,上述只是其中一種。
另外,ETSI在2000年左右有定義一套專為行動電話設計的梅爾倒頻譜係數演算法。
歷史
一般認為Paul Mermelstein 是主要致力於發展梅爾倒頻譜的人,然而 Mermelstein 本人卻將主要的概念功勞歸給 Bridle 和 Brown for the idea:
Bridle 和 Brown 運用了一組十九個、由餘弦轉換導出的頻譜型的係數,轉換的輸入值是訊號在一組在頻帶上有非均勻間隔分布的帶通濾波器後的輸出。
濾波器的間隔是呈現對數分布的;因此,一般稱之為梅爾式的導頻譜係數
係數推導
- 對該信號做傅立葉變換
X[k]=FT{x[n]}
- 根據下面公式算出Y[m]
Y[m]=\log \left( \sum_{k=f_{m-1}}^{f_{m+1}} \left| X[k] \right|^2 B_m[k] \right)
其中B_m[k]是梅爾頻率倒頻譜的遮罩
B_m[k]= \begin{cases} 0 & \mbox{for } kf_{m+1}\\
\cfrac {k-f_{m-1}}{f_m-f_{m-1}} & \mbox{for } f_{m-1} \leq k \leq f_m \\
\cfrac {f_{m+1}-k}{f_{m+1}-f_m} & \mbox{for } f_m \leq k \leq f_{m+1} \end{cases}
3.對Y[m]做IDCT得c_x[n],因為Y[m]是偶函數,故用IDCT(反離散餘弦變換)取代IDFT(反離散傅立葉變換)
c_x[n]= \frac{1}{M} \sum_{m=1}^{M} Y[m]cos \left( \cfrac{\pi n(m-1/2)}{M} \right)
優勢
梅爾倒頻譜主要是為了解決傳統倒頻譜在數學計算上的缺陷,並使其特徵更適用於聲學與語音辨識。
相位產生的無限多解問題
一般倒頻譜的核心運算是對 X(F) 取對數,而 \log(X(F)) = \log|X(F)| + j\arg(X(F)),其中虛部的相角 \arg(X(F)) 本質上是一個週期函數,任何相位值加上 2\pi 的整數倍都代表同一個複數,導致虛部j\arg(X(F))產生無限多組解,造成相位計算上的模糊與困難。
相對地,梅爾頻率倒頻譜在計算 Y[m] 時,是把 |X[k]|^2 這個一定為非負實數的量,透過三角形濾波器 B_m[k] 在某個頻帶範圍內加權後加總,所以 \sum_k |X[k]|^2 B_m[k] 永遠是一個確定的非負實數,對它取對數自然只會得到唯一實數值,不存在多解問題,使得梅爾倒頻譜的計算更加乾淨、穩定且更容易實作。
數值趨近負無限大
在實際訊號中,頻譜 |X(F)| 在某些頻率點上很可能因為訊號本身的特性或是因為雜訊造成的相消干涉,而出現非常接近零甚至等於零的情況。一旦 |X(F)| \to 0,\log|X(F)| 就會趨近於負無限大,這在數值計算上會造成嚴重的不穩定或讓後續的反傅立葉轉換無法收斂或產生極端的尖峰值。
梅爾倒頻譜的做法是先把整個頻帶範圍內的能量 |X[k]|^2 用濾波器 B_m[k] 做加權加總,而不是針對單一頻率點取對數。由於這個加總是橫跨一段頻帶的多個頻率成分,即便其中某幾個 |X[k]| 恰好接近零,整個頻帶內其他頻率成分的能量幾乎不可能同時也都接近零,因此 \sum_k |X[k]|^2 B_m[k] 整體變成零的機率被大幅降低,\log 運算趨近於 -\infty 的風險也就跟著大幅減少,整體數值穩定性自然提升許多。
人類聽覺感知
人耳對頻率的敏感度並非線性,在低頻範圍(例如幾百到一千多 Hz)人耳的頻率解析度很高,能分辨很細微的頻率差異,但在高頻範圍,即使頻率差異很大,人耳感受到的差異卻相對小。
梅爾頻率倒頻譜使用了頻率以等比級數增加的遮罩,在低頻區間排列得較密、頻寬較窄,在高頻區間則排列得較疏、頻寬較寬,模擬人耳對不同頻率的解析能力。因此,當訊號經過這組濾波器處理後再取對數、做離散餘弦轉換,所得到的特徵會更貼近人耳實際感受到的差異。對於語音辨識這類模擬人類如何分辨聲音的應用,這種貼近聽覺感知的特徵自然比一般倒頻譜更有意義。
運算複雜度
一般的複數倒頻譜在最後一步,是將已經取過對數的複數頻譜 \hat{X}(F) 透過反離散時間傅立葉轉換(IFT)轉回時域得到 \hat{x}[n],由於此 IFT 是複數運算,計算量相對較大。
而梅爾頻率倒頻譜在計算出每個濾波器頻帶對應的實數對數能量 Y[m] 之後,使用離散餘弦轉換(DCT)將 Y[m] 轉換成最終的係數,運算上不需要處理虛部,且可以利用與快速傅立葉轉換(FFT)類似但更精簡的快速演算法來計算,因此相較於需要處理複數資料的 IFT,DCT 的運算量明顯較小。再加上梅爾倒頻譜整體所需計算的資料量本身就比一般倒頻譜(理論上是無限長序列)小得多,使得梅爾頻率倒頻譜在計算效率上具有相當明顯的優勢。
應用
梅爾倒頻譜係數通常可以用於作為语音识别系統中的特徵質觀察,例如:可以自動辨認一個人透過電話說的數字。梅爾倒頻譜係數通常也可以作為声纹识别(Speaker Recognition),也就是、用來辨識某段語音訊號的發話者是誰的技術。除此之外,也延伸出語音情緒辨識等方向。
梅爾倒頻譜係數在近年來於音樂分類(music genre classification)相關應用的領域也逐漸嶄露頭角,例如尋找一段音樂的相似程度等。
語音辨識
梅爾頻率倒譜係數MFCC和感知線性預測PLP:不同於LPC等通過對人的發聲機理的研究而得到的聲學特徵,Mel倒譜係數MFCC和感知線性預測PLP是受人的聽覺系統研究成果推動而導出的聲學特徵。對人的聽覺機理的研究發現,當兩個頻率相近的音調同時發出時,人只能聽到一個音調。臨界帶寬指的就是這樣一種令人的主觀感覺發生突變的帶寬邊界,當兩個音調的頻率差小於臨界帶寬時,人就會把兩個音調聽成一個,這稱之為屏蔽效應。Mel刻度是對這一臨界帶寬的度量方法之一。
MFCC的計算首先用FFT將時域信號轉化成頻域,之後對其對數能量譜用依照Mel刻度分布的三角濾波器組進行卷積,最後對各個濾波器的輸出構成的向量進行離散餘弦變換DCT,取前N個係數。PLP仍用德賓法去計算LPC參數,但在計算自相關參數時用的也是對聽覺激勵的對數能量譜進行DCT的方法。
雜訊
根源
梅爾倒頻譜係數在理想的安靜環境下表現優異,但其本質上並非相當穩定,在實際計算過程中極易受到外加的加性雜訊影響。這種脆弱性主要源自於演算法中的取對數步驟。當語音訊號處於低能量區段(例如句尾、氣音或停頓處)時,即使是微弱的背景雜訊,也會在對數運算後被不成比例地放大,導致最終算出的倒頻譜係數產生劇烈波動,進而大幅降低語音辨識或聲紋比對系統的準確率。
特徵正規化
為了對抗雜訊與錄音設備帶來的變異,通常必須在萃取出的 MFCC 特徵上進行正規化(Normalization)處理。最廣泛使用的技術是倒頻譜均值減法(Cepstral Mean Subtraction, CMS)與倒頻譜變異數正規化(Cepstral Variance Normalization, CVN),兩者常合併稱為 CMVN。CMS 的做法是計算一段語音中所有 MFCC 向量的平均值,並將每個特徵向量扣除該平均值;這能有效消除由麥克風特性或傳輸通道所造成的靜態線性濾波效應(迴響或通道失真)。而 CVN 則是將特徵的變異數縮放至單位變異數,以減少不同發話者音量大小與動態範圍變化的干擾。
演算法改良
除了後期的正規化,許多研究者也致力於從 MFCC 的基礎演算法著手,使其設計得更加頑強。其中一種做法是導入對數能量底限。由於當頻帶能量趨近於零時,對數運算會產生極大的負值,因此在進行離散餘弦轉換(DCT)之前,演算法會強制規定一個能量的下限值。一旦濾波器計算出的能量低於此範圍,便會被提升並鎖定在這個底限值上。這種機制確保了諸如背景白噪音等低能量項,不會在對數化後主導整個係數的結果。
此外,為了進一步平滑雜訊造成的頻譜峰值劇烈變化,也會套用倒頻譜提升(Cepstral Liftering)技術,對計算出的 MFCC 乘上一個正弦窗函數,藉此壓抑高階係數中不穩定的雜訊成分,同時突顯對語音辨識最有幫助的中低階係數。
程式碼實作範例
以下是使用 Python實作提取梅爾倒頻譜係數(MFCC)的範例:
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from scipy.fftpack import dct
參數設定
fs = 8000
frame_ms = 25
N = int(fs * frame_ms / 1000)
NFFT = 512
n_filters = 20
n_ceps = 13
產生模擬訊號(包含三個頻率成分)
n = np.arange(N)
f0 = 150
f1, f2 = 1200, 2400
x = (1.0 np.sin(2 np.pi f0 n / fs)
- 0.6 np.sin(2 np.pi f1 n / fs)
- 0.3 np.sin(2 np.pi f2 n / fs))
加上 Hamming 窗函數
window = np.hamming(N)
x_w = x * window
快速傅立葉轉換 (FFT) 與功率頻譜計算
X = np.fft.rfft(x_w, NFFT)
freqs = np.fft.rfftfreq(NFFT, d=1 / fs)
power_X = np.abs(X) ** 2
定義 Hz 與 Mel 刻度之間的轉換函數
def hz_to_mel(f):
return 2595.0 * np.log10(1.0 + f / 700.0)
def mel_to_hz(m):
return 700.0 (10 * (m / 2595.0) - 1.0)
計算梅爾濾波器組的中心頻率與邊界
low_mel = hz_to_mel(0)
high_mel = hz_to_mel(fs / 2)
mel_points = np.linspace(low_mel, high_mel, n_filters + 2)
hz_points = mel_to_hz(mel_points)
bin_points = np.floor((NFFT + 1) * hz_points / fs).astype(int)
建立梅爾三角形濾波器組
filters = np.zeros((n_filters, len(freqs)))
for m in range(1, n_filters + 1):
f_left, f_center, f_right = bin_points[m - 1], bin_points[m], bin_points[m + 1]
for k in range(f_left, f_center):
if f_center != f_left:
filters[m - 1, k] = (k - f_left) / (f_center - f_left)
for k in range(f_center, f_right):
if f_right != f_center:
filters[m - 1, k] = (f_right - k) / (f_right - f_center)
濾波器加權與能量計算
filter_energy = filters @ power_X
filter_energy = np.where(filter_energy == 0, np.finfo(float).eps, filter_energy) # 避免 log(0)
log_energy = np.log(filter_energy) # Y[m]
離散餘弦轉換 (DCT) 取得 MFCC
mfcc = dct(log_energy, type=2, norm="ortho")[:n_ceps]
參考
评论 (0)