Tensorflow实现Attention层

发布于 2019-06-11 19:25:42

Attention机制最近很火啊,万物皆可Attention,为啥呢?

首先,Attention是怎么来的?在十月一号的景点,你给你心爱的拍了一张照片,然后你看着这张照片,眼睛里满满都是你心爱的人,为什么呢,因为你给你心爱的都在图像区域分配较大权重,而给**地方分配了较小的权重,所以这张照片主要描述的内容就是你心爱的人,无论你怎么构图,把他放1/3处,左下角,右上角,这张照片的主要内容都不会改变。这个就是Attention最初思想的由来。所以Attention的本质就是一个权重分配机制。
有超级多的博客说了Attention是一种软寻址方式,其实很有道理,但是对于大部分而言就感觉听起来就很难,所以我们换个角度理解,所以呢当你做Attention的时候,你要明确两个东西,第一个就是你要给什么东西做Attention,第二个,什么东西决定你的权重。做Attention的东西比如说,每一个字有N维字向量,每一维字向量(向量级别),每一部分字向量(比如0-25维,25-50维,50-75维)Bert(Tranformer)的思路,每一个字的所有向量,每一个词。这些都可以进行Attention。上述的做Attention的部分就是Key和Value,接下来是你需要选择另外一个向量对他进行权重分配就是Query。
由于我不会上传图片。。。就口述一下,在自然语言中一般K=V(在Google的《Attention is all you need》中K=V=Q,这个叫自注意力机制,用自己给自己定权重,喜欢Attention机制的人这篇文章应该是必读的),我这边就不详述了,我讲讲Attention的常见做法

第一步:
S=F(Q,K)
第二步:
A=Softmax(S)
第三步:
multiply(A,V)
第一步是个相似度的计算,常见的相似度计算有点乘,拼接,感知机。第二步是搞成概率的样子,就是相加为1,第三步是一个点乘就是让每个部分乘上他的权重然后得到最后Attention输出的值。
F(Q,K)=Qt.K F(Q,K)=Wa[Q,K] F(Q,K)=V(UQ+WK)
W,U,V为参数矩阵,(bert用的第一个,是不是感觉到了bert的厉害了,都不用参数)。我这里代码实现了一下第三个,上代码:

hidden_size2 = int(A.shape[-1])
hidden_size1 = int(B.shape[-1])
A = tf.reshape(A, [-1, hidden_size2])
attention_W = tf.get_variable(name="attention_W",
                              shape=[hidden_size1, self._nb_classes],
                              initializer=tf.contrib.layers.xavier_initializer(),
                              dtype=tf.float32)
attention_V = tf.get_variable(name="attention_V", shape=[self._nb_classes, 1],
                              initializer=tf.contrib.layers.xavier_initializer(),
                              dtype=tf.float32)
attention_U = tf.get_variable(name="attention_U",
                              shape=[hidden_size2, self._nb_classes],
                              initializer=tf.contrib.layers.xavier_initializer(),
                              dtype=tf.float32)
atten_hidden = tf.tanh(
    tf.add(tf.matmul(B, attention_W), tf.matmul(A, attention_U)))
e_i = tf.matmul(atten_hidden, attention_V)
alpha_i = tf.nn.softmax(e_i)
self.outputs = tf.multiply(alpha_i, B)

这里想单独说一下这句话,tf.contrib.layers.xavier_initializer()这是参数初始化的一种方式,是一篇很有名的论文,大家可以去看一下,Tensorflow厉害在,很多论文都以接口的形式给出,能入Tensorflow接口的也都是比较厉害的论文了。

0 评论

发布
问题