LAS:LISTEN, ATTEND AND SPELL
LAS:LISTEN, ATTEND AND SPELL
一个基于神经网络的语音识别系统List, Attend and Spell(LAS),能够将语音直接转录为文字。
进步性:LAS将声学、发音和语言模型融合为一个神经模型,因此可以实现端到端。LAS只包含两部分:收听器(listener)和拼写器(speller)。收听器是一个金字塔循环网络编码器,拼写器是一个基于注意力机制的循环网络解码器。
模型结构
输入\(\mathbf{x}=\left(x_{1}, \ldots, x_{T}\right)\) 滤波器组光谱特征, \(\mathbf{y}= \left(\langle\operatorname{sos}\rangle, y_{1}, \ldots, y_{S},\langle\operatorname{eos}\rangle\right)\), \(y_{i} \in\{a, \cdots, z, 0, \cdots, 9,\)\(\langle space \rangle \langle comma \rangle,\)\(\langle period \rangle,\langle apostrophe \rangle,\langle\mathrm{unk}\rangle\}\) 为输出的字符序列。\(\langle\operatorname{sos}\rangle\) , \(\langle\operatorname{eos}\rangle\) 是特殊的句子开始标记和句子结束标记, \(\langle\mathrm{unk}\rangle\) 未知的标记,如重音字符。
LAS将每个字符输出\(y_{i}\)建模为一个条件分布,覆盖之前的字符\(y_{<i}\)和输入信号 \(\mathrm{x}\),表示为:
这是一种区分性的端到端模型,因为直接预测了给定声信号下字符序列的条件概率。
listener是一个声学模型编码器,它执行一个叫做Listen的操作。Listen操作将原始信号 \(\mathrm{x}\) 转换为高级表示 \(\mathbf{h}=\left(h_{1}, \ldots, h_{U}\right)\) \(U \leq T .\) speller是一个基于注意力的字符解码器,它执行一个AttendAndSpell的操作,输入\(\mathbf{h}\)并产生字符序列的概率分布:
图1描述了这两个组件。
图1 Listen, Attend and Spell (LAS)
Listen
Listen操作使用一个具有金字塔结构的双向长短期记忆RNN (BLSTM)。这个修改是为了减少长度 从\(T\) 减少到\(U\) ,因为输入的语音信号可能有数百到数千帧长。
在每一个连续堆叠的pBLSTM层中,我们将时间分辨率降低了1 / 2。在一个典型的深度BLSTM架构中,\(j\) -th层在\(i\) -th时间步长的输出计算如下:
在pBLSTM模型中,我们将每一层连续步骤的输出连接起来,然后再将其送入下一层,即:
在我们的模型中,我们将3个pblstm叠加在底层的BLSTM层之上,减少8倍时间分辨时间。除了降低分辨率,深度架构允许模型学习数据的非线性特征表示。
speller \(U\)中的注意机制的计算复杂度为\(O(U S)\)因此,减少\(U\)可以显著加快学习和推理。
其中Listen的Encoder部分可使用的模型有双(单)向RNN、1-D CNN、CNN+RNN*更为常用(可以在前几层x1、x2、…、xT使用1-D CNN做filter之后再接RNN得到隐藏层向量h)、或者选择带有Self-attention Layers的方式做Encoder。
Down Sampling
在语音辨识中很重要的数据预处理是要对输入做Down Sampling,因为一段声音讯号表示成 acoustic features 声学特征向量 太长了,1s就有100个frames,相邻的向量间还有很多重叠,为了节约计算量和提高效率
I 减少RNN类模型的运算量所使用的Down Sampling
Down Sampling有很多实现方法,举例来说,最早的是16年提出的 Pyramid RNN ,在传统的RNN中输入4个向量输出4个向量,但在Pyramid RNN内如图第二层中将两个向量transform成一个向量,使得第一层输入4个向量,输出为2个向量。;同年另一种经典的处理方法 Pooling over time,两者类似,不过Pooling是在两个中选一个送到下一层,而Pyramid是两者结合成一个送到下一层。
II 减少CNN、Attention类模型的运算量所使用的Down Sampling
以CNN为例,在语音辨识中,CNN常用的变形是Time-delay DNN(TDNN)(1-D的CNN),在一般CNN filter里会将范围内所有的部分都考虑,但对TDNN来说将只会考虑开头和结尾(就是dilated convolution,空洞卷积)。
在Self-attention中,一般而言,在每一个时间点每一个feature都会去attend到所有的feature,如将x3变为h3,要考虑所有的x才能得到h3,都要做attend计算,(在Translation翻译问题上这种方式是毫无疑问的,因为在翻译中源句的词序可能会被打乱地翻译到译句中,且输入输出长度有限)。但问题是,在语音上输入部分向量很长,没办法做全部的attention,故使用Truncated Self-Attention(如,在做x3的attention时只考虑前后一部分(这个长度是个可调的参数)的范围内做attend,这种方法有一定道理的,语音辨识的输入输出也是顺序的。)
Attend
Dot-Attention
首先有个vector z0,和Encoder的输出\(h^i\)等去一一计算attention,这个计算attention的感觉就像是搜寻,像通过关键字去查询资料库,z0就是关键字,\(h^i\)等就是资料库的内容。在做attention时会有一个function,match这个方式会以z0和来自Encoder的输出h1(至h4)作为输入,会通过计算得到一个数值α。在此便产生了两种match方式,一个常用的方式是如上图的Dot-product 点积运算。
h和z是match的输入,将h和z分别乘上一个矩阵各得到一个新的vector(上图Wh和Wz的上面的绿色框和黄色框),再将这两个vector做dot-product得到α。
这里的match方式就是相当于计算z0和h1的相似度α,z0会和每一个h计算attention得到α。
Additive-Attention
另一种match方式是Additive-Attention,同样输入h和z,再分别乘上一个矩阵,但之后不是做dot-product而是将这两个新vector加起来,再通过激活函数tanh得到向量W,再transform得到α
Attend and Spell
AttendAndSpell函数是使用基于注意力的LSTM传感器计算的 。在每一个输出步,换能器产生的概率分布下一个字符的条件下,所有字符看到之前。\(y_{i}\)的分布是解码器状态\(s_{i}\)和上下文\(c_{i}\)的函数,解码器状态\(s_{i}\)是前一个状态\(s_{i-1}\)、前一个发出的字符\(y_{i-1}\)和上下文\(c_{i-1}\)的函数。上下文向量\(c_{i}\)是由注意机制产生的。具体地说,
其中CharacterDistribution是一个MLP,在字符上有softmax输出,RNN是一个2层LSTM.
在每个时间步,注意机制AttentionContext生成一个上下文向量,\(c_{i}\)将信息封装在生成下一个字符所需的声音信号中。注意模型是基于内容的,将解码器状态\(s_{i}\)的内容与表示时间步长\(u\)的\(\mathbf{h}\)的\(h_{u}\)的内容进行匹配,生成注意向量\(\alpha_{i}\)。向量\(h_{u}\)使用\(\alpha_{i}\)线性混合生成\(c_{i}\)。
具体来说,在每个解码器时间步\(i\), AttentionContext函数利用\(h_{u} \in \mathbf{h}\) 和\(s_{i}\)计算每个时间步\(u\)的标量能量\(e_{i, u}\) .使用softmax函数将标量能量\(e_{i, u}\)转化为时间步长(或注意)\(\alpha_{i}\)的概率分布。使用softmax概率作为混合权值,将listener特征\(h_{u}\)混合到输出时间步\(i\)的上下文向量\(c_{i}\):
\(\phi\) 和 \(\psi\) 是 MLP networks. 训练之后,\(\alpha_{i}\)分布通常非常清晰,只关注\(\mathbf{h}\)的几帧;\(c_{i}\)可以看作是\(\mathbf{h}\)加权特征的连续函数。图1显示了LAS体系结构。
这里的z0会和每一个h计算attention,如 z0和h1 得到 α1、z0和h2 得到 α2,…接下来再将同一行的α做softmax,使这些α和为1,再将这些softmax后的α去乘上各自的h得到最终的向量c0。
就像上图一样,假设softmax后得到的α1 = 0.5 α2 = 0.5 α3 = 0 α4 = 0最终c0 = 0.5h1 + 0.5h2
接下来c0会被当做Decoder的Input,这个c在文献上常常被称为Context vector。
c0作为Decoder的输入只是一种用法,在z0和c0作为输入时,通过RNN得到隐藏层向量z1,再经过一次transform会得到一个由所有tokens构成的Distribution概率分布矩阵(就像上一篇所讲,tokens有很多种选择可以是Grapheme字母汉字 Phoneme音素 Morpheme词根、缀 或Word词,甚至是bytes)如果token是 英文的Grapheme时,则可得到的Distribution如上图所示,概率最大的c将是本次Decoder的输出。
- 输入 \(c^{0},\) 隐藏层由 \(z^{0}\) 更新为 \(z^{1},\) 隐藏层输出通过transform (矩阵变换) 得到预测向量output。
- 拿 \(z^{1}\) 作Attention, 得到 \(\alpha_{1}^{1}, \alpha_{1}^{2}, \alpha_{1}^{3}, \alpha_{1}^{4}\) 。通过Softmax得到 \(c^{1},\) 作为Decoder的第二次输入。
- 每个time step得到的预测向量output(token)会作为下一个time step时Decoder的输入。
- 反复继续下去,直到输出特殊符号
,代表句子的结束。
在这样逐一生成token的过程中将会使用一种算法 Beam Search。
Beam Search
假设现在所有的token只有A和B(当然现实中无论什么语言都不会只有两个token),在第一个timestamp时,Decoder产生第一个token的distribution是A = 0.6,B=0.4,那么选几率最大的那个便是A,这个就叫做Greedy Decoding(类似贪心算法,贪心解码),依次类推,每一个timestamp都将得到几率最大的token,最终将得到A->B->B。注意,看Spell的模型图,在下一个timestamp时候,输入包含上一步的输出,会逐个影响,就像是A->B->B选择A的输出会影响B的输出,选择B的输出会影响下一个B的输出。但这种方法得到的整体概率是不一定最大的,就像贪心算法一样,每一次都选几率大的最终整体的几率不一定最大。就像上图一样 B->B->B的整体几率是大于Greedy的A->B->B,这样生成的token是整体稳定的,理论上是更好的。
在实际上没有办法遍历所有的可能性,找出整体几率最大的路径,而Beam Search是解决Greedy Decoding的一种方法,每一次都保留B(Beam Size)个最好的路径。
假设B=2,如上图,在一开始,可以选择A 可以选择B,每次都保留2个最好的路径,所以就保留A 和 B。之后,我们有A->A A->B B->A B->B四条路径,选择2个概率最高的路径保留,是A->B 和 B->B。再得到A->B->A A->B->B B->B->A B->B->B四个路径,同样保留两个。以此类推,在最后剩余的两条路径选择最好的。注意,代码中B是一个参数,需要自己实验调改。
Learning
我们训练模型的参数,使正确序列的log概率最大化。具体地说,
其中\(\tilde{y}_{i-1}\)为ground truth前一个字符或从模型中随机采样(以\(10 \%\)的概率)的一个字符,即CharacterDistribution\(\left(s_{i-1}, c_{i-1}\right)\),使用的过程。
Teacher Forcing
在训练过程中,假设输入的是cat的语音,输出的是c a t的token。则对于我们的模型来说,我们可将token改为one-hot 矩阵,使得训练模型,在每一个timestamp得到的token distribution与one-hot矩阵的CrossEntropy越小越好,即如图所示,在第二个timestamp上使得生成a的概率更大。
注意,在使用模型时,一般而言,在输出第二个distribution的时候会参考第一个distribution生成的结果,会选择其中最大的一个token变成第二个distribution的输入再产生第二个distribution。但在训练的时候,我们通常会不考虑上一个distribution生成的结果,如在输出a之前,已知c,则我们直接给模型输入c,而不管上一个真正的生成的distribution。这种将正确答案放在训练的过程中叫做Teacher Forcing
如果我们拿前一个timestamp的输出当下一个timestamp的输入,会存在什么样的问题呢?因为在训练的过程中,一开始model的参数是随机的,故一开始的decoder部分效果是非常的烂,很可能第一个生成的token不是c而是x,则对于后续部分,模型会认为在输入x后应该输出a,而不是看到c输出a。经过训练后,模型变好了,会在第一个token部分生成c,但之前的所有训练都白费了。 不管前一个timestamp生成的是什么,我们只要正确答案c,模型只要在后面专注于输入c生成a就好,这种方法就叫做Teacher Forcing。在有encoder、decoder的模型架构中,这是关键的一步。
Attention
就像是 Spell里面所讲(见上图的左),我们把 Decoder的hidden state 拿出来,然后做一下attention产生的context vector c,而这个vector就是下一个timestamp的输入。
还有另外一种使用attention的方式(见上图的右),先把hidden state z拿出来,做attention得到context vector c,而这个vector不是保留到下一个timestamp才使用,而是直接在这个timestamp里使用,将c和z合起来丢到RNN里面产生distribution。
两者哪一个更好呢?在第一篇使用attention做语音辨识的论文中就是我全都要。将上述两种结合,如下图所示,将hidden state z做attention得到context vector c,而这个c一方面作为本次timestamp的输入,又作为下一个timestamp的输入。
Location-aware attention
但在语音方面,上述的attention会不会太过了,因为attention在开始时是为了解决类似翻译问题的输入输出位置不匹配(翻译中,如输入的第一个词“我”很可能翻译到最后一个英文单词“I”),而语音中没有这样的问题,attention的改变就应该是由左到右。
在第一篇LAS的作者也这么觉得,所以他加了一种机制,将前后一段得到的α也拿出来,通过transform与z和h计算。
现在我们要计算time step \(\mathrm{t}=1\) 时对Encoder \(h^{2}\) 的权值 (attention) \(, \alpha_{1}^{2}\).
Location-aware
- 使用前一个time step \(\mathrm{t}=\) 0时Encoder产生的 \(\alpha_{0}^{1}, \alpha_{0}^{2}, \alpha_{0}^{3}, \alpha_{0}^{4}\) 。 \(\quad\) (经过Softmax)
- process history的输入体现了location, 即只考虑 \(h^{2}\) 附近的 \(\alpha\) 。 process history为transform, 输出一个向量, 作为time step \(t=1\) 时 attention的输入。
- 此时attention机制考虑了位置关系,随着语音位置往右移。
Decoding and Rescoring
在推理过程中,我们希望根据输入声音找到最可能的字符序列:
我们使用一个简单的从左到右的波束搜索,类似于[8]。我们也可以将语言模型单独应用于大型外部文本语料库,类似于传统的语音系统[21]。我们简单地用语言模型重定向我们的光束。
我们发现我们的模型对较短的语句有较小的偏倚,因此我们通过假设中字符数\(|\mathbf{y}|_{c}\)来标准化我们的概率,并将其与语言模型概率\(P_{\mathrm{LM}}(\mathbf{y})\)相结合:
其中\(\lambda\)是我们的语言模型权重.
Limitation
• LAS outputs the first token after listening the whole input.
• Users expect on-line speech recognition.
今天的语音辨识,我们是希望可以online的语音辨识的,就是一边听一边辨识,说一点辨识一点。如今天的手机语音辨识,我们可以一边讲语音辨识结果一边产生,而不是听完整句才能进行辨识。一般的LAS做不到,encoder听完整个句子,decoder再去做attention,整个句子没听完没办法做attention。
下一篇要讲的模型就是可以一边听一边做语音辨识的模型。
参考
李宏毅2020人类语言处理
LISTEN, ATTEND AND SPELL: A NEURAL NETWORK FORLARGE VOCABULARY CONVERSATIONAL SPEECH RECOGNITION
https://blog.csdn.net/qq_44574333/article/details/108048650?spm=1001.2014.3001.5501