Python深度学习基于Tensorflow(9)注意力机制

文章目录

        • 注意力机制是怎么工作的
        • 注意力机制的类型
      • 构建Transformer模型
        • Embedding层
        • 注意力机制的实现
        • Encoder实现
        • Decoder实现
        • Transformer实现

注意力机制的主要思想是将注意力集中在信息的重要部分,对重要部分投入更多的资源,以获取更多所关注目标的细节信息,抑制其他无用信息;

在注意力机制的背景下,我们将自主性提示称为查询(Query)。对于给定任何查询,注意力机制通过集中注意力(Attention Pooling)选择感官输入(Sensory Input),这些感官输入被称为值(Value)。每个值都与其对应的非自主提示的一个键(Key)成对。通过集中注意力,为给定的查询(自主性提示)与键(非自主性提示)进行交互,从而引导选择偏向值;

注意力机制计算过程如下:

![[Pasted image 20240512132525.png]]

注意力机制是怎么工作的

图中有四个东西,QueryKeyValueAttention,图中把KeyValue放在了一起是因为其产生的output是与KeyValue的维度是无关的,只与Query的维度有关;文中把KeyValue称作为Context sequenceQuery还是称作为Query sequence;为什么要这么做?可以看模型中右上方的Multi-Head Attention和左下角的Multi-Head Attention的区别进行分析;

QueryKeyValue这三个东西可以用python中的字典来解释,KeyValue表示字典中的键值对,而Query表示我们需要查询的键,QueryKeyValue匹配其得到的结果就是我们需要的信息;但是在这里并不要求QueryKey严格匹配,只需要模糊匹配就可以;Query对每一个Key进行一次模糊的匹配,并给出匹配程度,越适配权重就越大,然后根据权重再与每一个Value进行组合,得到最后的结果;其匹配程度的权重就代表了注意力机制的权重;

多头注意力机制就是把QueryKeyValue多个维度的向量分为几个少数维度的向量组合,再在Query_iKey_iValue_i上进行操作,最后把结果合并;

注意力机制的类型

Transformer模型中Multi-Head Attention有三个, 这三个分别对应三种Multi-Head Attention Layerthe cross attention layerthe global self attention layerthe causal self attention layer,从图中也可以发现每一层都有各自的不同,下面来一一介绍;

the cross attention layer:模型右上角(解码器)的Multi-Head Attention是注意力机制最直接的使用,其将编码器的信息和解码器的信息充分的结合了起来,文中把这一层叫做the cross attention layer;其context sequenceEncoder中得到的;

在这里要注意的是,每一次的查询是可以看得到所有的KeyValue的,但是查询与查询相互之间是看不到的,即独立的;

the global self attention layer:模型左下角(编码器)的Multi-Head Attention,这一层负责处理上下文序列,并沿着他的长度去传播信息即QueryQuery之间的信息;

Query与Query之间的信息传播有很多种方式,例如在Transformer没出来之间我们普遍采用Bidirectional RNNsCNNs的方式来处理;

但是为什么这里不使用RNN和CNN的方法呢?

RNNCNN的限制

  • RNN 允许信息沿着序列一路流动,但是它要经过许多处理步骤才能到达那里(限制梯度流动)。这些 RNN 步骤必须按顺序运行,因此 RNN 不太能够利用现代并行设备的优势。
  • 在 CNN 中,每个位置都可以并行处理,但它只提供有限的接收场。接收场只随着 CNN 层数的增加而线性增长,需要叠加许多卷积层来跨序列传输信息(小波网通过使用扩张卷积来减少这个问题)。

the global self attention layer允许每个序列元素直接访问每个其他序列元素,只需少量操作,并且所有输出都可以并行计算。 就像下图这样:

虽然图像类似于线性层,其本质好像也是线性层,但是其信息传播能力要比普通的线性层要强;

the causal self attention layer:因果自注意层,这一层与the global self attention layer类似,其不同的特点是需要maskMasked Multi-Head Attention;这里要注意的是Transformer是一个自回归模型,每次产生一个输出并且把输出当作输入用来继续产生输出,因此这些模型确保每个序列元素的输出仅依赖于先前的序列元素,所以需要对Attention weights进行处理;

根据论文公式: A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dk QKT)V
可以发现 Q Q Q K K K是做矩阵运算的, A t t e n t i o n Attention Attention中的单个元素计算是 Q Q Q中的某行和 K K K中的某行做点积运算;论文中是计算 A t t e n t i o n Attention Attention后在相应掩码位置乘一个无穷小,这里其实可以优化一下,只计算 A t t e n t i o n Attention Attention有效的位置,可以加快速度;

这一层根据训练和推理有一点不同,如上文所说,在训练时,我们不需要每一次新产生的输出做为输入,我们直接用真值(shift)代替新产生的输出进行训练就好,这样可以在缺失一点稳定性的情况下,加快训练速度,并得到每一个位置上的损失大小;

在推理时,我们并没有真值,我们只能以每一次新产生的输出作为输入进行计算,这里有两种自回归的处理方式;一个是RNN,一个是CNN:Fast Wavenet;

以下是该层的简要表示,即每个序列元素的输出仅依赖于先前的序列元素;

构建Transformer模型

模型结构如下:

Embedding层

Embedding层分为两个部分:input_embeddingposition_embedding

首先是input_embedding,假设 “注意力机制是Transformer的核心” 这句话分词得到 [注意力机制, 是, Transformer, 的, 核心];用序号表示为[1,2,3,4,5],由于是分类变量,需要转化为独热编码再使用权重矩阵映射到某一维度,然而这里可以直接用tf.kears.layers.Embedding一步实现上述两步功能;其需要一个input_dim:表示分类个数,也就是序号的最大值;output_dim:表示隐藏层维度,也就是d_model

其次是position_embedding,论文中采用的是绝对位置编码的方式:

![[Pasted image 20240512143453.png]]

其需要两个参数,一个是pos,这是表示位置,也就是 输入序列的长度 范围内的值,第二个是i,这表示嵌入向量的位置,也就是d_model 隐藏维度范围内的值;实现代码如下:

def absolute_position_embedding(n_len, d_model):positions = tf.range(n_len, dtype=tf.float32)[:,tf.newaxis]depths = tf.range(d_model//2, dtype=tf.float32)[tf.newaxis, :]/(d_model//2)angle_rads = positions / (10000**depths)pos_embedding = tf.concat([tf.sin(angle_rads), tf.cos(angle_rads)], axis=-1)return pos_embedding# position_input = absolute_position_embedding(n_len=2048, d_model=512)
# plt.pcolormesh(position_input.numpy().T, cmap='RdBu')
# plt.ylabel('Depth')
# plt.xlabel('Position')
# plt.colorbar()
# plt.show()

结合起来获得Embeding,使用 tf.keras.layers.Layer 类表达如下:

class Embedding(tf.keras.layers.Layer):def __init__(self, n_len, input_dim, d_model):super(Embedding, self).__init__()self.input_embedding = tf.keras.layers.Embedding(input_dim=input_dim, output_dim=d_model)self.position_embedding = self.absolute_position_embedding(n_len=n_len, d_model=d_model)def absolute_position_embedding(self, n_len, d_model):positions = tf.range(n_len, dtype=tf.float32)[:,tf.newaxis]depths = tf.range(d_model//2, dtype=tf.float32)[tf.newaxis, :]/(d_model//2)angle_rads = positions / (10000**depths)pos_embedding = tf.concat([tf.sin(angle_rads), tf.cos(angle_rads)], axis=-1)return pos_embeddingdef call(self, x):x = self.input_embedding(x)output = x + self.position_embeddingreturn output
注意力机制的实现

由于要适应三种注意力机制,我们需要分离 maskqkv功能

class MultiHeadAttention(tf.keras.layers.Layer):def __init__(self, d_model, num_heads):super(Self_Attention_Mechanism, self).__init__()self.num_heads = num_headsself.wq = tf.keras.layers.Dense(d_model)self.wk = tf.keras.layers.Dense(d_model)self.wv = tf.keras.layers.Dense(d_model)self.wo = tf.keras.layers.Dense(d_model)def split_head(self, x):"""(batch_size, heads, len, depth)"""output = tf.reshape(x, [x.shape[0], x.shape[1], self.num_heads, -1])output = tf.transpose(output, [0,2,1,3])return outputdef scaled_dot_product_attention(self, q, k, v, mask=False):dk = tf.cast(k.shape[-1], tf.float32)matmul_qk = tf.matmul(q, k, transpose_b=True) / tf.math.sqrt(dk)if mask:matmul_qk += -(1 - tf.linalg.band_part(tf.ones_like(matmul_qk), 0, -1)) * 1e9attention_weighs = tf.nn.softmax(matmul_qk, axis=-1)outputs = tf.matmul(attention_weighs, v)return attention_weighs, outputsdef call(self, q, k, v, mask=False, return_attention_weights=False):q = self.split_head(self.wq(q))k = self.split_head(self.wk(k))v = self.split_head(self.wv(v))attention_weighs, output = self.scaled_dot_product_attention(q, k, v, mask=mask)output = tf.transpose(output, [0,2,1,3])output = tf.reshape(output, [output.shape[0], output.shape[1], -1])output = self.wo(output)if return_attention_weights:return attention_weighs, outputelse:return output
Encoder实现

由于 Encoder 有六个相同的子块 EncoderLayer,这里先实现一下 EncoderLayer

EncoderLayer 中 包含一个自注意力机制以及一个前反馈层,所以需要三个参数初始化:d_modelnum_headsdff

这里 dff 表示前反馈层中的投影维度;

class EncoderLayer(tf.keras.layers.Layer):def __init__(self, d_model, num_heads, dff):super(EncoderLayer, self).__init__()self.mha = MultiHeadAttention(d_model, num_heads)self.fnn_in = tf.keras.layers.Dense(dff, activation='relu')self.fnn_out = tf.keras.layers.Dense(d_model)self.layernorm1 = tf.keras.layers.LayerNormalization()self.layernorm2 = tf.keras.layers.LayerNormalization()def call(self, x):x1 = self.mha(q=x, k=x, v=x)x1 = self.layernorm1(x + x1)x2 = self.fnn_in(x1)x2 = self.fnn_out(x2)output = self.layernorm2(x1 + x2)return output

Encoder 从本质来说就是 EncoderLayer 的累加:

class Encoder(tf.keras.layers.Layer):def __init__(self, num_encoder_layer, d_model, num_heads, dff):super(Encoder, self).__init__()self.encoder_layers = [EncoderLayer(d_model, num_heads, dff) for _ in range(num_encoder_layer)]def call(self, x):for encoder_layer in self.encoder_layers:x = encoder_layer(x)return x
Decoder实现

同样按照Encoder中一样实现,但是不同的是:首先多了一个 Mask MutliHead Attention,其次第二个MHA中 kv 是来自于Encoder

class Decoder_layer(tf.keras.layers.Layer):def __init__(self, d_model, num_heads, dff):super(Decoder_layer, self).__init__()self.mha1 = MultiHeadAttention(d_model, num_heads)self.mha2 = MultiHeadAttention(d_model, num_heads)self.fnn_in = tf.keras.layers.Dense(dff, activation='relu')self.fnn_out = tf.keras.layers.Dense(d_model)self.layernorm1 = tf.keras.layers.LayerNormalization()self.layernorm2 = tf.keras.layers.LayerNormalization()self.layernorm3 = tf.keras.layers.LayerNormalization()def call(self, x, enc_output):x1 = self.mha1(q=x, k=x, v=x, mask=True)x1 = self.layernorm1(x + x1)x2 = self.mha2(q=x1, k=enc_output, v=enc_output)x2 = self.layernorm2(x1 + x2)x3 = self.fnn_in(x2)x3 = self.fnn_out(x3)output = self.layernorm3(x2 + x3)return output

循环 DecoderLayer 得到 Decoder

class Decoder(tf.keras.layers.Layer):def __init__(self, num_decoder_layer, d_model, num_heads, dff):super(Decoder, self).__init__()self.decoder_layers = [Decoder_layer(d_model, num_heads, dff) for _ in range(num_decoder_layer)]def call(self, x, enc_output):for decoder_layer in self.decoder_layers:x = decoder_layer(x, enc_output)return x
Transformer实现

结合一下前面实现的东西,很轻松可以得到:

class Transformer(tf.keras.Model):def __init__(self, num_encoder_layer, num_decoder_layer, input_dim, n_len, d_model, num_heads, dff):super(Transformers, self).__init__()self.embedding_1 = Embedding(n_len, input_dim, d_model)self.embedding_2 = Embedding(n_len, input_dim, d_model)self.encoder = Encoder(num_encoder_layer, d_model, num_heads, dff)self.decoder = Decoder(num_decoder_layer, d_model, num_heads, dff)self.final_dense = tf.keras.layers.Dense(input_dim, activation='softmax')def call(self, x1, x2):x1 = self.embedding_1(x1)x2 = self.embedding_2(x2)x1 = self.encoder(x1)x2 = self.decoder(x2, x1)output = self.final_dense(x2)return output

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/836388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GoF之代理模式(静态代理+动态代理(JDK动态代理+CGLIB动态代理带有一步一步详细步骤))

1. GoF之代理模式(静态代理动态代理(JDK动态代理CGLIB动态代理带有一步一步详细步骤)) 文章目录 1. GoF之代理模式(静态代理动态代理(JDK动态代理CGLIB动态代理带有一步一步详细步骤))每博一文案2. 代理模式的理解3. 静态代理4. 动…

整理好的中债国债3年期到期收益率数据集(2002-2023年)

01、数据简介 国债,又称国家公债,是由国家发行的债券,是中央ZF为筹集CZ资金而发行的一种ZF债券,是中央ZF向投资者出具的、承诺在一定时期支付利息和到期偿还本金的债权债务凭证。 中债,是指由中国中债登记结算有限责…

Jetpack Compose一:初步了解Compose

Intellij IDEA构建Android开发环境 IntelliJ IDEA 2023.2.1 Android开发变化 IDEA配置使用Gradle 新建Compose工程,取名ComposeStudy 可以看到的是IDEA为项目初始化了部分代码 使用Compose开发不再需要使用xml文件来设计布局了 Compose中的Text也不同于Android V…

机器学习特征降维

目录 特征降维概念 低方差过滤法 PCA主成分分析 相关系数法 小结 特征降维概念 特征对训练模型时非常重要的;用于训练的数据集包含一些不重要的特征,可能导致模型性能不好、泛化性能不佳;例如: 某些特征的取值较为接近&…

部署Gerapy

1.Gerapy 是什么? Gerapy 是一款基于 Python 3 的分布式爬虫管理框架,它旨在简化和优化分布式爬虫的部署、管理和监控过程。 2.作用与功能? 2.1分布式管理: Gerapy 允许用户在多台机器上部署和管理Scrapy爬虫,实现爬虫…

Oracle数据库之 常用数据库对象(二)

目录 1.视图 1.1.什么是视图? 1.2.创建视图的语法 1.3.简单视图和复杂视图 1.4.创建复杂视图 1.4.1.创建复杂视图的步骤 1.4.2.示例 1.4.3.注意事项 1.5.视图中使用DML的规定 1.5.1.屏蔽DML操作 1.6.删除视图 2.序列 2.1.语法: 2.2.查询序…

HNU-操作系统OS-2024期中考试

前言 该卷为22计科/智能OS期中考卷。 感谢智能22毕宿同学记忆了考卷考题。 同学评价:总体简单;第1,7概念题较难需要看书;第4,5题原题。 欢迎同学分享答案。 【1】共10分 操作系统的设计目标有哪些? 【…

安卓surfaceview的使用方式

1. 什么是surfaceview surfaceview内部机制和外部层次结构 在安卓开发中,我们经常会遇到一些需要高性能、高帧率、高画质的应用场景,例如视频播放、游戏开发、相机预览等。这些场景中,我们需要直接操作图像数据,并且实时地显示到…

传感网应用开发教程--AT指令访问新大陆云平台(ESP8266模块+物联网云+TCP)

实现目标 1、熟悉AT指令 2、熟悉新大陆云平台新建项目 3、具体目标:(1)注册新大陆云平台;(2)新建一个联网方案为WIFI的项目;(3)ESP8266模块,通过AT指令访问…

电商购物系统首页的商品分类

如上图对商品的一个分类实际上和省市区的分类十分类似 , 都是通过自关联的方法来实现 , 但是这里不同的是 , 涉及到外键来获取数据 首先让我们来看一下最后通过后端返回数据的形式是什么样子的 """{1:{channels:[{id:1 , name:手机 , url:},{}{}],sub_cats:[{…

Vue报错:TypeError: Cannot read property ‘upgrade‘ of undefined

Vue报错:TypeError: Cannot read property ‘upgrade’ of undefined 前言 最近打开一个很就之前的开发项目,因为扫描包,所以删除了部分代码,后来就一直报错,现在总结一下。 报错原因:vue.config.js中 d…

力扣HOT100 - 74. 搜索二维矩阵

解题思路&#xff1a; 两次二分&#xff0c;第一次定位行&#xff0c;第二次定位列。 class Solution {public boolean searchMatrix(int[][] matrix, int target) {int m matrix.length, n matrix[0].length;int l 0, r m - 1;//定位行int row -1;while (l < r) {in…

【机器学习300问】86、简述超参数优化的步骤?如何寻找最优的超参数组合?

本文想讲述清楚怎么样才能选出最优的超参数组合。关于什么是超参数&#xff1f;什么是超参数组合&#xff1f;本文不赘述&#xff0c;在之前我写的文章中有详细介绍哦&#xff01; 【机器学习300问】22、什么是超参数优化&#xff1f;常见超参数优化方法有哪些&#xff1f;htt…

Web3探索加密世界:如何避免限制并增加空投成功的几率

今天分享空投如何避免限制以提高效率&#xff0c;增加成功几率&#xff0c;首先我们来了解什么是空投加密&#xff0c;有哪些空投类型。 一、什么是空投加密&#xff1f; 加密货币空投是一种营销策略&#xff0c;包括向用户的钱包地址发送免费的硬币或代币。 加密货币项目使用…

BM7 链表中环的入口结点(快慢指针模板题)

描述 给一个长度为n链表&#xff0c;若其中包含环&#xff0c;请找出该链表的环的入口结点&#xff0c;否则&#xff0c;返回null。 数据范围&#xff1a; &#x1d45b;≤10000n≤10000&#xff0c;1<结点值<100001<结点值<10000 要求&#xff1a;空间复杂度 &…

第02章 计算机网络概述

2.1 本章目标 了解计算机网络的定义了解计算机网络的功能了解计算机网络的分类了解计算机网络的组成 2.2 计算机网络的定义 2.3 计算机网络的功能 2.4 计算机网络的分类 物理拓扑结构分类&#xff1a;总线型、环型、星型 2.5 计算机网络的组成 网络适配器(NIC)接口规格分类&a…

阮怀俊谈如何盘活和挖掘乡村文旅资源

近年来&#xff0c;浙江凭借高水平建设新时代美丽乡村&#xff0c;各项工作持续走在全国前列&#xff0c;最近&#xff0c;在国家发展改革委关于恢复和扩大消费措施的通知中也提到&#xff1a; “推广浙江‘千万工程’经验&#xff0c;建设宜居宜业和美乡村。实施文化产业赋能乡…

报告!Golang冲上来啦!

今天又来讲Go语言&#xff0c;根据全球知名的编程语言排行榜TIOBE在4月份公布的最新的编程语言排名&#xff0c;令人瞩目的是&#xff0c;Go语言已经跃升至历史最高位&#xff0c;位列排行榜第七名&#xff0c;并且Go语言是前十榜单中最年轻的编程语言。这一成绩不仅彰显了Go语…

哈希表Hash table

哈希表是根据关键码的值而直接进行访问的数据结构。 数组就是⼀张哈希表。 哈希表中关键码就是数组的索引下标&#xff0c;然后通过下标直接访问数组中的元素&#xff0c;如下图所示&#xff1a; 那么哈希表能解决什么问题呢&#xff0c;一般哈希表都是用来快速判断⼀个元素是…

【JavaScript】DOM 事件的传播机制

事件与事件流 事件&#xff0c;这里指和网页进行互动。比如点击链接&#xff0c;移动鼠标等网页被触发&#xff0c;做出响应&#xff0c;形成交互。 js 采用事件监听器来监听事件是否发生。 事件流 事件流描述了从页面中接收事件的顺序。当一个事件发生在某个元素上时&…