1. 程式人生 > >Kaldi thchs30手札(六)說話人自適應訓練(SAT)、FMLLR以及quick訓練(line 87-104)

Kaldi thchs30手札(六)說話人自適應訓練(SAT)、FMLLR以及quick訓練(line 87-104)

本部分是對Kaldi thchs30 中run.sh的程式碼的line 87-104 行研究和知識總結,內容涵蓋說話人自適應訓練(Speaker Adaptive Training,SAT)以及特徵空間最大似然線性迴歸(Feature-space Maximum Likelihood Linear Regression, FMLLR)以及quick訓練。

概覽

首先放程式碼:

#sat
steps/train_sat.sh --cmd "$train_cmd" 2500 15000 data/mfcc/train data/lang exp/tri2b_ali exp/tri3b || exit 1
; #test tri3b model local/thchs-30_decode.sh --nj $n "steps/decode_fmllr.sh" exp/tri3b data/mfcc & #sat_ali steps/align_fmllr.sh --nj $n --cmd "$train_cmd" data/mfcc/train data/lang exp/tri3b exp/tri3b_ali || exit 1; #上面的部分以說話人適應訓練為主。 #quick訓練 #quick steps/train_quick.sh --cmd "$train_cmd" 4200 40000 data/mfcc/train data/lang exp
/tri3b_ali exp/tri4b || exit 1; #test tri4b model local/thchs-30_decode.sh --nj $n "steps/decode_fmllr.sh" exp/tri4b data/mfcc & #quick_ali steps/align_fmllr.sh --nj $n --cmd "$train_cmd" data/mfcc/train data/lang exp
/tri4b exp/tri4b_ali || exit 1; #quick_ali_cv steps/align_fmllr.sh --nj $n --cmd "$train_cmd" data/mfcc/dev data/lang exp/tri4b exp/tri4b_ali_cv || exit 1;

七行程式碼。第一行是對特徵進行FMLLR,而後訓練GMM模型。第二行是對自適應模型的解碼及測試。第三行是根據FMLLR模型對資料進行對齊可以看出核心任務是對特徵碼本做FMLLR以達到說話人自適應的目的。第四行進行quick訓練。第五行對quick訓練得到的模型進行解碼測試。第六行採用quick訓練得到的模型對資料進行對齊。第七行是對開發資料集進行對齊。

以下對說話人自適應訓練和FMLLR以及quick訓練做詳細介紹。

SAT

所謂說話人自適應技術是利用特定說話人資料對說話人無關(Speaker Independent,SI)的碼本進行改造,其目的是得到說話人自適應(SPeaker Adapted, SA)的碼本來提升識別效能。我們知道在某個說話人的訓練資料足夠多的時候,針對當前說話人資料採用傳統的訓練方法可以得到×說話人相關(Speaker Dependent, SD)的碼本,由於SD碼本很好的反應了當前說話人的特徵,因此效果往往更好,但實際中往往缺少足夠的資料,因此採用說話人自適應,這樣我們只需要很少量的資料就可以得到比較大的效能提升。其實質是利用自適應資料調整SI碼本以符合當前說話人特性

由於傳統訓練方法得到的 SI 碼本不可避免地受訓練集特性的影響, 在訓練集和自適應資料失配時這會導致自適應效果變得不明顯, 原始碼本越具有說話人無關性, 在自適應時就越能迅速地趨近當前說話人的特徵。與自適應相結合的碼本訓練對 SI 碼本、訓練集內每個說話人特性分別建立模型, 因此可以得到更具說話人無關性的 SI 碼本。

FMLLR

Kaldi上對其的定義是”Constrained Maximum Likelihood Linear Regression (CMLLR), also known as feature-space MLLR (fMLLR), is an affine feature transform of the formxAx+b”,關於Kaldi中使用的CMLLR的詳細解釋可以看論文”Maximum likelihood linear transformations for HMM-based speech recognition”。

我對FMLLR的理解是:針對特定的說話人,其碼本可以用SI碼本經過線性變換後的SA碼本表示,即SA碼本中的任意均值向量可以表示為:

x=Ax+b

其中x表示N維SI碼本的均值向量,A為N×N的線性變換矩陣,b表示偏移量,不同的均值向量可以有不同的變換矩陣A。fMLLR碼本自適應的目的就是估算變換矩陣A從而更新SA碼本。

那這個矩陣怎麼得到呢?我們可以將其作為引數,使用引數估計的方法得到。

假設有K個說話人的訓練資料,每個說話人的SA碼本均由SI碼本線性變換得到,訓練的目標是使得輸出概率函式最大,即:

(A,λ)=argmaxk=1KtO(k)P(o(t)|λAk)=argminf(x,Σ,A) f(x,Σ,A)=k=1KtO(k)log[P(o(t)|λAk]

式中λ表示SI碼本的引數集合(均值和方差),Ak表示第k個說話人的變換矩陣,AK=[bk,Uk]Ok表示第k個說話人的訓練資料集合,W,λ表示引數的最佳估計。

從碼本包含資訊的角度分析, 語音訊號總是包含兩部分的內容: 說話人資訊( 這裡指廣義的說話人資訊, 也包括環境變化造成的特徵的不確定性) 和語意資訊, 這可以看作兩個相對獨立的座標軸。在訓練說話人無關碼本時希望碼本儘量只與語意相關, 傳統的訓練方法對所有資料作平均, 這實際隱含著訓練集中說話人資訊部分可相互抵消的假設; 而自適應訓練的做法是: 對每個說話人分別估計說話人資訊, 期望在此基礎上能夠真正得到說話人無關碼本, 對兩部分的估計是同時進行的, 對訓練集的要求相對較低。

引數估計

引數估計的目標是更新碼本的均值、方差和每個說話人的線性變換矩陣以使得輸出概率最大,由於多個優化引數的存在,需要分別實現引數更新。

  1. 初始時給定SI碼本,轉換矩陣A為單位矩陣。

  2. 更新說話人變換矩陣,首先根據SI碼本和當前說話人矩陣A得到SA碼本,依照SA碼本對每個說話人訓練資料做Viterbi分割,分割的結果是將每一幀分別歸到某一個高斯分佈,然後按照分割結果更新每個人的變換矩陣。

  3. 更新SI碼本均值。把已經更新的變換矩陣A帶入目標函式求解SI碼本均值。

  4. 更新SI碼本方差。利用更新後的說話人變換矩陣A和SI碼本均值帶入目標函式可以求解SI碼本的方差。

  5. 判斷統計量是否收斂,若不收斂重複2-4步進行迭代。

程式碼流程為:

check_phones_compatible.sh->ali-to-post->acc-tree-stats->sum-tree-stats->cluster-phones->compile-questions->build-tree->gmm-init-model->gmm-mixup->convert-ali->compile-train-graphs->{gmm-align-compiled->(ali-to-post->)gmm-acc-stats-ali->gmm-est}35->ali-to-post->gmm-est->analyze_alignments.sh

quick訓練

關於該部分在網上幾乎找不到相關的說明,因此此處為防止我的理解有偏差,我主要以程式碼中的描述為主,把它整理出來,再加以少量的自己理解。

在程式碼的註釋中,它對自身的描述是在一個已經存在的特徵的基礎上訓練模型。該指令碼的模型初始化(即GMM模型)是基於之前模型的基礎上的。具體實現思想是:對於當前模型的每個狀態(構建完樹後),它把舊模型中與其相近的狀態直接克隆過來,評判是否相近的標準就是看它們樹統計量的重疊數目相似度。

在程式碼上來說,模型初始化都是:

gmm-init-model tree treeacc topo 1.mdl

現在使用舊模型初始化的話:

gmm-init-model tree treeacc topo 1.mdl prev/tree prev/30.mdl

由於這種初始化後的高斯數量可能比我們想要的多或者少,因此我們需要在mixing-down或mixing-up目標高斯函式。

除此之外的流程和正常的訓練相似。也是強制對齊,累積統計量,更新引數等操作。

絮叨

到這裡經典的部分就結束了,之後就是DNN的部分了,前面都算是對它做的準備。但其最多也就是三講的內容。然後就要轉投深度學習了。。。雖然俗了點,畢竟效果確實好一些,而且要的資源少,希望深度學習有一天也能像以前的演算法一樣具備可解釋性和數學上的美感。

參考