0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

究竟Self-Attention结构是怎样的?

WpOh_rgznai100 来源:lq 2019-07-18 14:29 次阅读

一、Self-Attention概念详解

了解了模型大致原理,我们可以详细的看一下究竟Self-Attention结构是怎样的。其基本结构如下

对于self-attention来讲,Q(Query), K(Key), V(Value)三个矩阵均来自同一输入,首先我们要计算Q与K之间的点乘,然后为了防止其结果过大,会除以一个尺度标度,其中为一个query和key向量的维度。再利用Softmax操作将其结果归一化为概率分布,然后再乘以矩阵V就得到权重求和的表示。该操作可以表示为

这里可能比较抽象,我们来看一个具体的例子(图片来源于https://jalammar.github.io/illustrated-transformer/),该博客讲解的极其清晰,强烈推荐),假如我们要翻译一个词组Thinking Machines,其中Thinking的输入的embedding vector用表示,Machines的embedding vector用表示。

当我们处理Thinking这个词时,我们需要计算句子中所有词与它的Attention Score,这就像将当前词作为搜索的query,去和句子中所有词(包含该词本身)的key去匹配,看看相关度有多高。我们用代表Thinking对应的query vector,及分别代表Thinking以及Machines对应的key vector,则计算Thinking的attention score的时候我们需要计算与的点乘,同理,我们计算Machines的attention score的时候需要计算与的点乘。如上图中所示我们分别得到了与的点乘积,然后我们进行尺度缩放与softmax归一化,如下图所示:

显然,当前单词与其自身的attention score一般最大,其他单词根据与当前单词重要程度有相应的score。然后我们在用这些attention score与value vector相乘,得到加权的向量。

如果将输入的所有向量合并为矩阵形式,则所有query, key, value向量也可以合并为矩阵形式表示:

其中是我们模型训练过程学习到的合适的参数。上述操作即可简化为矩阵形式:

二、Self_Attention模型搭建

笔者使用Keras来实现对于Self_Attention模型的搭建,由于网络中间参数量比较多,这里采用自定义网络层的方法构建Self_Attention。

Keras实现自定义网络层。需要实现以下三个方法:(注意input_shape是包含batch_size项的)

build(input_shape): 这是你定义权重的地方。这个方法必须设self.built = True,可以通过调用super([Layer], self).build()完成。

call(x): 这里是编写层的功能逻辑的地方。你只需要关注传入call的第一个参数:输入张量,除非你希望你的层支持masking。

compute_output_shape(input_shape): 如果你的层更改了输入张量的形状,你应该在这里定义形状变化的逻辑,这让Keras能够自动推断各层的形状。

实现代码如下:

from keras.preprocessing import sequencefrom keras.datasets import imdbfrom matplotlib import pyplot as pltimport pandas as pdfrom keras import backend as Kfrom keras.engine.topology import Layerclass Self_Attention(Layer): def __init__(self, output_dim, **kwargs): self.output_dim = output_dim super(Self_Attention, self).__init__(**kwargs) def build(self, input_shape): # 为该层创建一个可训练的权重 #inputs.shape = (batch_size, time_steps, seq_len) self.kernel = self.add_weight(name='kernel', shape=(3,input_shape[2], self.output_dim), initializer='uniform', trainable=True) super(Self_Attention, self).build(input_shape) # 一定要在最后调用它 def call(self, x): WQ = K.dot(x, self.kernel[0]) WK = K.dot(x, self.kernel[1]) WV = K.dot(x, self.kernel[2]) print("WQ.shape",WQ.shape) print("K.permute_dimensions(WK, [0, 2, 1]).shape",K.permute_dimensions(WK, [0, 2, 1]).shape) QK = K.batch_dot(WQ,K.permute_dimensions(WK, [0, 2, 1])) QK = QK / (64**0.5) QK = K.softmax(QK) print("QK.shape",QK.shape) V = K.batch_dot(QK,WV) return V def compute_output_shape(self, input_shape): return (input_shape[0],input_shape[1],self.output_dim)

这里可以对照一中的概念讲解来理解代码

如果将输入的所有向量合并为矩阵形式,则所有query, key, value向量也可以合并为矩阵形式表示

上述内容对应

WQ = K.dot(x, self.kernel[0])WK = K.dot(x, self.kernel[1])WV = K.dot(x, self.kernel[2])

其中是我们模型训练过程学习到的合适的参数。上述操作即可简化为矩阵形式:

上述内容对应(为什么使用batch_dot呢?这是由于input_shape是包含batch_size项的)

QK = K.batch_dot(WQ,K.permute_dimensions(WK, [0, 2, 1]))QK = QK / (64**0.5)QK = K.softmax(QK)print("QK.shape",QK.shape)V = K.batch_dot(QK,WV)

这里QK = QK / (64**0.5) 是除以一个归一化系数,(64**0.5)是笔者自己定义的,其他文章可能会采用不同的方法。

三、训练网络

项目完整代码如下,这里使用的是Keras自带的imdb影评数据集。

#%%from keras.preprocessing import sequencefrom keras.datasets import imdbfrom matplotlib import pyplot as pltimport pandas as pdfrom keras import backend as Kfrom keras.engine.topology import Layerclass Self_Attention(Layer): def __init__(self, output_dim, **kwargs): self.output_dim = output_dim super(Self_Attention, self).__init__(**kwargs) def build(self, input_shape): # 为该层创建一个可训练的权重 #inputs.shape = (batch_size, time_steps, seq_len) self.kernel = self.add_weight(name='kernel', shape=(3,input_shape[2], self.output_dim), initializer='uniform', trainable=True) super(Self_Attention, self).build(input_shape) # 一定要在最后调用它 def call(self, x): WQ = K.dot(x, self.kernel[0]) WK = K.dot(x, self.kernel[1]) WV = K.dot(x, self.kernel[2]) print("WQ.shape",WQ.shape) print("K.permute_dimensions(WK, [0, 2, 1]).shape",K.permute_dimensions(WK, [0, 2, 1]).shape) QK = K.batch_dot(WQ,K.permute_dimensions(WK, [0, 2, 1])) QK = QK / (64**0.5) QK = K.softmax(QK) print("QK.shape",QK.shape) V = K.batch_dot(QK,WV) return V def compute_output_shape(self, input_shape): return (input_shape[0],input_shape[1],self.output_dim)max_features = 20000print('Loading data...')(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)#标签转换为独热码y_train, y_test = pd.get_dummies(y_train),pd.get_dummies(y_test)print(len(x_train), 'train sequences')print(len(x_test), 'test sequences')#%%数据归一化处理maxlen = 64print('Pad sequences (samples x time)')x_train = sequence.pad_sequences(x_train, maxlen=maxlen)x_test = sequence.pad_sequences(x_test, maxlen=maxlen)print('x_train shape:', x_train.shape)print('x_test shape:', x_test.shape)#%%batch_size = 32from keras.models import Modelfrom keras.optimizers import SGD,Adamfrom keras.layers import *from Attention_keras import Attention,Position_EmbeddingS_inputs = Input(shape=(64,), dtype='int32')embeddings = Embedding(max_features, 128)(S_inputs)O_seq = Self_Attention(128)(embeddings)O_seq = GlobalAveragePooling1D()(O_seq)O_seq = Dropout(0.5)(O_seq)outputs = Dense(2, activation='softmax')(O_seq)model = Model(inputs=S_inputs, outputs=outputs)print(model.summary())# try using different optimizers and different optimizer configsopt = Adam(lr=0.0002,decay=0.00001)loss = 'categorical_crossentropy'model.compile(loss=loss, optimizer=opt, metrics=['accuracy'])#%%print('Train...')h = model.fit(x_train, y_train, batch_size=batch_size, epochs=5, validation_data=(x_test, y_test))plt.plot(h.history["loss"],label="train_loss")plt.plot(h.history["val_loss"],label="val_loss")plt.plot(h.history["acc"],label="train_acc")plt.plot(h.history["val_acc"],label="val_acc")plt.legend()plt.show()#model.save("imdb.h5")

四、结果输出

(TF_GPU) D:FilesDATAsprjspython f_keras ransfromerdemo>C:/Files/APPs/RuanJian/Miniconda3/envs/TF_GPU/python.exe d:/Files/DATAs/prjs/python/tf_keras/transfromerdemo/train.1.pyUsing TensorFlow backend.Loading data...25000 train sequences25000 test sequencesPad sequences (samples x time)x_train shape: (25000, 64)x_test shape: (25000, 64)WQ.shape (?, 64, 128)K.permute_dimensions(WK, [0, 2, 1]).shape (?, 128, 64)QK.shape (?, 64, 64)_________________________________________________________________Layer (type) Output Shape Param #=================================================================input_1 (InputLayer) (None, 64) 0_________________________________________________________________embedding_1 (Embedding) (None, 64, 128) 2560000_________________________________________________________________self__attention_1 (Self_Atte (None, 64, 128) 49152_________________________________________________________________global_average_pooling1d_1 ( (None, 128) 0_________________________________________________________________dropout_1 (Dropout) (None, 128) 0_________________________________________________________________dense_1 (Dense) (None, 2) 258=================================================================Total params: 2,609,410Trainable params: 2,609,410Non-trainable params: 0_________________________________________________________________NoneTrain...Train on 25000 samples, validate on 25000 samplesEpoch 1/525000/25000 [==============================] - 17s 693us/step - loss: 0.5244 - acc: 0.7514 - val_loss: 0.3834 - val_acc: 0.8278Epoch 2/525000/25000 [==============================] - 15s 615us/step - loss: 0.3257 - acc: 0.8593 - val_loss: 0.3689 - val_acc: 0.8368Epoch 3/525000/25000 [==============================] - 15s 614us/step - loss: 0.2602 - acc: 0.8942 - val_loss: 0.3909 - val_acc: 0.8303Epoch 4/525000/25000 [==============================] - 15s 618us/step - loss: 0.2078 - acc: 0.9179 - val_loss: 0.4482 - val_acc: 0.8215Epoch 5/525000/25000 [==============================] - 15s 619us/step - loss: 0.1639 - acc: 0.9368 - val_loss: 0.5313 - val_acc: 0.8106

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计算
    +关注

    关注

    2

    文章

    431

    浏览量

    38477
  • 矩阵
    +关注

    关注

    0

    文章

    406

    浏览量

    34244
  • 机制
    +关注

    关注

    0

    文章

    24

    浏览量

    9719

原文标题:机器如何读懂人心:Keras实现Self-Attention文本分类

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    真正软件定义无线电究竟怎样的?

    真正软件定义无线电究竟怎样的?
    发表于 05-14 06:47

    面向列的HBase存储结构究竟有什么样的不同之处呢?

    HBase是什么?HBase的存储结构究竟怎样的呢?面向列的HBase存储结构究竟有什么样的不同之处呢?
    发表于 06-16 06:52

    暴风电视拆机图解 内部结构究竟怎样

    继乐视、小米之后,国内另一家互联网公司--暴风影音也发布了旗下的智能电视产品,而且同样是分体式设计。而今天我们就来看看爱玩客带来的暴风电视的内部结构究竟怎样的。
    的头像 发表于 09-04 14:32 3w次阅读

    BERT模型的PyTorch实现

    BertModel是一个基本的BERT Transformer模型,包含一个summed token、位置和序列嵌入层,然后是一系列相同的self-attention blocks(BERT-base是12个blocks, BERT-large是24个blocks)。
    的头像 发表于 11-13 09:12 1.4w次阅读

    为什么要有attention机制,Attention原理

    没有attention机制的encoder-decoder结构通常把encoder的最后一个状态作为decoder的输入(可能作为初始化,也可能作为每一时刻的输入),但是encoder的state
    的头像 发表于 03-06 14:11 1.6w次阅读
    为什么要有<b class='flag-5'>attention</b>机制,<b class='flag-5'>Attention</b>原理

    AAAI 2019 Gaussian Transformer 一种自然语言推理方法

    自然语言推理 (Natural Language Inference, NLI) 是一个活跃的研究领域,许多基于循环神经网络(RNNs),卷积神经网络(CNNs),self-attention 网络 (SANs) 的模型为此提出。
    的头像 发表于 05-14 09:45 2878次阅读
    AAAI 2019 Gaussian Transformer 一种自然语言推理方法

    解析Transformer中的位置编码 -- ICLR 2021

    引言 Transformer是近年来非常流行的处理序列到序列问题的架构,其self-attention机制允许了长距离的词直接联系,可以使模型更容易学习序列的长距离依赖。由于其优良的可并行性以及可观
    的头像 发表于 04-01 16:07 1.2w次阅读
    解析Transformer中的位置编码 -- ICLR 2021

    一个LSTM被分解成垂直和水平的LSTM

    Vision Transformer成功的原因被认为是由于Self-Attention建模远程依赖的能力。然而,Self-Attention对于Transformer执行视觉任务的有效性有多重要还不清楚。事实上,只基于多层感知器(MLPs)的MLP-Mixer被提议作为V
    的头像 发表于 05-07 16:29 1152次阅读

    基于视觉transformer的高效时空特征学习算法

    视觉Transofrmer通常将图像分割为不重叠的块(patch),patch之间通过自注意力机制(Self-Attention)进行特征聚合,patch内部通过全连接层(FFN)进行特征映射。每个
    的头像 发表于 12-12 15:01 1073次阅读

    简述深度学习中的Attention机制

    Attention机制在深度学习中得到了广泛的应用,本文通过公式及图片详细讲解attention机制的计算过程及意义,首先从最早引入attention到机器翻译任务(Bahdanau et al. ICLR2014)的方法讲起。
    的头像 发表于 02-22 14:21 1048次阅读
    简述深度学习中的<b class='flag-5'>Attention</b>机制

    解析ChatGPT背后的技术演进

    。  2)Transformer模型没有使用传统的CNN和RNN结构,其完全是由Attention机制组成,其中Self-Attention(自注意力)是Transformer的核心。  3)OpenAI的GPT模型和Googl
    发表于 03-29 16:57 1次下载

    如何入门面向自动驾驶领域的视觉Transformer?

    理解Transformer背后的理论基础,比如自注意力机制(self-attention), 位置编码(positional embedding),目标查询(object query)等等,网上的资料比较杂乱,不够系统,难以通过自学做到深入理解并融会贯通。
    的头像 发表于 07-09 14:35 398次阅读
    如何入门面向自动驾驶领域的视觉Transformer?

    基于Transformer的目标检测算法的3个难点

    理解Transformer背后的理论基础,比如自注意力机制(self-attention), 位置编码(positional embedding),目标查询(object query)等等,网上的资料比较杂乱,不够系统,难以通过自学做到深入理解并融会贯通。
    发表于 07-18 12:54 450次阅读
    基于Transformer的目标检测算法的3个难点

    基于Transformer的目标检测算法难点

    理解Transformer背后的理论基础,比如自注意力机制(self-attention), 位置编码(positional embedding),目标查询(object query)等等,网上的资料比较杂乱,不够系统,难以通过自学做到深入理解并融会贯通。
    发表于 08-24 11:19 166次阅读
    基于Transformer的目标检测算法难点

    视觉Transformer基本原理及目标检测应用

    视觉Transformer的一般结构如图2所示,包括编码器和解码器两部分,其中编码器每一层包括一个多头自注意力模块(self-attention)和一个位置前馈神经网络(FFN)。
    发表于 04-03 10:32 299次阅读
    视觉Transformer基本原理及目标检测应用