语音识别入门知识总结

395 阅读17分钟

语音识别入门


  • 语音识别步骤

    • 语音输入
      • 得到音频信号
    • 音频信号特征提取
      • 对音频信号预处理,再进行特征提取(MFCC)
    • 声学模型处理
      • 将语音的声学特征分类对应到音素或者字词单元。
    • 语言模型处理
      • 使用语言模型将所得到的字词解码成一个完整的句子,得到语音识别结果。
  • MFCC(Mel-scaleFrequency Cepstral Coefficient,梅尔倒谱系数)

    • 先将线性频谱映射到基于听觉感知的Mel非线性频谱中,然后转换到倒谱上。
      • 在Mel频域内,人对音调的感知度为线性关系
    • 1.预处理
      • 1.预加重
        • 将语音信号通过一个高通滤波器。
        • 目的
          • 目的是为了对语音的高频部分进行加重,去除口唇辐射的影响,增加语音的高频分辨率。
          • 弥补了高频部分的损耗,保护了声道信息
      • 2.分帧
        • 将N个采样点集合成一个观测单位,称为帧。
        • 两相邻帧之间会有一段重叠区域。
      • 3.加窗(Hamming Window)
      • 将每一帧乘以汉明窗,以增加帧左端和右端的连续性。
        • 分帧后在起始和结束会出现不连续情况(吉布斯效应),那样这个信号在分帧之后,就会越来越背离原始信号 。加窗是为了减少帧起始和结束的地方信号的不连续性问题
      • 加窗之后,原本没有周期性的语音信号呈现出周期函数的部分特征。
    • 2.FFT(Fast Fourier Transform,快速傅里叶变换)
      • 将语音信号由时域转换为频域。
    • 3.谱线能量
      • 对语音信号的频谱取模平方得到语音信号的谱线能量。
    • 4.计算通过Mel滤波器的能量
      • 目的
        • 对频谱进行平滑化,并消除谐波的作用,突显原先语音的共振峰。
          • 以 MFCC 为特征的语音辨识系统,并不会受到输入语音的音调不同而有所影响。
        • 降低运算量。
    • 5.计算DCT倒谱
  • 频谱包络

    • 频谱包络是将不同频率的振幅最高点连结起来形成的曲线。
    • 声道的形状在语音短时功率谱的包络中显示出来。
    • 原始的频谱由两部分组成:包络和频谱的细节。
      • 包络是低频信号,通过一个低通滤波器就可以得到包络。
      • 频谱的细节是高频信号。
  • 共振峰

    • 共振峰是指在声音的频谱中能量相对集中的一些区域。
    • 共振峰就是携带了声音的辨识属性,以识别不同的声音。
  • 倒谱

    • 倒谱(cepstrum)就是一种信号的傅里叶变换经对数运算后再进行傅里叶反变换得到的谱。
  • 特征

    • delta特征

      • Delta特征对mfcc特征(13维)做一阶二阶差分得到的39维的特征。
    • LDA+MLLT特征

      • 对MFCC特征进行扩帧,使用LDA降维(默认降低到40),然后经过多次迭代轮数估计一个对角变换(又称为MLLT或CTC)。
  • 强制对齐

    • 声学模型训练需要对齐结果,而对齐过程又需要声学模型。
      • kaldi采用简单粗暴的首次对齐策略:
        • 直接将训练样本按照该句子的HMM状态数平均分段,认为每段对应的状态。
    • 对齐过程
      • 根据语音帧和已有的声学模型,选取状态图中的一条最优路径将各语音帧匹配到状态图上。
      • 相当于语音识别,但是解码路径被限制在直线状态图上。
  • kaldi识别过程

    • 首先提取特征,然后过声学模型AM,然后过解码网络HCLG.fst,最后输出识别结果。
  • HCLG.fst解码网络结构

    • H(HMM).fst
      • HMM模型
      • 输入为senone状态
      • 输出为context-dependent phone
    • C(context).fst
      • 上下文环境
      • 输入:triphone(上下文相关)(context-dependent phones)
      • 输出: monophnoe
      • Kaldi中,单独的C.fst是不存在的。
        • L和G合并生成LG.fst,然后在其基础上,根据决策树的结果,直接生成CLG.fst。
    • L(lexicon).fst
      • 词典
      • 输入: monophone(phone序列)
      • 输出: 词
    • G(grammar).fst
      • 语言模型
      • 输入输出类型相同,均为词
      • 实际是一个WFSA(acceptor接受机),为了方便与其它三个WFST进行操作,将其视为一个输入输出相同的WFST。

HCLG = asl(min(rds(det(H' o min(det(C o min(det(L o G))))))))

  • o表示组合,det表示确定化,min表示最小化,rds表示去除消岐符号,asl表示增加自环。

  • HCLG训练顺序为 G -> L -> C -> H

    • G 语法模型基于统计生成,L 则是在 G 生成过程中使用的基础,而 C 则是基于 L 生成的 phone 上下文关系依据决策树生成的结果。
  • kaldi中记录数据的格式

    • archive
      • archive包含实际的数据(text-only(t) or binary)。
      • ark:
        • ark前缀告诉kaldi是archive文件。
        • kaldi 不会自己判断这到底是个 script 还是 archive 形式。
    • script file
      • script file存储数据的地址,指向archive文件的位置。
      • scp:
        • scp前缀告诉kaldi是script文件(text-only)。
  • embeding的作用

    • 对输入特征进行升维/降维,得到一个固定特征表示。
    • 训练方法(无监督学习)
      • 输入到embeding的映射为f:x>yf:x->y,y是嵌入向量,假设有标注(x,z),用数据(xix_i,ziz_i)训练任务k:x>zk:x->z,可被表示为z=g(f(x)),f:x>y,g:y>zz=g(f(x)), f:x->y, g:y->z。训练完成后只截取网络的前面部分作为f:x>yf:x->y,学习到embeding。
  • kaldi基于决策树的状态绑定

    • 1.生成问题集

      • 1.对每个句子进行维特比强制对齐
      • 2.得到统计量:EventType的出现次数count_,特征向量的均值和均值的平方。
      • 3.构造问题集
        • 将得到的所有音素及其统计量放到树的根节点。
        • 根据公式公式得到最大似然提升对应的划分,对节点进行分裂。
        • 不断地递归进行节点分裂,直到所有的划分所带来的似然度提升都小于某个阈值。
        • 除根节点以外的所有节点都看做是问题集。
    • 2.构建决策树

      • 1.读取roots文件
      [shared | not-shared] [ split | not-split    ] phoneme number
      
      shared or not-shared 表示对一个音素的3(或5)个hmm state分别建立3颗不同的决策树,还是一个音素所有hmm state共享一颗决策树树根。
      
      split or not-split 表示是否需要对该音素对应的决策树进行分裂,如果不进行分裂,该决策树就只有一个树根。
      
      • 2.建立决策树
        • 从问题集中选择对决策树似然度提升的问题对决策树进行提问,根据提问结果进行节点分裂。
        • 构建完决策树后,还会将两两空间距离较近(如欧式距离)的叶子结点绑定在一起。
    • 状态绑定牵涉到两次决策树的简历。

      • 第一次是为了得到问题集而建立的决策树
        • 通过将所有音素作为决策树根节点,然后计算对音素集进行划分带来的似然度提升,不断对结点进行分裂,进而得到一系列问题集。
      • 第二次是进行状态绑定
        • 对所有中间音素以及hmm state相同的EventType,我们从第一步得到的问题集中选出对似然度提升最大的问题,对建立一颗决策树。然后比较所有叶子结点,把两两空间距离较近(如欧式距离)的叶子结点绑定在一起,有共同的pdf-id(混合高斯函数)。
  • 区分性训练

    • 一般声学模型的训练(ML,Maximum Likelihood,最大似然)是最大化p(O|W)的概率,而区分性训练(MMI,Maximum Mutual Information, 最大互信息)直接最大化P(W|O)的概率。(语音观测序列O,词序列W)

    θML=argmaxPθ(OW)=argmaxlogPθ(OuWu)\theta_{ML}=argmaxP_\theta(O|W)=argmax\sum{\log{P_\theta(O_u|W_u)}}

    θMMI=argmaxPθ(WO)=argmaxlogPθ(WuOu)=argmaxlogPθ(OuWu)P(Wu)P(Ou)=argmaxlogPθ(OuWu)P(Wu)Pθ(OuW)P(W)\theta_{MMI}=argmaxP_\theta(W|O)=argmax\sum{\log{P_\theta(W_u|O_u)}}=argmax\sum{\log\frac{P_\theta(O_u|W_u)P(W_u)}{P(O_u)}}=argmax\sum{\log\frac{P_\theta(O_u|W_u)P(W_u)}{\sum{P_\theta(O_u|W)P(W)}}}

    • ML目标函数仅与正确的标注有关系。
    • MMI目标函数不仅与正确的标注(分子)有关系,还与其他的所有可能的W序列(分母)有关系。不仅与声学模型有关系,还与语言模型P(W)有关系。
      • 因为MMI中的分母实际上是无穷的,使用对应语音识别解码的Lattice近似W。
        • 所以需要在区分性训练之前训练一个DNN模型进行解码生成lattice。
        • Lattice是一个解码过程,其生成代价很高,并且只能在CPU上进行解码生成。
        • 一般只生成一次Lattice,区分性训练的过程中并不根据当前更新后的声学模型实时生成Lattice,也就是不使用实时的Lattice做MMI训练。所以Lattice是滞后的,和当前的声学模型并不同步。
  • LF-MMI(Lattice-Free Maximum Mutual Information)

    • 将W表示为一个和语音识别解码时类似的语言模型G,并为MMI分母构建一个类似HCLG的解码图,则该解码图中组合了MMI中的声学模型和语言模型的信息。无需生成lattice。
      • 以单音素Phone作为语言模型单元。
        • 识别系统中Phone的一般在几十个到一百多个,考虑到数据稀疏性,即使做tri-gram或者4-gram复杂度也在合理区间内。
        • 以Phone作为建模单元时,MMI的分母图为HCG(没有词典L了,并且G的单元是Phone)。
      • State作为语言模型建模单元。
        • 识别系统中的State一般在几千个左右,考虑到数据稀疏性,做tri-gram复杂度也在合理区间内。
        • 以State作为建模单元时,MMI的分母图为G(G以State作为建模单元,这里State是指上下文相关的CD-State/senone)。
    • 合理的控制Phone和State的MMI分母的大小,可以将其前向后向计算塞进GPU进行计算,也就是将MMI训练迁移到GPU,从而大大提高了MMI的训练速度。
  • Kaldi chain model

    • Kaldi中的chain model是kaldi中关于LF-MMI的一种实现
      • HMM拓扑结构改变,从标准的三状态改为单状态的HMM。
      • 帧率从10ms降低到30ms。
      • MMI分母使用Phone作为语言模型建模单元,最终表示为HCG,且为简化,C为bi-phone。
      • 训练数据均做等长(1.5s)切分,分子使用该句话的Lattice表示。且在分子Lattice上引入一定时间扰动。
      • CE正则化。训练时同时引入CE作为第二个任务进行multi task learning。
      • L2正则化/Leaky HMM等。
  • 解码器

    • 静态图

      • 解码时,解码器直接使用已经构建好的HCLG,该HCLG已经全部展开。
      • 缺点
        • 静态图HCLG自身占用空间大,难以使用大的语言模型,其在解码运行过程中占用内存也大,难以在移动端直接使用HCLG。
        • 静态图HCLG构建过程速度慢,消耗内存高。
    • 动态图

      • 把HCLG分开成HCL和G,构图时分别构建HCL和G。在解码时,分别加载HCL和G,然后根据解码动态的对HCL和G进行按需动态Compose,而无需完全Compose展开。
        • 分别构建的HCL和G因为不是完全展开的图,这两个图的大小远比其展开的静态图HCLG小,这样就节省了空间。
        • 无需再进行HCL和G的Compose这一过程,而这一步恰恰是静态图HCLG构建过程中最为耗时的一步,所以又节省了构图时间。
      • 缺点
        • 动态图加大了解码时的计算量,解码速度会降低。
    • Rescoring

      • 在构建时使用小的LM1构建G1,使用G1构建静态图HCLG1,然后使用小的LM1和大的LM2构建G2(G2中LM的weight为LM2的weight减去LM1的weight)。解码:
        • 常规Rescoring
          • 利用HCLG1先全部解码,生成lattice或者nbest,然后在G2上做lattice和nbest的Rescoring。
        • on-the-fly Rescoring
          • 使用HCLG1做解码,在解码过程中,每当解码出word时,立即再加上G2中的LM weight。
  • kaldi中pdf-id,transition-id等

    • Phone:音素,编号从1开始的整数。
    • HMM-state:HMM里隐藏的状态。每个音素的HMM-state编号都是从0开始的整数。
    • pdf-id:每个state相对应的GMM概率密度函数(pdf: probability density function)的id,编号是全局唯一,从0开始的整数。
    • transition-state:表示一个转移状态。
    • transition-index:表示一个状态的转移路径的index,在每个状态内从0开始的整数。
    • transition-id:所有状态转移路径的id,全局唯一,从1开始的整数。跟(transition-state, transition-index)一一对应。
  • WFST(Weighted Finite-State Transducer,加权有穷状态机)

    • 合并操作
      • 合并操作用于将两个相同层次的WFST合并成,将它们合并到一个WFST。
      • 相当于求并集。
    • 组合操作
      • 组合操作用于合并不同层次的WFST,用于将前一个WFST的输出符号同后一个WFST的输入符号做合并,生成由前一个WFST的输入符号到后一个WFST输出符号的状态机。
    • 确定化操作
      • 确定化操作用于去除WFST的冗余,对于WFST的每一个状态,它的每一个状态对于同一个输入符号,只有一个转移弧。
      • 对于确定化的加权有限状态器,一个给定的输入符号序列最多只有一条路径与其对应,这样可以降低搜索算法的时间和空间复杂度。
    • 权重推移
      • 权重前推操作将转移弧的权重都向加权有限状态器的初始状态推移。
      • 这样在采用搜索算法去找到最大或者最小路径时,可以在早期就丢弃一些不可能的路径,提高搜索的效率。
    • 最小化操作
      • 最小化操作让WFST中的状态数最少。
  • 3gram语言模型

    • 为了避免数据溢出、提高性能,计算概率时通常会使用取log后使用加法运算替代乘法运算。
    • 数据稀疏是测试集中很多语言在训练语料中未出现,会导致很多参数(某n元对的概率)为0。
    • 使用数据平滑(Data Smoothing)技术来解决数据稀疏。
      • 加法平滑
        • 基本思想是为避免零概率问题,将每个n元对得出现次数加上一个常数δ\delta
        • P(WiWin+1...Wi1)=C(Win+1...Wi1Wi)+δC(Win+1...Wi1)+NδP(W_i|W_{i-n+1}...W_{i-1})=\frac{C(W_{i-n+1}...W_{i-1}W_i)+\delta}{C(W_{i-n+1}...W_{i-1})+N\delta}
          • C(Win+1...Wi1)C(W_{i-n+1}...W_{i-1})是文本Win+1...Wi1W_{i-n+1}...W_{i-1}出现的次数。
      • Good-Turing Smoothing
        • 利用频率的类别信息来对频率进行平滑。
        • PGT(WiWin+1...Wi1)=CGT(Win+1...Wi1Wi)C(Win+1...Wi1)P_{GT}(W_i|W_{i-n+1}...W_{i-1})=\frac{C_{GT}(W_{i-n+1}...W_{i-1}W_i)}{C(W_{i-n+1}...W_{i-1})}
          • CGT(Win+1...Wi1Wi)=(C(Win+1...Wi1Wi)+1)N(C(Win+1...Wi1Wi)+1)N(C(Win+1...Wi1Wi))C_{GT}(W_{i-n+1}...W_{i-1}W_i)=(C(W_{i-n+1}...W_{i-1}W_i)+1)*\frac{N(C(W_{i-n+1}...W_{i-1}W_i)+1)}{N(C(W_{i-n+1}...W_{i-1}W_i))}
          • N(c)N(c)是频率为c的n-gram的数量。
        • 利用出现次数较多的N阶元组去调整出现比他少的N阶元组的估计量。
          • r=(r+1)Nr+1Nrr^*=(r+1)\frac{N_{r+1}}{N_{r}}
            • NrN_{r}是发生次数为r的元组个数,r是文本发生次数。
              • r=C(Win+1...Wi1Wi)r=C(W_{i-n+1}...W_{i-1}W_i)
            • CGT(Win+1...Wi1Wi)=(C(Win+1...Wi1Wi)+1)N(C(Win+1...Wi1Wi)+1)N(C(Win+1...Wi1Wi))=(r+1)Nr+1NrC_{GT}(W_{i-n+1}...W_{i-1}W_i)=(C(W_{i-n+1}...W_{i-1}W_i)+1)*\frac{N(C(W_{i-n+1}...W_{i-1}W_i)+1)}{N(C(W_{i-n+1}...W_{i-1}W_i))}=(r+1)\frac{N_{r+1}}{N_r}
        • 缺点
          • 当单词出现次数慢慢增大时,有些频率r的n-gram并未出现,而每一个P(r)的计算都依赖于r+1。
            • 解决方法是通过线性回归之类的方法,平滑的推断不存在r值的对应count值,带入公式重新计算。
      • 线性插值平滑
        • 利用低元n-gram模型对高元n-gram模型进行线性插值。
          • 因为在没有足够的数据对高元n-gram模型进行概率估计时,低元n-gram模型通常可以提供有用的信息。
        • Pinterp(WiWin+1...Wi1)=λnPMLE(WiWin+1...Wi1)+(1λn)PMLE(WiWin+2...Wi1P_{interp}(W_i|W_{i-n+1}...W_{i-1})=\lambda_n*P_{MLE}(W_i|W_{i-n+1}...W_{i-1})+(1-\lambda_n)*P_{MLE}(W_i|W_{i-n+2}...W_{i-1}
          • λn\lambda_n通过EM算法来估计。
      • Katz平滑(回退(back-off)平滑)
        • 基本思想是当一个n元对的出现次数足够大时,用最大似然估计方法估计其概率。
        • 当n元对的出现次数不够大时,采用Good-Turing估计对其平滑,将其部分概率折扣给未出现的n元对。
        • 当n元对的出现次数为0时,模型回退到低元模型。
  • GMM-UBM

    • 使用大量非目标用户数据(背景数据)混合起来充分训练出一个GMM,这个GMM可以看作是对语音的表征,但是又由于它是从大量身份的混杂数据中训练而成,它又不具备表征具体身份的能力。将这种模型看作是某一个具体说话人模型的先验模型。这个GMM对语音特征在空间分布的概率模型给出一个良好的预先估计。
    • 然后将目标用户的数据在这个模型上进行参数的微调即可。
      • 通过MAP算法对模型参数进行估计,避免了过拟合的发生,同时不必调整目标用户GMM的所有参数(权重,均值,方差),只需要对各个高斯成分的均值参数进行估计,就能实现最好的识别性能。
      • MAP自适应算法
        • 首先,使用目标说话人的训练数据计算出UBM模型的新参数(高斯权重、均值和方差)。
        • 将得到的新参数与UBM模型的原参数进行融合,从而得到目标说话人的模型。
  • 词格(lattice)

    • 权重(图固有分和声学分)
      • 语言分和HMM转移概率,多音字中特定发音概率混在一起构成图固有分。
        • 而语言模型重打分调整的只是语音分。
  • 重打分策略(语言模型过大)

    • 使用较小的语言模型来构建G.fst,进而构造HCLG。使用这个HCLG解码后,对得到词格lattice的语言模型使用较大的语音模型G.fst进行修正。
    • 使用apra-to-const-arpa工具将APRA文件转换成CONST APRA。之后就可以使用lattice-lmrescore-const-arpa工具进行重打分。
      • CONST APRA是树型结构,可以快速查找到某一个单词的语言分,而无需构建庞大的WFST。
  • beam search 和viterbi对比

    • beam search柱搜索
      • 基于贪心算法思想。
        • 每步只保留top-k结果。
      • 可以看做一种宽度(或者说是广度)优先图搜索。因为每一步预测候选集(词表大小是10万量级)很大,所以将概率较低的分支删除,即剪枝。这样大大缩小了搜索空间,所以其得到的是近似解,不是全局最优解。是一种启发式算法。
      • 常用于搜索空间非常大的情况,如语言生成任务,每一步是选择一个词,而词表非常大,在十万量级,beam search可以大大减少计算量。
    • viterbi维特比
      • viterbi是基于动态规划思想。
        • 计算到当前节点的最短路径(最大概率路径)。
      • 每一步是根据上一步全部可能选择的最高概率推测当前所有可能选择的最高概率,保证有全局最优解
      • 适合于搜索宽度较小的图寻找最优路径,即每一步的选择比较少的时候。如在CRF、HMM中使用。
  • 困惑度(perplexity)

    • 困惑度是衡量语言模型好坏的指标,是一个句子的概率的倒数的N方根。
      • PP(W)=P(W1W2...Wn)1N=1P(W1W2...Wn)NPP(W)={P(W_1W_2...W_n)}^{-\frac{1}{N}}=\sqrt[N]{\frac{1}{P(W_1W_2...W_n)}}
      • 一个句子出现的概率P(W1W2...Wn)P(W_1W_2...W_n)越大,则困惑度PP(W)PP(W) 越小,说明语言模型预测的越好。
        • 困惑度在语言模型中的物理意义可以描述为对于任意给定序列,下一个候选词的可选范围大小。
        • 困惑度越小,说明所建模的语言模型越精确。
    • 句子的平均交叉熵为H(W)=1NlogP(W1W2...Wn)H(W)=-\frac{1}{N}\log{P(W_1W_2...W_n)},描述的是样本的平均编码长度,困惑度PP(W)=2H(W)=P(W1W2...Wn)1N=1P(W1W2...Wn)NPP(W)=2^H(W)={P(W_1W_2...W_n)}^{-\frac{1}{N}}=\sqrt[N]{\frac{1}{P(W_1W_2...W_n)}}