Kaldi PLDA實現C++程式碼閱讀
阿新 • • 發佈:2018-11-09
PLDA(Probabilistic Linear Discriminant Analysis) 廣泛用於Speaker Verification中,這篇部落格主要記錄一下本人閱讀Kaldi中PLDA底層C++程式碼的過程。Kaldi中PLDA的實現主要參考Sergey Ioffe的這篇paper. 程式碼中有很多有用的comments, 對於理解實現思路非常重要。本人在寫這篇部落格時也參考了A Note on Kaldi’s PLDA Implementation. 這篇總結得很好,在此表示感謝。
- 背景知識
LDA常常用來提取線性特徵, 這種特徵旨在最大化between-class separation以及最小化within-class separation. LDA可以通過給訓練資料擬合一個高斯混合模型得到:用 來表示observable sample,用 來表示the latent variable,則類條件概率可以表示為
其中,
這種混合模型只能表示有限的 類,我們想拓展這個概率模型,讓它能夠model出現在訓練資料中的其他類。為此,我們讓 的先驗成為連續的。為了能夠運算簡單,我們可以讓 的先驗(prior)遵循高斯分佈(因此,本文所討論的是Gaussian PLDA,或者也叫做G-PLDA,對於其他型別的PLDA,例如Heavy-Tail PLDA,請參考相關paper):
在以上的式子中, 表示類內covariance, 表示內間covariance, 。通常來說,我們要求前者是正定的,後者是半正定的。由線性代數的知識可以知道, 和 可以被同時對角化,即我們可以找到一個非奇異矩陣 ,使得
和 可以通過解一個generalized eigenproblem 得到。定義 , 則 , 。我們的模型就變成了
上面的式子非常重要,對於理解程式碼很有幫助。
我們要從訓練資料中估計 和 。值得注意的是, 是所有說話人i-vector 的global mean,因此我們可以先把 計算出來,並從訓練資料中減去。我們仍然用 來表示減去 後的i-vector,它的先驗概率可以表示為:
對於訓練資料中的某一個說話人 ,假設用 來表示他/她的i-vector平均, 表示i-vector的個數,那麼
我們把