Transformer 模型

What is TRANSFORMER?

今天学一下变形金刚,transformer是一个很有用的模型,尤其会为我们后面学习BERT model打好基础。文章如有不当之处,请不吝赐教。下面来看一下这个神奇的工具吧。

李宏毅老师transformer课程:https://www.youtube.com/watch?v=ugWDIIOHtPA

用CNN代替RNN

Seq2Seq模型是一个很常用的东西,它能处理的问题类型很广泛,包括翻译、命名体识别等NLP领域的火热话题。这里有一篇关于Seq2Seq的教程,希望能够帮助不是很熟悉Seq2Seq的朋友,下文假设大家已经都比较清楚Seq2Seq model了,至少比我要强

应该说Seq2Seq模型很不错,但是我们还是有不满意的地方。哪里不满意呢?

其实很多人都很注意模型是否能够在数据并行、计算并行的条件下工作,能够得到一个高效的训练方法。RNN就暴露了一个很显然的问题,那就是它并不能并行计算。那我们看看有没有什么其他的方案可以替代它呢?CNN行不行呢?当然可以,要不然这段标题就没有意义了。

纯手绘图,有点丑请见谅。

在图中象征性的画了几个CNN,用\(a_1, a_2, .. a_n\)作3个一起的inner product,得到第一层之后的节点,用第一层的输出继续CNN,以此类推我们可以得到\(b_1, b_2, ..b_n\)。可以看出,虽然一次CNN计算只能考虑附近的三个点的输入,但是多几层就可以考虑整个序列,能起到和bi-RNN类似的效果,更重要的是,你在计算下一层的部分节点时候不需要本层所有节点都算完,计算第\(i\)个节点不需要算出本层的第\(i - 1\)个节点,这让我们的并行成为了可能。

缺点

上面提到的这个做法的缺陷也很明显,就是你必须要加很多层CNN,才可以达到查看整个序列的信息的目的。为了做出改进,有了下面的self-attention。

Self-Attention

我们先给Self-Attention layer一个概念性的定义。

自注意力机制最早来源于Google的一篇论文,这篇论文的名字估计很多人听过,叫'Attention Is All You Need',文中阐述了这个模型的工作原理。总体的来讲,他也是一个Sequential Model,适合处理序列性问题。从论文标题我们就可以看出,文章告诉我们,不再需要RNN,不需要CNN,这个模型也可以input一个sequence,output一个sequence,并且能像bi-directional RNN一样,输出是看过整个输入的,而且还可以parallel!

How to do attention

假设我们的输入还是最原始的one-hot vector,首先通过embedding。即:

\[x^i \rightarrow a^i \]

然后我们有三个矩阵\(q,k,v\),分别再得到\(q^i, k^i, v^i\):

\[q: query(to\ match\ others)\\ k: key(to\ be\ matched)\\ v: information\ to\ be\ extracted \]

attention

然后我们做的一件事情,就是对于每一个\(query\)去和别的\(key\)作attention。我们得到attention后的结果。

\[\alpha^{ij} = attention(q^i, k^j) \]

其中一种可以选用的attention做法,也是paper中的做法:

\[attention(q^i, k^i) = \frac{q^i \cdot k^i}{\sqrt d} \]

其中\(d\)\(q,k\)的维度,为了保证dot product的结果不会大到超出我们的预期,可以直观的感受一下这一部分的作用。当然,其他的运算方法也是可以的,在'attention is all you need'中并没有对运算方法的不同对模型效率的影响做评估。

对上面的结果作softmax:

\[\hat \alpha^{ij} = softmax(\alpha^{ij}) \]

我们这样就计算出了注意力下的各个\(x_j\)\(x_i\)的重要性。

计算output

得到的注意力权重已经是看过整个序列之后的结果了,只要我们的\(v^i\)也是正确的,我们有理由得到:

\[b^i = \sum_j \hat \alpha^{ij} v^i \]

在这个计算过程中,大家看的出来,两个点不过距离多远,只要注意力足够,我们都能保证一定的关联度。

Matrix计算

现在我们看看整个过程是怎么parallel的。

\[I = (a^1 a^2..a^n)\\ Q = (q^1q^2..q^n) = W^q I\\ K = (k^1k^2..k^n) = W^k I\\ V = (v^1v^2..v^n) = W^v I\\ \]

attention过程:

\[\begin{pmatrix} \alpha^{1, 1} & \alpha^{1, 2} & \alpha^{1, 3}\\ \alpha^{2, 1} & \alpha^{2, 2} & \alpha^{2, 3}\\ \alpha^{3, 1} & \alpha^{3, 2} & \alpha^{3, 3} \end{pmatrix} = \begin{pmatrix} k^1 \\ k^2 \\ k^3 \end{pmatrix} \begin{pmatrix} q^1 & q^2 & q^3 \end{pmatrix}\\ \hat A = softmax(A)\\ O = \begin{pmatrix} b^1 & b^2 & b^3 \end{pmatrix} = \begin{pmatrix} v^1 & v^2 & v^3 \end{pmatrix} \hat{A} \]

上面的一连串运算都是矩阵乘法,可以使用GPU加速。

变种:Multi-Head self-attention

所谓Multi-Head Self-Attention呢,就是在原来\(q\)的基础上,我们继续分:

\[Q^{1} = W^{q,1} q^i\\ Q^2 = W^{q,2} q^i\\ \]

\(k,v\)也如此做,这样就得到了多个\(b\),最后再做结合并降维就可以了。

引入多个head的好处是,不同的注意力头可能会注意不同的地方,Google的论文中提到,他们各司其职,可能有的比较注意附近的点,有的比较注意离得远的。

位置信息

如果你还记得,上面说self-attention的这种做法是远处和进出一视同仁,并不考虑各种顺序关系。我们知道这肯定是不合理的,为了让它考虑位置信息,我们再加上position的内容。

做法是用一个包含位置内容的向量\(e^i\)来表示,这个\(e^i\)并不是学习出来的,而是人为规定的。

其实这个位置信息更直观的添加方法是在\(x^i\)那里concat一个表示位置的one-hot对吧?不用担心,实际上道理上是都可行的,而且论文中已经证明了后者做法效果不会比前者更好。

In this work, we use sine and cosine functions of different frequencies:

\[P E(pos,2i) = sin(pos/10000^{2i/d_{model} })\\ P E(pos,2i+1) = cos(pos/10000^{2i/d_{model} } ) \]

where pos is the position and i is the dimension.

Seq2Seq with Attention

现在回忆一下你熟悉的Seq2Seq模型,其中的encoder和decoder,不管是有没有attention,我们都用上面讲的self-attention layer代替。下面是来自Google AI Blog的动画:

一个做翻译任务的transformer的完整结构图如下:

encoder

首先inputs做Embedding,然后用包含位置信息的Positional Encoding加到Embeded input中去,作为整个encoder的输入。

encoder由\(N\)个sublayers组成,每个sublayer又有一个Multi-Head Attention layer和Feed Forward layer组成,其中的Add是把输入和输出加在一起,Norm是做了一次layer Normalization

decoder

decoder相比encoder,多了一层Masked Multi-Head Attention。解码时,所有的已经预测出的结果和输入的Context Vector都会参与Attention,因为只计算已经得到的output的key,所以要这遮住一部分。

应用

基本上所有Seq2Seq用的东西,Transformer都可以应用。可以用它替代RNN,并且能够实现更好的效果。比如文章摘要自动生成,不管输入还是输出,在数量级上都比RNN的应用阶段提升了不少。

Universal Transformers,更加扩展了transformer的应用范围,弥补了其缺点。

posted @ 2020-04-18 17:59  TABball  阅读(677)  评论(0编辑  收藏  举报