attention中Q,K,V的理解

  • 第一种

1.首先定义三个线性变换矩阵,query,key,value:

class BertSelfAttention(nn.Module):self.query = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.key = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.value = nn.Linear(config.hidden_size, self.all_head_size)

注意,这里的query, key, value只是一种操作(线性变换)的名称,实际的Q/K/V是它们三个的输出

 2.假设三种操作的输入都是同一个矩阵,这里暂且定长度为L的句子,每个token的特征维度是768,那输入就是(L,768),每一行就是一个字,像这样:

乘以上面三种操作就得到了Q、K、V,(L,768)*(768,768)=(L,768),维度其实没变,即此刻的Q、K、V分别为:

代码为:

class BertSelfAttention(nn.Module):def __init__(self, config):self.query = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.key = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.value = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768def forward(self,hidden_states): # hidden_states 维度是(L, 768)Q = self.query(hidden_states)K = self.key(hidden_states)V = self.value(hidden_states)

3.然后实现这个操作:

① 首先是Q和K矩阵乘,(L, 768)*(L, 768)的转置=(L,L),看图:

首先用Q的第一行,即“我”字的768特征和K中“我”字的768为特征点乘求和,得到输出(0,0)位置的数值,这个数值就代表了“我想吃酸菜鱼”中“我”字对“我”字的注意力权重,然后显而易见输出的第一行就是“我”字对“我想吃酸菜鱼”里面每个字的注意力权重;整个结果自然就是“我想吃酸菜鱼”里面每个字对其它字(包括自己)的注意力权重(就是一个数值)了~

② 然后是除以根号dim,这个dim就是768,至于为什么要除以这个数值?主要是为了缩小点积范围,确保softmax梯度稳定性,具体推导可以看这里:Self-attention中dot-product操作为什么要被缩放

然后就是为什么要softmax,一种解释是为了保证注意力权重的非负性,同时增加非线性,还有一些工作对去掉softmax进行了实验,如PaperWeekly:线性Attention的探索:Attention必须有个Softmax吗?

③ 然后就是刚才的注意力权重V矩阵乘了,如图:

 注意力权重 x VALUE矩阵 = 最终结果

首先是“我”这个字对“我想吃酸菜鱼”这句话里面每个字的注意力权重,和V中“我想吃酸菜鱼”里面每个字的第一维特征进行相乘再求和,这个过程其实就相当于用每个字的权重对每个字的特征进行加权求和,然后再用“我”这个字对对“我想吃酸菜鱼”这句话里面每个字的注意力权重和V中“我想吃酸菜鱼”里面每个字的第二维特征进行相乘再求和,依次类推~最终也就得到了(L,768)的结果矩阵,和输入保持一致~

整个过程在草稿纸上画一画简单的矩阵乘就出来了,一目了然~最后上代码:

class BertSelfAttention(nn.Module):def __init__(self, config):self.query = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.key = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768self.value = nn.Linear(config.hidden_size, self.all_head_size) # 输入768, 输出768def forward(self,hidden_states): # hidden_states 维度是(L, 768)Q = self.query(hidden_states)K = self.key(hidden_states)V = self.value(hidden_states)attention_scores = torch.matmul(Q, K.transpose(-1, -2))attention_scores = attention_scores / math.sqrt(self.attention_head_size)attention_probs = nn.Softmax(dim=-1)(attention_scores)out = torch.matmul(attention_probs, V)return out

4. 为什么叫注意力网络?因为可以看到Q/K/V都是通过同一句话的输入算出来的,按照上面的流程也就是一句话内每个字对其它字(包括自己)的权重分配;那如果不是自注意力呢?简单来说,Q来自于句A,K、V来自于句B即可~

5. 注意,K/V中,如果同时替换任意两个字的位置,对最终的结果是不会有影响的,至于为什么,可以自己在草稿纸上画一画矩阵乘;也就是说注意力机制是没有位置信息的,不像CNN/RNN/LSTM;这也是为什么要引入位置embeding的原因。

  • 第二种

其实直接用邱锡鹏老师PPT里的一张图就可以直观理解——假设D是输入序列的内容,完全忽略线性变换的话可以近似认为Q=K=V=D(所以叫做Self-Attention,因为这是输入的序列对它自己的注意力),于是序列中的每一个元素经过Self-Attention之后的表示就可以这样展现:

也就是说,The这个词的表示,实际上是整个序列加权求和的结果——权重从哪来?点积之后Softmax得到——这里Softmax(QK)就是求权重的体现。我们知道,向量点积的值可以表征词与词之间的相似性,而此处的“整个序列”包括The这个词自己(再一次强调这是Self-Attention),所以最后输出的词的表示,其“主要成分”就主要地包含它自身和跟它相似的词的表示,其他无关的词的表示对应的权重就会比较低。

  • 第三种

首先附上链接:张俊林:深度学习中的注意力模型(2017版)这个几乎是我读到过的讲解Attention最为透彻的篇章之一了。

Q(Querry)代表查询值,对应Decoder的H(t-1)状态。这里要正确理解H(t-1),想要解码出t时刻的输出,你送入Decoder的必然有前一时刻计算出的隐状态。好了,所谓查询,就是你要拿着这个Decoder中的H(t-1)去和Encoder中各个时刻的隐状态[H(1), H(2), ... , H(T)](也就是各个Key)去比,也就是二者计算相似度(对应于文献中的各种energy函数)。最后算出来的结果用Softmax归一化,这个算出来的权重就是带有注意力机制的权重,其实在翻译任务中,Key和Value是相等的。在Transformer的实现源码中,Key和Value的初始值也是相等的。有了这个权重之后,就可以用这个权重对Value进行加权求和,生成的这个新的向量就是带有注意力机制的语义向量 Context vector,而这个语义向量会权衡Target与Source的token与token的关系,从而实现解码输出时,与Source中“真正有决定意义”的token关联。

姑且画蛇添足的再说几句:
首先,Attention机制是由Encoder-Decoder架构而来,且最初是用于完成NLP领域中的翻译(Translation)任务。那么输入输出就是非常明显的 Source-Target的对应关系,经典的Seq2Seq结构是从Encoder生成出一个语义向量(Context vector)而不再变化,然后将这个语义向量送入Decoder配合解码输出。这种方法的最大问题就是这个语义向量,我们是希望它一成不变好呢?还是它最好能配合Decoder动态调整自己,来使Target中的某些token与Source中的真正“有决定意义”的token关联起来好呢?

这就是为什么会有Attention机制的原因。说到底,Attention机制就是想生成会动态变化的语义向量来配合解码输出。而新贵 Self-Attention则是为了解决Target与Source各自内部token与token的关系。在Transformer中,这两种注意力机制得到了有机的统一,释放出了异常惊人的潜力。  

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

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

相关文章

上海线下活动 | LLM 时代的 AI 编译器实践与创新

今年 3 月份, 2023 Meet TVM 系列首次线下活动从上海出发,跨越多个城市,致力于为各地关注 AI 编译器的工程师提供一个学习、交流的平台。 12 月 16 日 2023 Meet TVM 年终聚会将重返上海,这一次我们不仅邀请了 4 位资深的 AI 编…

自动伸缩:解密HPA、VPA、CA和CPA智能调整应用大小和数量

关注【云原生百宝箱】公众号,快速掌握云原生 Kubernetes提供了多种自动伸缩机制,例如HPA(Horizontal Pod Autoscaling),可以根据不同情况动态调整Pod副本数量。此功能使 Pod 能够有效地处理当前流量,而无需…

pytorch中的激活函数详解

1 激活函数介绍 1.1 什么是激活函数 激活函数是神经网络中引入的非线性函数,用于捕获数据中的复杂关系。它来自动物界的灵感,动物的神经元会接受来自对它有作用的其他神经元的信号,当然这些信号对该神经元的作用大小不同(即具有不…

Jmeter+ant+jenkins实现持续集成看这一篇就搞定了!

jmeterantjenkins持续集成 一、下载并配置jmeter 首先下载jmeter工具,并配置好环境变量;参考:https://www.cnblogs.com/YouJeffrey/p/16029894.html jmeter默认保存的是.jtl格式的文件,要设置一下bin/jmeter.properties,文件内容…

如何提高3D建模技能?

无论是制作影视动画还是视频游戏,提高3D建模技能对于你的工作都至关重要的。那么如何能创建出精美的3D模型呢?本文给大家一些3D建模技能方面的建议。 3D建模通过专门的软件完成,涉及制作三维对象。这项技能在视频游戏开发、建筑、动画和产品…

【Java Web学习笔记】0 - 技术体系的说明

B/S软件开发架构简述 B/S架构 1.B/S框架,意思是前端(Browser浏览器)和服务器端( Server )组成的系统的框架结构。 2. B/S架构也可理解为web架构,包含前端、后端、数据库三大组成部分。 3.示意图 ●前端 前端开发技术工具包括三要素: HTML、CSS和Jav…

1-3、DOSBox环境搭建

语雀原文链接 文章目录 1、安装DOSBox2、Debug进入Debugrdeautq 1、安装DOSBox 官网下载下载地址:https://www.dosbox.com/download.php?main1此处直接下载这个附件(内部有8086的DEBUG.EXE环境)8086汇编工作环境.rar执行安装DOSBox0.74-wi…

解决CentOS下PHP system命令unoconv转PDF提示“Unable to connect or start own listener“

centos系统下,用php的system命令unoconv把word转pdf时提示Unable to connect or start own listene的解决办法 unoconv -o /foo/bar/public_html/upload/ -f pdf /foo/bar/public_html/upload/test.docx 2>&1 上面这个命令在shell 终端能执行成功&#xff0c…

基于GAN的多尺度门合并多模态MRI图像合成

Multi-Modal MRI Image Synthesis via GAN With Multi-Scale Gate Mergence 基于GAN的多尺度门合并多模态MRI图像合成背景贡献实验方法生成器gate mergence (GM) strategy(门控融合策略)判别器 损失函数Thinking 基于GAN的多尺度门合并多模态MRI图像合成…

深入了解接口测试:揭秘网络分层和数据处理!

网络分层和数据 上一小节中介绍了接口测试中一些必要重要的定义,这一节我们来讨论一下在学习接口测试过程中我们要关注的最重要的东西:网络分层和数据。 首先,我们来尝试理解一下,为什么网络是要分层的呢? 我们可以…

python文件读取

相对路径 读文件 打印txt文件 fopen(".\data.txt","r",encoding"utf-8") contentf.read() print(content) f.close()with open(".\data.txt","r",encoding"utf-8") as f:contentf.read()print(content)contentf…

Ilya Sutskever:师从Hinton,“驱逐”奥特曼,一个改变AI世界的天才科学

ChatGPT 已经在全球爆火,但大众在两周之前似乎更熟悉Sam Altman,而对另一位创始人 Ilya Sutskever 却了解不多。 直到前几天因为OpenA眼花缭乱的政权争夺大戏,OpenAI 的首席科学家Ilya Sutskever的名字逐渐被世人所知。 Ilya Sutskever在科…

STM32 CUBEIDE Outline is disabled due to scalability mode

项目场景: 问题描述 Outline is disabled due to scalability mode 看不到函数 解决方案:

继承中的析构函数的权限的深入了解

如果一个父类中的析构函数如果设置为 private 权限 ,一个子类public继承了这个父类,那么 这个父类可以创建对象吗? 答案是 不可以 看看下面的代码 class A { public:private:~A() {} };class B :public A {A a; // 这个地方编译不报错&…

【CAN通信】CanIf模块详细介绍

目录 1.内容简介 2.CanIf详细设计 2.1 CanIf功能简介 2.2 一些关键概念 2.3依赖的上下层模块 2.4 功能详细设计 2.4.1 Hardware object handles 2.4.2 Static L-PDUs 2.4.3 Dynamic L-PDUs 2.4.4 Dynamic Transmit L-PDUs 2.4.5 Dynamic receive L-PDUs 2.4.6Physi…

PostGIS学习教程八:空间关系

PostGIS学习教程八:空间关系 到目前为止,我们只使用了测量(ST_Area、ST_Length)、序列化(ST_GeomFromText)或者反序列化(ST_AsGML)几何图形(geometry)的空间…

【MATLAB】异常数据识别

基于分位数的异常点识别 首先,给定了一个原始数据序列x。然后,计算了序列x的上四分位数和下四分位数,并根据这两个值计算了异常点的阈值。上四分位数减去1.5倍的四分位数范围得到异常值下界,下四分位数加上1.5倍的四分位数范围得…

运行新vue3项目

一,下载node并安装 官网:https://nodejs.org/en/ 查看版本: node -v二,cd进入到vue3项目目录 cd D:\Program-space\HBuilderXProject\Vue3project三,npm install npm install四,查看安装 npm list五&a…

解析生效探测方法

linux dig命令 1.最常用的查询命令 dig baidu.com2 . 根据记录类型进行查询,比如MX,CNAME,NS,PTR等,只需将类型加在命令后面即可。 dig a.shifen.com ns3 . 指定域名DNS服务器测试解析是否生效的命令,以…

centos8 下载

下载网址 Download 直接下载地址 https://mirrors.cqu.edu.cn/CentOS/8-stream/isos/x86_64/CentOS-Stream-8-20231127.0-x86_64-dvd1.iso 这个版本安装的时候方便