人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析
語音識別中常用的音頻特征包括fbank與mfcc。
獲得語音信號的fbank特征的一般步驟是:預(yù)加重、分幀、加窗、短時傅里葉變換(STFT)、mel濾波、去均值等。對fbank做離散余弦變換(DCT)即可獲得mfcc特征。
下面通過代碼進行分析說明。
- 1、導(dǎo)包
- 2、繪圖函數(shù)
繪制時域圖
def plot_time(sig, fs):time = np.arange(0, len(sig)) * (1.0 / fs)plt.figure(figsize=(20, 5))plt.plot(time, sig)plt.xlabel('Time(s)')plt.ylabel('Amplitude')plt.grid()繪制頻域圖
def plot_freq(sig, sample_rate, nfft=512):xf = np.fft.rfft(sig, nfft) / nfftfreqs = np.linspace(0, sample_rate/2, nfft/2 + 1)xfp = 20 * np.log10(np.clip(np.abs(xf), 1e-20, 1e100))plt.figure(figsize=(20, 5))plt.plot(freqs, xfp)plt.xlabel('Freq(hz)')plt.ylabel('dB')plt.grid()繪制二維數(shù)組
def plot_spectrogram(spec, notylabele):fig = plt.figure(figsize=(20, 5))heatmap = plt.pcolor(spec)fig.colorbar(mappable=heatmap)plt.xlabel('Time(s)')plt.ylabel(ylabel)plt.tight_layout()plt.show()- 3、數(shù)據(jù)讀取
音頻信號鏈接:OSR_us_000_0010_8k.wav
wav_file = 'OSR_us_000_0010_8k.wav' fs, sig = wavfile.read(wav_file) # 保留前3.5s數(shù)據(jù) sig = sig[0: int(3.5 * fs)]plot_time(sig, fs)plot_freq(sig, fs)- 4、預(yù)加重
從上面這個圖來看,確實起到了平衡頻譜的作用。
- 5、分幀
- 6、加窗
在分幀之后,通常需要對每幀的信號進行加窗處理。目的是讓幀兩端平滑地衰減,這樣可以降低后續(xù)傅里葉變換后旁瓣的強度,取得更高質(zhì)量的頻譜。常用的窗有:矩形窗、漢明(Hamming)窗、漢寧窗(Hanning),以漢明窗為例,其窗函數(shù)為:
這里
, 是窗的寬度。# 加窗 window = np.hamming(int(round(frame_len_s * fs))) plt.figure(figsize=(20, 5)) plt.plot(window) plt.grid() plt.xlim(0, 200) plt.ylim(0, 1) plt.xlabel('Samples') plt.ylabel('Amplitude') frame_sig *= windowplot_time(frame_sig[1], fs)plot_freq(frame_sig[1], fs)- 7、短時傅里葉變換(STFT)
對于每一幀的加窗信號,進行N點FFT變換,也稱短時傅里葉變換(STFT),N通常取256或512。
def stft(frame_sig, nfft=512):""":param frame_sig: 分幀后的信號:param nfft: fft點數(shù):return: 返回分幀信號的功率譜np.fft.fft vs np.fft.rfftfft 返回 nfftrfft 返回 nfft // 2 + 1,即rfft僅返回有效部分"""frame_spec = np.fft.rfft(frame_sig, nfft)# 幅度譜frame_mag = np.abs(frame_spec)# 功率譜frame_pow = (frame_mag ** 2) * 1.0 / nfftreturn frame_pownfft = 512 frame_pow = stft(frame_sig, nfft)plt.figure(figsize=(20, 5)) plt.plot(frame_pow[1]) plt.grid()- 8、mel濾波
經(jīng)過上面的步驟之后,在能量譜上應(yīng)用Mel濾波器組,就能提取到FBank特征。
在介紹Mel濾波器組之前,先介紹一下Mel刻度,這是一個能模擬人耳接收聲音規(guī)律的刻度,人耳在接收聲音時呈現(xiàn)非線性狀態(tài),對高頻的更不敏感,因此Mel刻度在低頻區(qū)分辨度較高,在高頻區(qū)分辨度較低,與頻率之間的換算關(guān)系為:
Mel濾波器組就是一系列的三角形濾波器,通常有40個或80個,在中心頻率點響應(yīng)值為1,在兩邊的濾波器中心點衰減到0,如下圖:
具體公式可以寫為:
def mel_filter(frame_pow, fs, n_filter, nfft):"""mel 濾波器系數(shù)計算:param frame_pow: 分幀信號功率譜:param fs: 采樣率 hz:param n_filter: 濾波器個數(shù):param nfft: fft點數(shù):return: 分幀信號功率譜mel濾波后的值的對數(shù)值mel = 2595 * log10(1 + f/700) # 頻率到mel值映射f = 700 * (10^(m/2595) - 1 # mel值到頻率映射上述過程本質(zhì)上是對頻率f對數(shù)化"""mel_min = 0 # 最低mel值mel_max = 2595 * np.log10(1 + fs / 2.0 / 700) # 最高mel值,最大信號頻率為 fs/2mel_points = np.linspace(mel_min, mel_max, n_filter + 2) # n_filter個mel值均勻分布與最低與最高mel值之間hz_points = 700 * (10 ** (mel_points / 2595.0) - 1) # mel值對應(yīng)回頻率點,頻率間隔指數(shù)化filter_edge = np.floor(hz_points * (nfft + 1) / fs) # 對應(yīng)到fft的點數(shù)比例上# 求mel濾波器系數(shù)fbank = np.zeros((n_filter, int(nfft / 2 + 1)))for m in range(1, 1 + n_filter):f_left = int(filter_edge[m - 1]) # 左邊界點f_center = int(filter_edge[m]) # 中心點f_right = int(filter_edge[m + 1]) # 右邊界點for k in range(f_left, f_center):fbank[m - 1, k] = (k - f_left) / (f_center - f_left)for k in range(f_center, f_right):fbank[m - 1, k] = (f_right - k) / (f_right - f_center)# mel 濾波# [num_frame, nfft/2 + 1] * [nfft/2 + 1, n_filter] = [num_frame, n_filter]filter_banks = np.dot(frame_pow, fbank.T)filter_banks = np.where(filter_banks == 0, np.finfo(float).eps, filter_banks)# 取對數(shù)filter_banks = 20 * np.log10(filter_banks) # dBreturn filter_banks# mel 濾波 n_filter = 40 # mel濾波器個數(shù) filter_banks = mel_filter(frame_pow, fs, n_filter, nfft) plot_spectrogram(filter_banks.T, ylabel='Filter Banks')- 9、去均值
去均值的目的是希望減少訓(xùn)練集與測試集之間的不匹配,均衡頻譜,提升信噪比。
# 去均值 filter_banks -= (np.mean(filter_banks, axis=0) + 1e-8) plot_spectrogram(filter_banks.T, ylabel='Filter Banks')去均值之后的fbank- 10、離散余弦變換(DCT)
前面提取到的FBank特征,往往是高度相關(guān)的。因此可以繼續(xù)用DCT變換,將這些相關(guān)的濾波器組系數(shù)進行壓縮。對于ASR來說,通常取2~13維,扔掉的信息里面包含濾波器組系數(shù)快速變化部分。
num_ceps = 12 mfcc = dct(filter_banks, type=2, axis=1, norm='ortho')[:, 1:(num_ceps+1)] plot_spectrogram(mfcc.T, 'MFCC Coefficients')從圖中可以看出,DCT使得fbank的很多高頻部分被濾除掉了。
同樣可以對mfcc進行去均值操作。
mfcc -= (np.mean(mfcc, axis=0) + 1e-8) plot_spectrogram(mfcc.T, 'MFCC Coefficients')去均值之后的mfcc- 11、fbank與mfcc的比較
fbank特征更多是希望符合聲音信號的本質(zhì),擬合人耳的接收特性。
DCT是線性變換,會丟失語音信號中原本的一些高度非線性成分。在深度學(xué)習(xí)之前,受限于算法,mfcc配GMMs-HMMs是ASR的主流做法。當(dāng)深度學(xué)習(xí)方法出來之后,由于神經(jīng)網(wǎng)絡(luò)對高度相關(guān)的信息不敏感,mfcc不是最優(yōu)選擇,經(jīng)過實際驗證,其在神經(jīng)網(wǎng)絡(luò)中的表現(xiàn)也明顯不如fbank。
有人質(zhì)疑是否需要傅里葉變換,其根據(jù)是傅里葉變換也是一種線性變換,也會使得語音信號中的非線性成分丟失,因此是不是有可能對時域信號進行直接處理的效果會更好。經(jīng)實驗證明,信號經(jīng)過傅里葉變換后比直接處理時域信號的效果更好,這是因為傅里葉變換本身不容易被擬合,不可避免地會增加模型的復(fù)雜度。此外,傅里葉變換是在短時上應(yīng)用的,可以假設(shè)信號在短時內(nèi)是線性的,因此,傅里葉變換的線性不會造成很嚴(yán)重的問題。
總結(jié)
本文分析了音頻信號特征fbank與mfcc,進行了代碼實現(xiàn)與可視化。
DCT造成音頻信號的高度非線性成分丟失嚴(yán)重,實驗已經(jīng)證明,mfcc在對高度相關(guān)信息不敏感的神經(jīng)網(wǎng)絡(luò)中的效果不如fbank。
傅里葉變換應(yīng)用在短時上,其本身的線性不會造成嚴(yán)重問題,實驗證明,傅里葉變換的使用有利于模型效果的提升。
參考
Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What's In-Between
ASR中常用的語音特征之FBank和MFCC(原理 + Python實現(xiàn))
英國愛丁堡大學(xué)ASR課程講義
一個成熟的python提取這些特征的包
總結(jié)
以上是生活随笔為你收集整理的人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: verilog 浮点转定点_定点数优化:
- 下一篇: bat贪吃蛇游戏代码_100行pytho