深度学习中的Attention机制

0. 导言

attention机制是模仿人类注意力而提出的一种解决问题的办法,简单地说就是从大量信息中快速筛选出高价值信息。主要用于解决LSTM/RNN模型输入序列较长的时候很难获得最终合理的向量表示问题,做法是保留LSTM的中间结果,用新的模型对其进行学习,并将其与输出进行关联,从而达到信息筛选的目的。

1. 知识点前述

encoder+decoder,中文名字是编码器和解码器,应用于seq2seq问题,其实就是固定长度的输入转化为固定长度输出。其中encoder和decoder可以采用的模型包括CNN/RNN/BiRNN/GRU/LSTM等,可以根据需要自己的喜好自由组合。

image

encoder过程将输入的句子转换为语义中间件,decoder过程根据语义中间件和之前的单词输出,依次输出最有可能的单词组成句子。

image

问题就是当输入长度非常长的时候,这个时候产生的语义中间件效果非常的不好,需要调整。

2. attention模型

attention模型用于解码过程中,它改变了传统decoder对每一个输入都赋予相同向量的缺点,而是根据单词的不同赋予不同的权重。在encoder过程中,输出不再是一个固定长度的中间语义,而是一个由不同长度向量构成的序列,decoder过程根据这个序列子集进行进一步处理。

image

这么说比较抽象,具体是怎么做的呢。用一个小例子来说明:
假设输入为一句英文的话:Tom chase Jerry
那么最终的结果应该是逐步输出 “汤姆”,“追逐”,“杰瑞”。
那么问题来了,如果用传统encoder-decoder模型,那么在翻译Jerry时,所有输入单词对翻译的影响都是相同的,但显然Jerry的贡献度应该更高。
引入attention后,每个单词都会有一个权重:(Tom,0.3)(Chase,0.2) (Jerry,0.5),现在的关键是权重怎么算的呢。

image

从图上可以看出来,加了attention机制以后,encoder层的每一步输出都会和当前的输出进行联立计算(wx+b形式),最后用softmx函数生成概率值。
概率值出来了,最后的结果就是一个加权和的形式。

image

基本上所有的attention都采用了这个原理,只不过算权重的函数形式可能会有所不同,但想法相同。

3.attention应用

attention的应用领域非常广泛,文本、图片等都有应用。
文本:应用于seq2seq模型,最常见的应用是翻译。
图片:应用于卷积神经网络的图片提取
当然还有很多其他应用,大家可以自己探索。

4.attention简单实现

4.1 思路1:直接对原文本进行权重计算

这个思路非常暴力,我们说过要对输入进行权重计算,此种方法的计算很简单,就是将输入来一个全连接,随后采用softmax函数激活算概率。先看代码:

from keras.layers import Permute
from keras.layers import Dense
from keras.layers import Lambda
from keras.layers import RepeatVector
from keras.layers import Multiply
def attention_3d_block(inputs, single_attention_blick=False):
    time_steps = K.int_shape()[1]#返回输入的元组,以列表的形式储存
    input_dim = K.int_shape()[2]#记住输入是[训练批量,时间长度,输入维度]
    #下面是函数建模方式
    a = Permute((2, 1))(inputs)
    a = Dense(time_steps, activation='softmax')(a)
    if single_attention_blick:
        a = Lambda(lambda x: K.mean(x, axis=1))(a)
        a = RepeatVector(input_dim)(a)
    a_probs = Permute((2, 1))(a)
    output_attention_mul = Multiply()([inputs, a.prob])
    return output_attention_mul

4.2 思路2:加入激活函数并求和

这个的思路是权重计算之后加了一个tanh激活函数,然后求完权重进行了加和,更加符合attention机制的习惯,其实方法是一样的只不过返回是乘完加和而已。代码来自网上,原作者自己定义了一个attention层。

image
class attention_layers(Layer):
    def __init__(self, **kwargs):
        super(attention_layers, self).__init__(**kwargs)

    def build(self,inputshape):
        assert len(inputshape) == 3
        #以下是keras的自己开发工作
        self.W = self.add_weight(name='attr_weight',
                                 shape=(inputshape[1], inputshape[2]),
                                 initializer='uniform',
                                 trainable=True)
        self.b = self.add_weight(name='attr_bias',
                                 shape=(inputshape[1],),
                                 initializer='uniform',
                                 trainable=True)
        super(attention_layers, self).bulid(inputshape)

    def call(self,inputs):
        x = K.permute_dimensions(inputs, (0, 2, 1))
        a = K.softmax(K.tanh(K.dot(x, self.W) + self.b))
        outputs = K.permute_dimensions(a*x, (0, 2, 1))
        outputs = K.sum(outputs, axis=1)
        return  outputs

    def compute_output_shape(self, input_shape):
        return input_shape[0], input_shape[2]

4.3 层级attention模型

这是比较新的一种思路,在句子和单词层面都输出了一个向量。思路图如下:

image
sentence_input = Input(shape=(MAX_SENT_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sentence_input)
l_lstm = Bidirectional(GRU(100, return_sequences=True))(embedded_sequences)
l_dense = TimeDistributed(Dense(200))(l_lstm)
l_att = AttentionLayer()(l_dense)
sentEncoder = Model(sentence_input, l_att)
review_input = Input(shape=(MAX_SENTS,MAX_SENT_LENGTH), dtype='int32')
review_encoder = TimeDistributed(sentEncoder)(review_input)  # 对文档中每个句子
l_lstm_sent = Bidirectional(GRU(100, return_sequences=True))(review_encoder)
l_dense_sent = TimeDistributed(Dense(200))(l_lstm_sent)
l_att_sent = AttentionLayer()(l_dense_sent)
preds = Dense(2, activation='softmax')(l_att_sent)
model = Model(review_input, preds)

作者:不分享的知识毫无意义
链接:https://www.jianshu.com/p/1d67638139da
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值