實戰:基於tensorflow 的中文語音識別模型 | CSDN博文精選
- 2019 年 10 月 28 日
- 筆記
來源 | CSDN部落格
目前網上關於tensorflow 的中文語音識別實現較少,而且結構功能較為簡單。而百度在PaddlePaddle上的 Deepspeech2 實現功能卻很強大,因此就做了一次大自然的搬運工把框架轉為tensorflow….
簡介
百度開源的基於PaddlePaddle的Deepspeech2實現功能強大,簡單易用,但新框架上手有難度而且使用過程中遇到了很多bug,因此萌生了轉成tensorflow的想法。網上看了一圈,發現基於tensorflow的中文語音識別開源項目很少,而且功能較為簡單。英語的項目倒是很多,但奈何寫程式碼的人功力太深厚,想轉成中文的很麻煩。因此本項目的目標是做一個簡單易理解,方便新手入門的基於神經網路的ASR模型,同時把常用的功能加上方便參考。(實際上是程式碼功力太差…), 語料採用Aishell 的170h語音.
項目連接ZASR_tensorflow
https://github.com/Pelhans/ZASR_tensorflow
識別流程
一、語料整理
1.1 生成 manifest.{train,dev,test} 文件
manifest 文件包含音頻文件的元資訊,如文件路徑、對應的文本、持續時長。存儲格式為JSON格式。類似於Kaldi里的scp文件 和text文件的結合。
{"audio_filepath": "/media/nlp/23ACE59C56A55BF3/wav_file/aishell/data_aishell/wav/train/S0002/BAC009S0002W0122.wav", "duration": 5.999, "text": "而對樓市成交抑制作用最大的限購"}您可以通過example/aishell/run_data.sh 腳本中的第一部分生成該文件,也可以修改參數後運行data/aishell/aishell.py 來生成,同時若指定目錄不包含指定文件,則自動下載語料並解壓。
1.2 生成vocab.txt
vocab.txt 是基於字的,即統計語料文本中的漢字。通過data_utils/build_vocab.py 生成。
1.3 生成mean_std.npz
mean_std.npz 是2000 個隨機音頻文件進行特徵處理後,計算功率譜特徵得到的均值和標準差,在訓練將會使用它對輸入的特徵做歸一化。由data_utils/compute_mean_std.py 生成。
二、特徵處理
2.1 MFCC
MFCC 也就是梅爾倒譜係數,在理論上它的獲取流程為:
- 先對語音進行預加重、分幀和加窗;(加強語音訊號性能(信噪比,處理精度等)的一些預處理)
- 對每一個短時分析窗,通過FFT得到對應的頻譜;(獲得分布在時間軸上不同時間窗內的頻譜)
- 將上面的頻譜通過Mel濾波器組得到Mel頻譜;(通過Mel頻譜,將線形的自然頻譜轉換為體現人類聽覺特性的Mel頻譜)
- 在Mel頻譜上面進行倒譜分析(取對數,做逆變換,實際逆變換一般是通過DCT離散餘弦變換來實現, 取DCT後的第2個到第13個係數作為MFCC係數),獲得Mel頻率倒譜係數MFCC,這個MFCC就是這幀語音的特徵;(倒譜分析,獲得MFCC作為語音特徵)
在程式碼上已經被人包裝好了,可以通過python_speech_features 中的mfcc函數直接得到音頻的mfcc特徵, 該函數的參數為:
mfcc(signal,samplerate=16000,winlen=0.025,winstep=0.01,numcep=13, nfilt=26,nfft=512,lowfreq=0,highfreq=None,preemph=0.97, ceplifter=22,appendEnergy=True)
具體的參數含義請查看官方介紹。
https://pypi.org/project/python_speech_features/0.4/
除了13 維 mfcc特徵外,我們還通過python_speech_features 中的 delta 函數計算了mfcc的一階差分和二階差分特徵,由此對每一幀得到了39維特徵向量。以上過程由data_utils/audio_featurizer.py內的_compute_mfcc()函數實現。
為了更緊密的結合前後幀之間的關係,在實際輸入中,每一幀的特徵由前後n_context 的特徵和本身的特徵構成i,n_context 的大小可以在conf/hyparam.py內設置。即:
inputs = concat(n_context * 39, current, n_context * 39) dims_of_input = n_context * 39 * 2 + current
特徵的n_context 連接由 data_utils/utils.py 內的 audiofile_to_input_vector()函數實現。
2.2 Linear specgram
通過FFT energy 計算linear specgram。其計算流程為:
- 通過numpy.lib.stride_tricks.as_strided() 函數對輸入的樣本進行切塊得到一個個的windows。
- 加窗,窗口採用hanning 窗,hanning 窗是一個加權餘弦窗函數,是升餘弦窗的特列。此處我們通過調用 numpy.hanning(N) 來使用它並計算權重,N代表窗口長度。
- 做FFT,調用np.fft.rfft()函數做FFT。而後經計算絕對值、求平方、計算對數等處理得到 linear specgram。
該特徵的計算由 data_utils/audio_featurizer.py 內的_specgram_real() 函數實現。
三、模型結構
3.1 概覽
DeepSpeech2 的模型結構如下圖所示:

其第一層為1D或2D的卷積神經網路,而後與BRNN或BGRU相連。其後添加了一個前瞻卷積神經網路(Lookahead CNN),該卷積神經網路的輸入除當前時間步外還結合了BRNN層的後兩時間步輸出。Lookahead CNN後採用全連接層對輸出進行整型。得到logits 去計算ctc損失函數和解碼。
在模型內我們對每一層的輸入都使用了Batch Normalization 來減少輸入和輸出間的分布差距,增加模型的泛化能力並加速訓練。
3.2 卷積神經網路CNN
為了方便搭建網路,我們對CNN部分整合到data_utils/network.py 中的conv2d()函數中,它包含卷積、Relu、max_pool、dropout操作。通過設定參數可快速得到指定形狀、步長的卷積層。
針對輸入語音特徵,在輸入到卷積層之前需要對其進行reshape操作與expamd_dims 操作,得到形狀為[batch_size, n_steps, n_dim, in_channel] 的tensor。因為我在輸入特徵時已經採用了前後幀的資訊,因此我把filter的height 設置為1。conv2d()函數的輸出shape 為 [batch_size, height, width. out_channel]。
3.3 雙向長短期記憶網路 BLSTM
為了更有效的學習前後幀間的資訊,在CNN層後使用了三層BLSTM。打包好的BLSTM實現位於 network.py 內 BiRNN()函數。在該函數內部首先定義了一個正向的LSTM和一個反向的LSTM,而後調用 tf.nn.bidirectional_dynamic_rnn() 函數生成一個BLSTM網路。需要注意的是這個函數有一個time_major 選項,如果為True,那你的輸入數據的shape[0]就應該是time_steps而不是batch_size。
3.4 Lookahead CNN
前面說過該網路就是在輸入上結合了BLSTM後兩時間步的輸出。因此理論上我們對該網路的輸入進行錯位疊加就可以了。。。但實現過程中發現tensor 因為在time_step 維度上形狀不可知導致沒有辦法迭代的取計算這個疊加。有哪位大神知道的可以告訴我一聲么,謝謝了。因此這個Lookahead CNN我用的是普通的CNN取代替的,這樣當由解決方案後可以直接替換了。
四、模型的訓練
4.1 損失函數
損失函數採用CTC損失函數,直接調用ctc_ops.ctc_loss 進行計算,其輸入為訓練文本標籤、神經網路的輸出logits和 序列長度。這裡需要注意的是假如在網路處理時time_step的長度發生了變化的話有可能導致小於seq_length 引發報錯。
4.2 損失函數的優化
優化演算法為Adam演算法,雖然有可能得不到最優的結果,但對於新人或調參能力不強的還是超級好用的。
五、解碼
5.1 ctc_ops.ctc_beam_search_decoder 解碼
最簡單的方式我們使用tensorflow自帶的ctc_ops.ctc_beam_search_decoder() 函數對網路輸出進行解碼,該解碼不使用外部的語言模型,輸入為網路輸出的logits 和 seq_length。
5.2 帶語言模型的解碼
在訓練聲學模型階段使用的是5.1的解碼方式,在實際使用過程中需要添加語言模型來提升識別的準確率。該部分由 utils/decoder/model.py 下的 decode_batch_beam_search()函數完成 。該函數接收一個2維的概率矩陣, 通過結合神經網路的輸出概率和語言模型的評分來對輸出進行解碼。
原文鏈接:https://blog.csdn.net/pelhans/article/details/81387472 (*本文為 AI科技大本營轉載文章,轉載請聯繫作者)

