Kaldi thchs30手札(七)DNN-HMM模型的訓練

Kaldi thchs30手札(七)DNN-HMM模型的訓練

來自專欄 Kaldi thchs30手札

歡迎大家關注我的博客 pelhans.com/ ,所有文章都會第一時間發布在那裡哦~


本部分是對Kaldi thchs30 中run.sh的代碼的line 106-107 行研究和知識總結,主要內容為Kaldi中nnet1的DNN-HMM模型訓練。

概覽

首先放代碼:

#train dnn model local/nnet/run_dnn.sh --stage 0 --nj $n exp/tri4b exp/tri4b_ali exp/tri4b_ali_cv || exit 1;

只有一行代碼,目標是採用DNN來訓練一個聲學模型,至於HMM部分則與GMM-HMM的HMM相似。下面對DNN部分和DNN-HMM框架進行詳細介紹.

DNN-HMM模型

之前的語音識別框架都是基於GMM-HMM的,然而淺層的模型結構的建模能力有限,不能捕捉獲取數據特徵之間的高階相關性。而DNN-HMM系統利用DNN很強的表現學習能力,再配合HMM的系列化建模能力,在很多大規模語音識別任務中都超過了GMM模型。

下圖給出一個DNN-HMM系統的結構圖。在這個框架中,HMM用來描述語音信號的動態變化,用DNN的每個輸出節點來估計連續密度HMM的某個狀態的後驗概率。在Kaldi thchs30中,該模型的整體輸入是fbank特徵,而後DNN對所有聚類後的狀態(如狀態綁定後的三音素)的似然度進行建模,得到後驗概率。再結合HMM對其進行解碼。

DNN的建模對象

我們知道,語音識別問題可表示為找到使得概率 P(W|O) 最大的句子:

egin{array}{left} W & = & argmaxlimits_{W}P(W|O)\ & = & argmaxlimits_{W}p(O|W)P(W)/P(W)\ & = & argmaxlimits_{W}p(O|W)P(W) end{array}

其中p(w)是語言模型,

 p(o|w) 就是聲學模型。用Viterbi解碼的方式對其進行展開:

egin{array}{left} p(o|w) & = & sumlimits_{q}p(o,q|w)p(q|w)\ & approx & max pi(q_{0})prodlimits_{t=1}^{T}a_{q_{t-1}q_{t}}prodlimits_{t=1}^{T}p(o_{t}|q_{t}) end{array}

傳統的GMM-HMM模型中,我們使用GMM對聲學模型進行建模,它是一個生成模型,可以直接生成似然概率 p(o_{t}|q_{t}) ,這個似然概率就是HMM所需要的觀察概率。

而現在我們要使用DNN,但DNN只能給出觀測值輸入到DNN輸出層之後在每個節點(狀態)上的後驗概率 p(q_{t} | o_{t}) ,因此我們通過貝葉斯定理將其轉換一下: p(o_{t} | q_{t}) = p(q_{t}|o_{t})p(o_{t})/p(q_{t})

其中  p (o_{t} ) 不變, p(q_{t}) 是關於狀態的先驗概率,這個概率也是訓練過程中訓練出來的(就是把觀測值(特徵向量)網狀態上對齊,跟某個狀態對齊的觀測值的個數佔比就是這個狀態的先驗概率)。這樣我們就可以對DNN-HMM模型進行解碼和訓練了。

基於DNN-HMM的模型訓練演算法

DNN-HMM 模型的主要訓練步驟如下:

  1. 首先訓練一個狀態共享的三音素 GMM-HMM 漢語識別系統,使用決策樹來決定如何共享狀態。設訓練完成的系統為 gmm-hmm。
  2. 用步驟 1 得到的 gmm-hmm 初始化一個新隱馬爾可夫模型(包括轉移概率,觀測概率,隱馬爾可夫模型的狀態),並生成一個 DNN-HMM 模型,設該模型為 dnn-hmm1。
  3. 預訓練 dnn-hmm1 系統中的深度神經網路,得到的深度神經網路為ptdnn。
  4. 使用 gmm-hmm 系統對語音訓練數據作排列(即求出訓練數據對應哪個隱馬爾可夫模型中的狀態),得到的數據設為 align-raw。
  5. 使用步驟 4 得到的數據對 ptdnn的參數作微調(可以使用隨機梯度下降演算法)。設得到的深度神經網路為 dnn。
  6. 利用 dnn 與 dnn-hmm1 和最大似然演算法重新估計隱馬爾可夫中的參數(轉移概率,觀測概率),設新得到的系統為 dnn-hmm2。
  7. 如果步驟 6 的精度不再提高則退出演算法,否則使用 dnn 和 dnn-hmm2產生新的語音訓練數據的排列數據,然後回到步驟 5。
  8. 利用訓練數據估計概率 P(q_{t}) 的值。

Kaldi中的DNN

Kaldi中的DNN實現有三個版本,其中Karel的nnet1支持單GPU訓練,好處是實現簡單,便於修改。另兩個版本的作者是Dan的nnet2和nnet3,其中nnet2支持多GPU訓練,它是在nnet1的基礎上擴展重寫而成的。nnet3是nnet2的新版。thchs30使用的是nnet1和nnet3.這裡先對nnet1進行介紹。

由於此部分在Kaldi官網有詳盡的介紹,因此此處我只把其實現的大體流程整理一下。

訓練流程

腳本 egs/wsj/s5/local/nnet/run_dnn.sh分下面這些步驟:

  1. 存儲在本地的40維fMLLR特徵, 使用steps/nnet/make_fmllr_feats.sh,這簡化了訓練腳本,40維的特徵是使用CMN的MFCC-LDA-MLLT-fMLLR。
  2. RBM 預訓練, steps/nnet/pretrain_dbn.sh,是根據Geoff Hinton』s tutorial paper來實現的。訓練方法是使用1步馬爾科夫鏈蒙特卡羅採樣的對比散度演算法(CD-1)。 第一層的RBM是Gaussian-Bernoulli, 和接下里的RBMs是Bernoulli-Bernoulli。這裡的超參數基準是在100h Switchboard subset數據集上調參得到的。如果數據集很小的話,迭代次數N就需要變為100h/set_size。訓練是無監督的,所以可以提供足夠多的輸入特徵數據目錄。

    當訓練Gaussian-Bernoulli的RBM時,將有很大的風險面臨權重爆炸,尤其是在很大的學習率和成千上萬的隱層神經元上。為了避免權重爆炸,我們在實現時需要在一個minbatch上比較訓練數據的方差和重構數據的方差。如果重構的方差是訓練數據的2倍以上,權重將縮小和學習率將暫時減小。
  3. 幀交叉熵訓練,steps/nnet/train.sh, 這個階段時訓練一個DNN來把幀分到對應的三音素狀態(比如: PDFs)中。這是通過mini-batch隨機梯度下降法來做的。默認的是使用Sigmoid隱層單元,Softmax輸出單元和全連接層AffineTransform。學習率是0.008,minibatch的大小是256;我們未使用衝量和正則化(注: 最佳的學習率與不同的隱含層單元類型有關,sigmoid的值0.008,tanh是0.00001)。

    輸入變換和預訓練DBN(比如:深度信念網路,RBMs塊)是使用選項『–input-transform』和』–dbn』傳遞給腳本的,這裡僅僅輸出層是隨機初始化的。我們使用提早停止(early stopping)來防止過擬合。為了這個,我們需要在交叉驗證集(比如: held-out set)上計算代價函數,因此兩對特徵對齊目錄需要做有監督的訓練。
  4. sMBR(State-level minimum Bayes risk)序列區分性訓練,steps/nnet/train_mpe.sh(minimum phone erro, MPE), 這個階段對所有的句子聯合優化來訓練神經網路,比幀層訓練更接近一般的ASR目標。
  5. sMBR的目標是最大化從參考的對齊中得到的狀態標籤的期望正確率,然而一個詞圖框架是來使用表示這種競爭假設。
  6. 訓練是使用每句迭代的隨機梯度下降法,我們還使用一個低的固定的學習率1e-5 (sigmoids)和跑3-5輪。
  7. 當在第一輪迭後重新生成詞圖,我們觀察到快速收斂。我們支持MMI, BMMI, MPE 和sMBR訓練。所有的技術在Switchboard 100h集上是相同的,僅僅在sMBR好一點點。
  8. 在sMBR優化中,我們在計算近似正確率的時候忽略了靜音幀。具體更加詳細的描述見danielpovey.com/files/2

個人補充

限制玻爾茲曼機(RBM)

玻爾茲曼機(Boltzmann Machines, BM)

玻爾茲曼機是二值的馬爾科夫隨機場(Markov Random Filed),一個玻爾茲曼機可以表示為帶權重的無向圖:

如上圖所示,對於有n個節點的無向圖,由於每個節點是二值的,所以一共有 2^n 個狀態,對於一個節點 x_i ,其值為1 的時候表示這個節點是』on』,其值為1的時候表示這個節點是』off』,對於一個狀態向量 	extbf{x} ,也就是長度為n的向量,表示這個圖n個節點的狀態,其能量值為:

E(x) = -b^{T}x-x^{T}Wx = -sumlimits_{j=1}^{n}b_{j}x_{j} - sumlimits_{i,j}x_{i}W_{i,j}x_{j}

x的概率分布為:

P(x) = frac{1}{Z}exp(-E(x))

Z = sumlimits_{x^{}}exp(-E(x^{}))

其中b表示長度為n的偏置向量,W是兩節點間的連接權值矩陣。

典型的BM有可見節點(Visible Node)和隱含節點(Hidden Node), 可見節點後面使用v表示,隱含節點用h表示.在這裡我們可以把v理解為我們可見的訓練參數,h理解為我們在訓練數據裡面的一些未知隱變數,如LDA裡面的隱藏話題,現在的問題是,給定一組可見節點的訓練數據 v_1,v_2,ldots,v_n ,現在的問題是,尋找參數W和b使得訓練語料的最大似然函數最大:

W^{}.b^{} = argmaxlimits_{W,b}l_{D}(W,b)

l_{D}(W, b) = prod_{i=1}^{n}P(v_{i})

P(v) = sumlimits_{h^{}}P(vodot h^{})= frac{sumlimits_{h^{}}exp(-E(vodot h^{}))}{sumlimits_{h^{}v^{}}exp(-E(vodot h^{}))}

理論上給出似然函數後,我們可以通過對其求對數而後對參數進行求導得到,但在實際操作中由於巨大的計算量變得不可接受。因此常常使用MCMC和Gibbs採樣方法。

限制玻爾茲曼機(Restricted Boltzmann Machines, RBM)

限制玻爾茲曼機是一種特殊的玻爾茲曼機,之所以是受限的,是因為,在RBM中,所有的連接都是在隱含節點和可見節點之間的,而在隱含節點內部和可見節點內部並沒有連接,一個典型的RBM的結構就是一個二分圖:

此時RBM的能量函數和之前的BM是一樣的。

RBM在DNN-HMM模型中的作用

在wsj的run_dnn.sh里採用了RBM訓練步驟。通過RBM所得到的網路參數權重將會用來初始化最終的深度學習結構的參數。之後我們就可以使用有標註的數據並利用監督學習的方法來微調整個網路。**使用該方法能有效訓練具有多層隱藏層的深度神經網路,特別是能夠有效改變最初幾層網路的權重。由於使用了大量的無標籤數據,在一定程度上避免了優化過程中局部最小值的影響,可以得到更優化的模型。RBM在DNN-HMM中的應用流程為:

對比散度(Contrastive Divergence,CD)

在求解的過程中,我們使用了Gibbs採樣對P(v)抽樣出來一大堆小v,然後再蒙特卡洛求均值求解。但問題是Gibbs採樣需要一直轉移到1000次再抽樣才能站的按照p(x)概率分布進行,太慢了,因此就不使用個1000次轉移之後,我們直接從訓練集 S={v^1,v^2,ldots,v^n} 這個v作為出發點(原來直接是隨機的出發點),轉移k次就夠了,而不用等轉移1000次之後。

經過這種方案得到的梯度會以差值的形式展現。具體的數學推到詳見受限玻爾茲曼機(RBM)學習筆記(六)對比散度演算法

參考

GMM-HMM和DNN-HMM 框架圖如何理解

Context-Dependent Pre-Trained Deep Neural Networks for Large-Vocabulary Speech Recognition

Deep Neural Networks in Kaldi

Karels DNN implementation

kaldi中的深度神經網路

受限制玻爾茲曼機RBM原理簡介


推薦閱讀:

重磅!阿里開源自研語音識別模型DFSMN,準確率高達96.04%
想撩外國妹紙,你需要島國推出的這款翻譯神器!
GMM
如何設計一個不討人厭的AI?「恐怖谷」了解一下
AI時代,為什麼懂語音者得天下?

TAG:語音識別 | kaldi |