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 ightarrow 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过程:

[egin{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} = egin{pmatrix} k^1 \ k^2 \ k^3 end{pmatrix} egin{pmatrix} q^1 & q^2 & q^3 end{pmatrix}\ hat A = softmax(A)\ O = egin{pmatrix} b^1 & b^2 & b^3 end{pmatrix} = egin{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的应用范围,弥补了其缺点。

一个人没有梦想,和咸鱼有什么区别!
原文地址:https://www.cnblogs.com/TABball/p/12727174.html