• seq2seq和Transformer


    简单而言,seq2seq由两个RNN组成,一个是编码器(encoder),一个是解码器(decoder).以MT为例,将源语言“我爱中国”译为“I love China”,则定义序列:

    [X=(x_0,x_1,x_2,x_3)\ 其中,x_0=“我”,x_1=“爱”,x_2=“中”,x_3=“国” ]

    另外目标序列:

    [Y=(y_0,y_1,y_2)="I love China" ]

    通过编码器将(X=(x_0,x_1,x_2,x_3))映射为隐层状态(h),再经由解码器将(h)映射为(Y=(y_0,y_1,y_2))

    通常使用(h​)表示编码器的隐状态;用(s​)表示解码器的隐状态

    注意:编码器输入和解码器输出向量的维度可以不同,最后将预测T和真实目标序列T‘做loss(通常是交叉熵)训练网络。

    注意力机制

    通过编码器,把(X=(x_1,x_2,x_3,x_4))映射为一个隐层状态(H=(h_0,h_1,h_2,h_3)),解码器将(H=(h_0,h_1,h_2,h_3))映射为(Y=(y_0,y_1,y_2))。在带注意力机制的编解码器中,(Y)中的每一个元素都与(H)中的所有元素相连,而解码器的每个元素通过不同的权值给予编码器输出(Y)不同的贡献。

    解码器输出有3个:

    • 上一解码步的隐状态((s_{t-1}))

    • 上一解码步的输出((y_{t-1}))

    • 注意力输出(编码器输出的加权和,context,是编码器端发给解码器信息的地方,由所有的编码器输出得到一个定长的向量,代表输入序列的全局信息,作为当前解码步的上下文),计算方法为:

      [c_i=sum_{j=1}^{T_x}alpha_{ij}h_j ]

      其中,(alpha_{ij})是权重((alpha_{ij})是标量,(alpha)是二阶张量),又称作alignment(h)是编码器所有时间步上的隐状态,又称作value或memory;(i)表示解码步,(j)表示编码步,输出(c_i)是和(h_j)同样大小的向量。

      在时间(i)上,

      [c_i=sum_{j=1}^{T_x}alpha_{ij}h_j=alpha_{i,1}h_1+alpha_{i,2}h_2+...+alpha_{i,T_x}h_{T_x} ]

      其中,(c_i)是与编码器输出(h_j)等大的向量;(j)为编码步;(i)为解码步;(alpha_{ij})为标量,计算方式:

      [alpha_{ij}=frac{exp(e_{ij})}{sum_{k=1}^{T_x}exp(e_{ik})} ]

      其中,(e_{ij}=a(s_{i-1,j},h_j)),表征(s_{i-1})(h_j)的相关程度,即对于某个给定的解码步,计算上一解码步的隐状态和所有编码步输出的相关程度,并且用softmax做归一化。这样,与上一解码步状态相关度大的编码器输出(h)的权重就大,在本解码步的整个上下文里面所占的比重就多,解码器在本时间步上解码时就越依赖这个编码器的输出(h).

      (e_{ij})又被称作能量函数,(a(·))的计算方法:

      1. (s_{i-1})做线性映射,得到向量作为query(解码器上一时间步隐状态作为“查询”),记作(q_i)
      2. (h_j)做线性映射,得到向量作为key(编码器每一个时间步上的结果作为key待查),记作(k_j)
      3. (e_{ij}=v^T(q_i+k_j))(q_i)(k_j)的维度必须相同,同为d维;(v)是一个d×1的向量,从而得到的(e_{ij})是一个标量

      1、2中的线性映射都是待训练的,3中的(v)也是待训练的。

      对query和key求相关性从而获得权重(alignment),用该权重对value加权和从而得到上下文送入解码器。

      小结

      • 3中query和key做加法,之后通过一个权重变为标量。这被称作“加性注意力”,相应的,可以做元素乘,被称作“乘性注意力”
      • location-sensitive,认为相邻(alpha_{ij})之间的关系会相对较大,为了捕获这种关系对alignment进行了卷积。
      • query有多种,不仅仅有上一解码步的隐状态;也有当前解码步的隐状态;还有将上一解码步上的隐状态和上一解码步的输出拼接作为query。但在TTS中,将上一解码步的隐状态和输出拼接作为query并不好,原因可能是可能两者不在同一空间,因此要具体问题具体分析。

    Transformer

    • 左右分别是编码器和解码器

    • 编码器和解码器的底部都是embedding,而embedding又分为两部分:input embeddingpositional embedding,其中input embedding就是NLP中常见的词嵌入。因为Transformer中只有attention,对于一对(query, key),无论这对query-key处在什么位置,其计算都是相同的。不像CNN或RNN有一个位置或时序的差异:CNN框住的是一块区域,随着卷积核的移动,卷积核边缘的点也随着有序变化;RNN则更为明显,不同时序的(h_t)(s_t)不同,而且是随着输入顺序(正/倒序)而不同。

      因此Transformer为了体现出时序或者序列中的位置差异,要对input加入一定的位置信息,这即是position embedding。求位置id为pos的位置编码向量:

      [left{egin{matrix} PE(pos,i)=sin(frac{pos}{10000^{frac{i}{d_{model}}}}), 若i为奇数 \ PE(pos,i)=cos(frac{pos}{10000^{frac{i}{d_{model}}}}) 若i为偶数 end{matrix} ight. PE向量第i维的求解方法 ]

      编码器和解码器输入序列shape: ([T,d_{model}]),即每个时刻的(x_i)都是(d_{model})维的,因此(posin [0,T])(iin[0,d_{model}])。即对于输入的([T,d_{model}])的一个张量,其中的每一个标量都对应一个独特的编码结果,可以理解为给embedding一个低频信号,让其周期性波动,而且每个维度波动都不相同,以表征其id信息。

    • 编码器和解码器的中部分别是两个块,分别输入一个序列,输出一个序列,这两个块重复N次。编码器的每个块里有两个子网,分别为Multi-Head Attention和Feed Forward Network(FFN);解码器的每个块里有三个子网,分别是2个Multi-Head Attention和一个FFN。这些子网之后都跟一个add & norm,就是像ResNet那样做一个残差,然后加一个layer normalization。

    • 解码器最后还有个linear和softmax

    FFN

    FFN就是对一个输入序列(X=(x_0,x_1,...,x_T)),对每一个(x_i)都进行一次channel的重组:512 -> 2048 -> 512,可以理解为对每个(x_i)进行两次线性映射,也可以对整个序列进行1×1卷积。

    Multi-Head Attention

    原始的attention就是一个query(Q)和一组key(K)算相似度,然后对一组value(V)做加权和。假如每个Q和K都是512维的向量,就相当于在512维的空间里比较两个向量的相似度。而Multi-Head相当于加过于512维的空间人为拆分为多个子空间,如head number=8就是将高维空间拆分为8个子空间,相应地V也要分为8个head,然后在这8个子空间中分别计算Q和K的相似度,再组合V。这样能使attention从不同角度捕获序列关系。

    • 编码器

      [sub\_layer\_output=LayerNorm(x+SubLayer(x))\ head_i=Attention(QW_i^Q,KW_i^K,VW_i^K)\ MultiHead(Q,K,V)=concat(head_1,head_2,...,head_h)W^O ]

      self-attention时,Q、K、V相同

    • 解码器

      • 输入:编码器的输出 & 对应i-1时刻的解码器输出(i-1步的hidden state和i-1步的输出)

        注意:在解码器中间的attention不是self-attention,其K、V来自编码器,Q来自上一时刻的解码器输出

      • 输出:i时刻的输出词的概率分布

      • 解码:编码可以并行,一次性全部编码出来(在编码时,各个计算互不依赖)。但解码不是一次把所有序列解出来,而是如同RNN一样,一个一个解出来,因为要用到上一解码步的隐状态作为attention的query。解码器端最先的Multi-Head是Masked,这是因为训练时输入是ground truth,这样确保预测第i个位置时,遮蔽掉该位置及其之后的信息,不会接触未来的信息。

    Transformer优缺点

    • 优点

      • 并行计算,这主要体现在编解码器都放弃了RNN,下一个时间步的计算不必等待之前的计算完全展开

      • 直接的长距离依赖

        原来的RNN中,第一帧要和第十帧发生关系,必须通过第二~九帧传递,进而产生两者的计算。而在这个过程中,第一帧的信息有可能已经产生了偏差,准确性和速度都难以保证。在Transformer中,由于self-attention的存在,任意两帧都有直接的交互,建立直接依赖。

    • 缺点

      仍然是自回归模型,任意一帧的输出都依赖于它之前的所有输出。比如输入abc,本次的输出实际是bcd,每输入一个序列,其实序列的末端都只是前进了一帧,因此要生成abcdefg仍然要循环6次。

  • 相关阅读:
    Web打印控件
    excel错误:外部表不是预期的格式 错误
    C#用ado.net访问EXCEL的常见问题及解决方法
    通过反射的方式获取类型中的所有属性
    在64位Windows7上安装64位Oracle11g
    2020&2021的计划
    jQuery_day1
    springboot+mybatis+MySQL(入门级-半小时搞定系列)
    springboot_web开发
    springboot日志
  • 原文地址:https://www.cnblogs.com/mengnan/p/9871665.html
Copyright © 2020-2023  润新知