1. 程式人生 > >Kaldi thchs30手札(七) DNN-HMM模型的訓練

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

本部分是對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)最大的句子:

W=argmaxWP(W|O)=argmaxWp(O|W)P(W)/P(W)=argmaxWp(O|W)P(W)

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

p(o|w)=qp(o,q|w)p(q|w
)maxπ(q0)t=1Taqt1qtt=1Tp(ot|qt)

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

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

p(ot|qt)=p(qt|ot)p(ot)/p(qt)

其中p(ot)不變, p(qt) 是關於狀態的先驗概率,這個概率也是訓練過程中訓練出來的(就是把觀測值(特徵向量)網狀態上對齊,跟某個狀態對齊的觀測值的個數佔比就是這個狀態的先驗概率)。這樣我們就可以對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(qt)的值。

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目標。

    • sMBR的目標是最大化從參考的對齊中得到的狀態標籤的期望正確率,然而一個詞圖框架是來使用表示這種競爭假設。
    • 訓練是使用每句迭代的隨機梯度下降法,我們還使用一個低的固定的學習率1e-5 (sigmoids)和跑3-5輪。
    • 當在第一輪迭後重新生成詞圖,我們觀察到快速收斂。我們支援MMI, BMMI, MPE 和sMBR訓練。所有的技術在Switchboard 100h集上是相同的,僅僅在sMBR好一點點。

個人補充

限制玻爾茲曼機(RBM)

玻爾茲曼機(Boltzmann Machines, BM)

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

如上圖所示,對於有n個節點的無向圖,由於每個節點是二值的,所以一共有2n個狀態,對於一個節點