目前在语音识别领域,有哪些常用的算法?
语音识别也和图像处理一样,有传统的语音识别算法和基于DeepLearning的语音识别算法。当然,现在的主流都是采用Deep Learning去做的。 那么,在传统语音识别领域,一般用什么方法呢?用得最多的就是3个算法,HMM(Hidden Markov Model) ;GMM(Gaussian Mixture Model);CTC(Connectionist Temporal Classification)
基于Deep Learning的语音识别算法,依据模型的不同,有如下5种选择:
CTC出现得最早,后来随着Seq2Seq概念的提出,有了LAS和RNN-T,近些年慢慢发展出了Neural Transducer,MochA。比较常用的是前面3个(LAS, CTC, RNN-T),LAS是可以和CTC一起使用的。另外,传统的HMM模型也可以结合DNN模型,做一些融合。下图为2019年NLP顶会100 paper,所采用的各种模型的比例
LAS算法
LAS就是我们所熟知的那个Seq2Seq算法,只不过其用在了语音识别领域,称作LAS
LAS的全称为Listen,Attend,Spell。分别对应于Seq2Seq模型的Encoder,Attention和Decoder
Listen(Encoder)
对于输入的二维语音信号,可以采用如下三种方式来做Encoder
- CNN(这里是1维卷积)
- RNN
- Self-Attention
有时候,在上述步骤处理完之后,我们也会适当加入Down-Sampling操作。因为一段声音讯号太长了,而且相邻向量间,带有重复的信息。为了节省计算量 ,我们可以用Pyramid RNN,它的做法是在每一层的RNN输出后,都做一个聚合操作。把两个向量加起来,变成一个向量。这样它的隐层就会比较少。或者我们也可以用Pooling Over time,两个time step的向量,只选其中一个,输入到下一层
除了上面两个,还有一些Down-Sampling的方法,例如Time-delay DNN,通常CNN是计算一个窗口内每个元素的加权之和,而TDDNN则只计算第一个和最后一个元素;Truncated self-attention是自注意力的一个变形。通常自注意力会对一个序列中每个元素都去注意,而Truncated的做法是只让当前元素去对周边一个窗口范围的元素注意
Attend(Attention)
Attention机制就是使得每个时间步,用来解码的输入不一样,从而使得不同时间步关注的侧重点不一样
Attention的输入包括三部分:
- Query向量(下图中的$h^1,h^2,h^3,h^4$)
- Key向量(下图中的$z^0$)
- Value向量(下图中的$h^1,h^2,h^3,h^4$)
通过Query和Key计算得到权重Weight(下图中的$a_0$),然后将Weight进行归一化操作之后,与Value进行dot product,最终得到解码器的输入
Spell(Decoder)
将得到的$c^0$和之前的$z^0$作为解码器RNN的输入,输入是$z^1$,$z^1$代表的是一个词表V中所有可能词预测概率分布向量。我们取argmax就可以解码得到最有可能的第一个token。再拿$z^1$与原编码器的隐层向量做Attention,得到一个新的context vector $c^1$,它与$z^1$一起输入到RNN,同样的方式就能得到第二个token。以此类推,直到解码器得到的token为终止符
语音识别是否非要用注意力不可呢?
注意力机制最早是用在Seq2Seq翻译上解决源语言与目标语言的对齐问题。这种跨度(指注意力观测的范围)很大的注意力,在语音上用会有种杀鸡焉用牛刀的感觉。因为语音上,每次注意跳跃是有限的。而不会出现像机器翻译那样,源句子的第一个词可能是目标句子的最后一个词。我们可以用Location-aware attention来优化。使得注意力不能够随便乱跳,而是要考虑前一个时间步得到的注意力权重影响。这样模型就能学到,每解码出一个token,注意力就要往右移动一点
LAS的限制
LAS虽然神通广大,但它也有一些问题。我们期待我们的模型可以做online的识别,即能够一边听,一边做语音识别。而不是模型听完整句话后,等上一秒,模型才输出辨识结果