日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析

發布時間:2024/9/30 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

語音識別中常用的音頻特征包括fbank與mfcc。

獲得語音信號的fbank特征的一般步驟是:預加重、分幀、加窗、短時傅里葉變換(STFT)、mel濾波、去均值等。對fbank做離散余弦變換(DCT)即可獲得mfcc特征。

下面通過代碼進行分析說明。

  • 1、導包
# 導包 import numpy as np from scipy.io import wavfile from scipy.fftpack import dct import matplotlib.pyplot as plt
  • 2、繪圖函數

繪制時域圖

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()

繪制二維數組

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、數據讀取

音頻信號鏈接:OSR_us_000_0010_8k.wav

wav_file = 'OSR_us_000_0010_8k.wav' fs, sig = wavfile.read(wav_file) # 保留前3.5s數據 sig = sig[0: int(3.5 * fs)]plot_time(sig, fs)

plot_freq(sig, fs)

  • 4、預加重
pre_emphasis = 0.97 sig = np.append(sig[0], sig[1:] - pre_emphasis * sig[:-1]) plot_time(sig, fs)

plot_freq(sig, fs)

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

  • 5、分幀
def framing(frame_len_s, frame_shift_s, fs, sig):"""分幀,主要是計算對應下標:param frame_len_s: 幀長,s:param frame_shift_s: 幀移,s:param fs: 采樣率,hz:param sig: 信號:return: 二維list,一個元素為一幀信號"""sig_n = len(sig)frame_len_n, frame_shift_n = int(round(fs * frame_len_s)), int(round(fs * frame_shift_s))num_frame = int(np.ceil(float(sig_n - frame_len_n) / frame_shift_n) + 1)pad_num = frame_shift_n * (num_frame - 1) + frame_len_n - sig_n # 待補0的個數pad_zero = np.zeros(int(pad_num)) # 補0pad_sig = np.append(sig, pad_zero)# 計算下標# 每個幀的內部下標frame_inner_index = np.arange(0, frame_len_n)# 分幀后的信號每個幀的起始下標frame_index = np.arange(0, num_frame) * frame_shift_n# 復制每個幀的內部下標,信號有多少幀,就復制多少個,在行方向上進行復制frame_inner_index_extend = np.tile(frame_inner_index, (num_frame, 1))# 各幀起始下標擴展維度,便于后續相加frame_index_extend = np.expand_dims(frame_index, 1)# 分幀后各幀的下標,二維數組,一個元素為一幀的下標each_frame_index = frame_inner_index_extend + frame_index_extendeach_frame_index = each_frame_index.astype(np.int, copy=False)frame_sig = pad_sig[each_frame_index]return frame_sigframe_len_s = 0.025 frame_shift_s = 0.01 frame_sig = framing(frame_len_s, frame_shift_s, fs, sig)
  • 6、加窗

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

這里

, 是窗的寬度。# 加窗 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 *= window

plot_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點數: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濾波

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

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

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

具體公式可以寫為:

def mel_filter(frame_pow, fs, n_filter, nfft):"""mel 濾波器系數計算:param frame_pow: 分幀信號功率譜:param fs: 采樣率 hz:param n_filter: 濾波器個數:param nfft: fft點數:return: 分幀信號功率譜mel濾波后的值的對數值mel = 2595 * log10(1 + f/700) # 頻率到mel值映射f = 700 * (10^(m/2595) - 1 # mel值到頻率映射上述過程本質上是對頻率f對數化"""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值對應回頻率點,頻率間隔指數化filter_edge = np.floor(hz_points * (nfft + 1) / fs) # 對應到fft的點數比例上# 求mel濾波器系數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)# 取對數filter_banks = 20 * np.log10(filter_banks) # dBreturn filter_banks# mel 濾波 n_filter = 40 # mel濾波器個數 filter_banks = mel_filter(frame_pow, fs, n_filter, nfft) plot_spectrogram(filter_banks.T, ylabel='Filter Banks')

  • 9、去均值

去均值的目的是希望減少訓練集與測試集之間的不匹配,均衡頻譜,提升信噪比。

# 去均值 filter_banks -= (np.mean(filter_banks, axis=0) + 1e-8) plot_spectrogram(filter_banks.T, ylabel='Filter Banks')

去均值之后的fbank
  • 10、離散余弦變換(DCT)

前面提取到的FBank特征,往往是高度相關的。因此可以繼續用DCT變換,將這些相關的濾波器組系數進行壓縮。對于ASR來說,通常取2~13維,扔掉的信息里面包含濾波器組系數快速變化部分。

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特征更多是希望符合聲音信號的本質,擬合人耳的接收特性。

DCT是線性變換,會丟失語音信號中原本的一些高度非線性成分。在深度學習之前,受限于算法,mfcc配GMMs-HMMs是ASR的主流做法。當深度學習方法出來之后,由于神經網絡對高度相關的信息不敏感,mfcc不是最優選擇,經過實際驗證,其在神經網絡中的表現也明顯不如fbank。

有人質疑是否需要傅里葉變換,其根據是傅里葉變換也是一種線性變換,也會使得語音信號中的非線性成分丟失,因此是不是有可能對時域信號進行直接處理的效果會更好。經實驗證明,信號經過傅里葉變換后比直接處理時域信號的效果更好,這是因為傅里葉變換本身不容易被擬合,不可避免地會增加模型的復雜度。此外,傅里葉變換是在短時上應用的,可以假設信號在短時內是線性的,因此,傅里葉變換的線性不會造成很嚴重的問題。

總結

本文分析了音頻信號特征fbank與mfcc,進行了代碼實現與可視化。

DCT造成音頻信號的高度非線性成分丟失嚴重,實驗已經證明,mfcc在對高度相關信息不敏感的神經網絡中的效果不如fbank。

傅里葉變換應用在短時上,其本身的線性不會造成嚴重問題,實驗證明,傅里葉變換的使用有利于模型效果的提升。

參考

Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs) and What's In-Between

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

英國愛丁堡大學ASR課程講義

一個成熟的python提取這些特征的包

總結

以上是生活随笔為你收集整理的人耳识别代码_语音识别之——音频特征fbank与mfcc,代码实现与分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。