1. 程式人生 > >Kaldi PLDA實現C++程式碼閱讀

Kaldi PLDA實現C++程式碼閱讀

PLDA(Probabilistic Linear Discriminant Analysis) 廣泛用於Speaker Verification中,這篇部落格主要記錄一下本人閱讀Kaldi中PLDA底層C++程式碼的過程。Kaldi中PLDA的實現主要參考Sergey Ioffe的這篇paper. 程式碼中有很多有用的comments, 對於理解實現思路非常重要。本人在寫這篇部落格時也參考了A Note on Kaldi’s PLDA Implementation. 這篇總結得很好,在此表示感謝。


  1. 背景知識
    LDA常常用來提取線性特徵, 這種特徵旨在最大化between-class separation以及最小化within-class separation. LDA可以通過給訓練資料擬合一個高斯混合模型得到:用 x
    \bold x
    來表示observable sample,用 y y 來表示the latent variable,則類條件概率可以表示為
    P (
    x y ) = N ( x
    y , Φ w ) P(\bold x | \bold y) = \mathcal{N}(\bold x| \bold y, \Phi_w)

    其中,
    P ( y ) = k = 1 K π k δ ( y μ k ) P(\bold y) = \sum_{k=1}^K \pi_k\delta(\bold y - \mu_k)
    這種混合模型只能表示有限的 K K 類,我們想拓展這個概率模型,讓它能夠model出現在訓練資料中的其他類。為此,我們讓 y \bold y 的先驗成為連續的。為了能夠運算簡單,我們可以讓 y \bold y 的先驗(prior)遵循高斯分佈(因此,本文所討論的是Gaussian PLDA,或者也叫做G-PLDA,對於其他型別的PLDA,例如Heavy-Tail PLDA,請參考相關paper):
    P ( y ) = N ( y m , Φ b ) P(\bold y) = \mathcal{N}(\bold y|\bold m, \Phi_b)
    在以上的式子中, Φ w \Phi_w 表示類內covariance, Φ b \Phi_b 表示內間covariance, m = 1 N k = 1 K i = 1 n k z k i \bold m = \frac{1}{N}\sum_{k=1}^{K}\sum_{i=1}^{n_k}z_{ki} 。通常來說,我們要求前者是正定的,後者是半正定的。由線性代數的知識可以知道, Φ w \Phi_w Φ b \Phi_b 可以被同時對角化,即我們可以找到一個非奇異矩陣 V V ,使得
    V T Φ w V = I V T Φ b V = Ψ V^T\Phi_wV=I \\ V^T\Phi_bV = \Psi
    Ψ \Psi V V 可以通過解一個generalized eigenproblem 得到。定義 A = V T A=V^{-T} , 則 Φ w = A A T \Phi_w=AA^T , Φ b = A Ψ A T \Phi_b=A\Psi A^T 。我們的模型就變成了
    x = m + A u , u N ( v , I ) , v N ( 0 , Ψ ) \bold x = \bold m + A\bold u, \\ 其中, \bold u \sim \mathcal{N}(\cdot | \bold v, \bold I), \\ \bold v \sim \mathcal{N}(\cdot |0, \Psi)
    上面的式子非常重要,對於理解程式碼很有幫助。
    我們要從訓練資料中估計 Φ w \Phi_w Φ b \Phi_b 。值得注意的是, m \bold m 是所有說話人i-vector 的global mean,因此我們可以先把 m \bold m 計算出來,並從訓練資料中減去。我們仍然用 z z 來表示減去 m \bold m 後的i-vector,它的先驗概率可以表示為:
    p ( z ) = N ( 0 , Φ b + Φ w ) p(z) = \mathcal{N}(0, \Phi_b + \Phi_w)
    對於訓練資料中的某一個說話人 k k ,假設用 m k m_k 來表示他/她的i-vector平均, n k n_k 表示i-vector的個數,那麼
    m k = 1 n k i = 1 n k z i N ( 0 , Φ b + Φ w n k ) m_k = \frac{1}{n_k}\sum_{i=1}^{n_k}z_i \sim \mathcal{N}(0, \Phi_b+\frac{\Phi_w}{n_k})
    我們把 m k , k = 1 ,   , K m_k, k =1,\cdots , K