Kaldi中的GMM模型

这部分主要记录的是GMM在kaldi中的实现。

Kaldi中关于高斯混合模型的表示,更新,主要用到下面这四个类,之间的关系如下:

具体表述为:

  1. DiagGMM表示一个GMM模型,AmDiagGMM存储了一个GMM声学模型中的所有GMM,也就是pdf
  2. AccumDiagGmm用来对一个GMM模型进行参数更新,AccumAmDiagGmm中存储了一个AccumDiagGmm向量,可以对整个声学模型进行更新

下面一个一个说明

DiagGMM

对于一个GMM模型,pdf可以表示为

对其中一个GMM分量,我们取log可以得到:

对于原先的指数部分,展开:

DiagGMM中gconst_weights_inv_vars_means_invvars_依次存放的值如下:

在给定$\boldsymbol{x}$时,计算一个分量的loglikelihood由下式给出

由此看来,DiagGMM的作用就是表示一个最基本的GMM模型,给出一个观测,可以给出一个各个GMM分量观测概率(比如在函数LogLikelihoods的作用,可以得到一个观测的后验向量)。对于这单个GMM模型的更新,需要记录EM算法中的一些过程量,这个依靠AccumDiagGmm完成。

AccumDiagGmm

结合EM算法,要更新GMM模型中的$(c_m, \mu_m, \varSigma_m)$,必须首先得到隐变量在完全数据下的期望$E_{H_n^m}$:

${P_m} \to {P_m / P}$的映射由函数ApplySoftMax完成,该函数如下

1
2
3
4
5
6
7
8
9
template<typename Real>
Real VectorBase<Real>::ApplySoftMax() {
Real max = this->Max(), sum = 0.0;
for (MatrixIndexT i = 0; i < dim_; i++) {
sum += (data_[i] = Exp(data_[i] - max));
}
this->Scale(1.0 / sum);
return max + Log(sum);
}

这个函数的功能如下:

由于实际参与运算的${P_m}$实际上都是取过log的,所以,ApplySoftMax完成了${P_m} \to {P_m / P}$映射功能,表示如下:

下面把AccumDiagGmm中的三个变量和EM算法中的更新参数结合起来

1
2
3
Vector<double> occupancy_;
Matrix<double> mean_accumulator_;
Matrix<double> variance_accumulator_;

以上三个变量的对应关系如下:

以上过程量$\mathcal{O}, \mathcal{M}, \mathcal{V} $在gmm-acc-stats-ali中完成积累,在gmm-est中完成更新。
结合EM算法中更新公式,可以得到:

kaldi中这部分还进行了GMM高斯数的自动调整,即merge和split操作。