Kaldi特征提取之-MFCC

Kaldi特征提取之-MFCC

背景

  • 上一节介绍的FBank特征已经很贴近人耳的响应特性,但是仍有一些不足:FBank特征相邻的特征高度相关(相邻滤波器组有重叠),因此当我们用HMM对音素建模的时候,几乎总需要首先进行倒谱转换,通过这样得到MFCC特征。

提取MFCC特征

  • MFCC特征的提取是在FBank特征的基础上再进行离散余弦变换, 因此前面几步和FBank一样,具体请参考上一节.

    1. 傅里叶变换
    2. 计算能量谱
    3. Mel滤波
    4. 取Log
    5. 离散余弦变换

      • 假设做完取Log之后,我们得到N维的特征向量 Mlog 。离散余弦变换公式如下:
        Ci=2Nj=1Nmjcos(piiN(j0.5)),i[1,M]
        N是取Log之后的特征维度,M 是 DCT(离散余弦变换)之后的特征维度。
      • 关于离散余弦变换,可以用matlab脚本看一下效果。
      • 关于离散余弦的实现。从计算公式可以看出DCT的时间复杂度为O(N*M),如果每次都重新计算DCT table无疑是得不偿失的,Kaldi中的做法是首先根据N和M的值计算出整个table,之后调用blas线性代数库,可以加快计算速度。相比之下,Htk中每次都要重新计算cos函数就显得性能比较低。以下是Htk和Kaldi的代码。
        // Htk implement
        void FBank2MFCC(Vector fbank, Vector c, int n)
        {
           int j,k,numChan;
           float mfnorm,pi_factor,x;
        
           numChan = VectorSize(fbank);
           mfnorm = sqrt(2.0/(float)numChan);
           pi_factor = PI/(float)numChan;
           for (j=1; j<=n; j++)  {
              c[j] = 0.0; x = (float)j * pi_factor;
              for (k=1; k<=numChan; k++)
                 c[j] += fbank[k] * cos(x*(k-0.5));
              c[j] *= mfnorm;
           }        
        }
        
        // Kaldi implement
        template<typename Real> void ComputeDctMatrix(Matrix<Real> *M) {
          //KALDI_ASSERT(M->NumRows() == M->NumCols());
          MatrixIndexT K = M->NumRows();
          MatrixIndexT N = M->NumCols();
        
          KALDI_ASSERT(K > 0);
          KALDI_ASSERT(N > 0);
          Real normalizer = std::sqrt(1.0 / static_cast<Real>(N));  // normalizer for
          // X_0.
          for (MatrixIndexT j = 0; j < N; j++) (*M)(0, j) = normalizer;
          normalizer = std::sqrt(2.0 / static_cast<Real>(N));  // normalizer for other
           // elements.
          for (MatrixIndexT k = 1; k < K; k++)
            for (MatrixIndexT n = 0; n < N; n++)
              (*M)(k, n) = normalizer
                  * std::cos( static_cast<double>(M_PI)/N * (n + 0.5) * k );
        }
        // 底层调用的blas库函数
        void VectorBase<Real>::AddMatVec(const Real alpha,
                                      const MatrixBase<Real> &M,
                                      MatrixTransposeType trans,
                                      const VectorBase<Real> &v,
                                      const Real beta) {
          KALDI_ASSERT((trans == kNoTrans && M.NumCols() == v.dim_ && M.NumRows() == dim_)
                   || (trans == kTrans && M.NumRows() == v.dim_ && M.NumCols() == dim_));
          KALDI_ASSERT(&v != this);
          cblas_Xgemv(trans, M.NumRows(), M.NumCols(), alpha, M.Data(), M.Stride(),
                      v.Data(), 1, beta, data_, 1);
        }
    6. 均值方差归一化(CMVN)

      • 实际情况下,受不同麦克风及音频通道的影响,会导致相同音素的特征差别比较大,通过CMVN可以得到均值为0,方差为1的标准特征。均值方差可以以一段语音为单位计算,但更好的是在一个较大的数据及上进行计算,这样识别效果会更加robustness。Kaldi中计算均值和方差的代码在compute-cmvn-stats.cc, 归一化在apply-cmvn.cc
    7. FBank与MFCC对比

      • 计算量,因为MFCC是在FBank的基础上进行的,所以MFCC的计算量更大
      • 特征区分度,FBank特征相关性较高,MFCC具有更好的判别度,这也是在大多数语音识别论文中用的是MFCC,而不是FBank

资料

  1. wav
  2. mfcc matlab代码
  3. dct matlab代码

参考

  1. Kaldi
  2. htkbook 3.4.1 Chapter 5.6
  3. CMVN
  4. Fbank
  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值