Attention机制全解
前言
之前已经提到过好几次Attention的应用,但还未对Attention机制进行系统的介绍,之后的实践模型attention将会用到很多,因此这里对attention机制做一个总结。
Seq2Seq
注意力机制(Attention Mechanism)首先是用于解决 Sequence to Sequence 问题提出的,因此我们了解下研究者是怎样设计出Attention机制的。
Seq2Seq,即序列到序列,指的是用Encoder-Decoder框架来实现的端到端的模型,最初用来实现英语-法语翻译。Encoder-Decoder框架是一种十分通用的模型框架,其抽象结构如下图所示:

其中,Encoder和Decoder具体使用什么模型都是由研究者自己定的,CNN/RNN/Transformer均可。Encoder的作用就是将输入序列映射成一个固定长度的上下文向量C,而Decoder则将上下文向量C作为预测\(Y_1\)输出的初始向量,之后将其作为背景向量,并结合上一个时间步的输出来对下一个时间步进行预测。
由于Encoder-Decoder模型在编码和解码阶段始终由一个不变的语义向量C来联系着,这也造成了如下一些问题:
- 所有的输入单词 X 对生成的所有目标单词 Y 的影响力是相同的
- 编码器要将整个序列的信息压缩进一个固定长度的向量中去,使得语义向量无法完全表示整个序列的信息
- 最开始输入的序列容易被后输入的序列给覆盖掉,会丢失许多细节信息,这点在长序列上表现的尤为明显
Attention机制的引入
Attention机制的作用就是为模型增添了注意力功能,使其倾向于根据需要来选择句子中更重要的部分。
加入加入Attention机制的Seq2Seq模型框架如下图所示:

与传统的语义向量C不同的是,带有注意力机制的Seq2Seq模型与传统Seq2Seq模型的区别如下:
- 其为每一次预测都有不同的上下文信息\(C_i\)
\[P(y_i|y_1, y_2, ..., y_{i-1}, X) = P(y_i-1, s_i, c_i)\]
其中\(s_i\)表示Decoder上一时刻的输出状态,\(c_i\)为当前的时刻的中间语义向量
- 当前的时刻的中间语义向量\(c_i\)为对输入信息注意力加权求和之后得到的向量,即:
\[c_i = \sum_{j=1}^{Tx}\alpha_{ij}h_j\]
其中\(h_j\)为Encoder端的第j个词的隐向量,\(\alpha_{ij}\)表示Decoder端的第i个词对Encoder端的第j个词的注意力大小,即输入的第j个词对生成的第i个词的影响程度。这意味着在生成每个单词\(Y_i\)的时候,原先都是相同的中间语义表示\(C\)会替换成根据当前生成单词而不断变化的\(c_i\)。生成\(C_i\)最关键的部分就是注意力权重\(\alpha_{ij}\)的计算,具体的计算方法我们下面再讨论。
Hard or Soft
之前我们提到的为Soft Attention的一般形式,还有一种Hard Attention,其与Soft Attention的区别在于,其通过随机采样或最大采样的方式来选取特征信息(Soft Attention是通过甲醛求和的方式),这使得其无法使用反向传播算法进行训练。因此我们常用的通常是Soft Attention
Global or Local
Global Attention 与 Local Attention 的区别在于二者的关注范围不同。Global Attention 关注的是整个序列的输入信息,相对来说需要更大的计算量。而 Local Attention 仅仅关注限定窗口范围内的序列信息,但窗口的限定使得中心词容易忽视不在窗口范围内的信息,因此窗口的大小设定十分重要。在实践中,默认使用的是Global Attention。
注意力的计算
我们之前已经讨论过,中间语义向量\(c_i\)为对输入信息注意力加权求和之后得到的向量,即:
\[c_i = \sum_{j=1}^{Tx}\alpha_{ij}h_j\]
而注意力权重\(\alpha_{ij}\)表示Decoder端的第i个词对Encoder端的第j个词的注意力大小,即输入的第j个词对生成的第i个词的影响程度。其基本的计算方式如下:
\[\alpha_{ij} = \frac{exp(e_{ij})}{\sum_{k=1}^{T_x}exp(e_{ik})}\]
\[e_{ij} = Score(s_{i-1}, h_j)\]
其中,\(s_{i-1}\)需要根据具体任务进行选择,对于机器翻译等生成任务,可以选取 Decoder 上一个时刻的隐藏层输出,对于阅读理解等问答任务,可以选择问题或问题+选项的表征,对于文本分类任务,可以是自行初始化的上下文向量。而\(h_j\)为 Encoder 端第j个词的隐向量,分析上面公式,可以将Attention的计算过程总结为3个步骤:
- 将上一时刻Decoder的输出与当前时刻Encoder的隐藏词表征进行评分,来获得目标单词 Yi 和每个输入单词对应的对齐可能性(即一个对齐模型),Score(·)为一个评分函数,一般可以总结为两类:
- 点积/放缩点积:
\[e_{ij} = Score(s_{i-1}, h_j) = s_{i-1} \cdot h_j\]
\[e_{ij} = Score(s_{i-1}, h_j) = \frac{s_{i-1} \cdot h_j}{||s_{i-1}||\cdot||h_j||}\]
- MLP网络:
\[e_{ij} = Score(s_{i-1}, h_j) = MLP(s_{i-1}, h_j)\]
\[e_{ij} = Score(s_{i-1}, h_j) = s_{i-1}Wh_{j}\]
\[e_{ij} = Score(s_{i-1}, h_j) = W|h_j;s_{i-1}|\]
- 点积/放缩点积:
得到对齐分数之后,用Softmx函数将其进行归一化,得到注意力权重
最后将注意力权重与 Encoder 的输出进行加权求和,得到需要的中间语义向量\(c_i\)
将公式整合一下:
\[c_{i,j} = Attention(Query, Keys, Values) = Softmax(Score(Query, Keys)) * Values\]
其中,\(Query\)为我们之前提到的\(s_{i-1}\),\(Keys\) 和 \(Values\)为 \(h\)
Self-Attention
重温一下我们讲解Transformer时提到的Self-Attention,其 \(Query\),\(Keys\) 和 \(Values\) 均为词表征通过一个简单的线性映射矩阵得到的,即可将其表示为
\[Attention(Q,K,V) = Attention(W^QX,W^KX,W^VX)\]
从其注意力分数的计算方法上来看也是一种典型的缩放点积,其关键在于仅对句子本身进行注意力权值计算,使其更能够把握句子中词与词之前的关系,从而提取出句子中的句法特征或语义特征。

小结
这一块对Attention的原理基本已经全部总结了,主要是对自己只是的巩固,以及对之后的实践工作做铺垫,之后有时间再将Attention这块相关的代码写出来。
参考链接
https://zhuanlan.zhihu.com/p/31547842
https://zhuanlan.zhihu.com/p/59698165
https://zhuanlan.zhihu.com/p/53682800
https://zhuanlan.zhihu.com/p/43493999
Attention机制全解的更多相关文章
- Js中this机制全解
JavaScript中有很多令人困惑的地方,或者叫做机制. 但是,就是这些东西让JavaScript显得那么美好而与众不同. 比方说函数也是对 象.闭包.原型链继承等等,而这其中就包括颇让人费解的th ...
- “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第二十四章:等待唤醒机制详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- 深度学习之seq2seq模型以及Attention机制
RNN,LSTM,seq2seq等模型广泛用于自然语言处理以及回归预测,本期详解seq2seq模型以及attention机制的原理以及在回归预测方向的运用. 1. seq2seq模型介绍 seq2se ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- Java IO编程全解(二)——传统的BIO编程
前面讲到:Java IO编程全解(一)——Java的I/O演进之路 网络编程的基本模型是Client/Server模型,也就是两个进程之间进行相互通信,其中服务端提供位置信息(绑定的IP地址和监听端口 ...
- js原型、原型链、作用链、闭包全解
https://www.2cto.com/kf/201711/698876.html [对象.变量] 一个对象就是一个类,可以理解为一个物体的标准化定义.它不是一个具体的实物,只是一个标准.而通过对象 ...
- Springboot整合log4j2日志全解
目录 常用日志框架 日志门面slf4j 为什么选用log4j2 整合步骤 引入Jar包 配置文件 配置文件模版 配置参数简介 Log4j2配置详解 简单使用 使用lombok工具简化创建Logger类 ...
- JVM类加载机制详解(二)类加载器与双亲委派模型
在上一篇JVM类加载机制详解(一)JVM类加载过程中说到,类加载机制的第一个阶段加载做的工作有: 1.通过一个类的全限定名(包名与类名)来获取定义此类的二进制字节流(Class文件).而获取的方式,可 ...
随机推荐
- 2、顺序表的实现(java代码)
1.这里实现了简单的顺序表的,为空判断.是否已满判断,插入.删除,查询元素下标等功能 public class Linear_List { private int[] arr; //用来保存数据 pr ...
- SQLServer的网络协议
一.总结 1.SQL Server访问协议包括Shared Memory.Named Pipes.TCP/IP.VIA四种,多数应用系统都是通过TCP/IP协议访问数据库.安装数据库后需要启用TCP/ ...
- Linux 笔记 - 第十八章 Linux 集群之(一)Keepalived 高可用集群
一.前言 Linux 集群从功能上可以分为两大类:高可用集群和负载均衡集群.此处只讲高可用集群,负载均衡放在下一篇博客讲解. 高可用集群(High Availability Cluster,简称 HA ...
- Day4 总结
- 反射的应用、获取Class类实例
*准备工作: 包结构:* ======================= Person.java代码: package com.atguigu.java; public class Person { ...
- [C++] 重载运算符与类型转换(2)——函数调用运算符和类型转换运算符
1.这两个应该是C++中比较高级的用法了. 一.函数调用运算符 1.重载函数调用运算符(),必须是成员函数,一个类可以定义多个不同版本的调用运算符,相互之间应该在参数数量或者类型上有所区别. ...
- 【面试】我是如何在面试别人Redis相关知识时“软怼”他的
事出有因 Redis是一个分布式NoSQL数据库,因其数据都存储在内存中,所以访问速度极快,因此几乎所有公司都拿它做缓存使用,所以Redis常被称为分布式缓存. 一次我的一个同事让我帮他看Redis相 ...
- 使用uEdit时,在线管理图片功能不可用
把所有的配置文件都配置好了,uedit的在线管理功能图片还是不可用,看了一下源码: 是的,它在img的src属性后边的图片上加上了参数,那肯定不能用啊,所以修改源文件image.js.直接搜索noCa ...
- WebApi简介
简单创建.NET Core WebApi:https://www.cnblogs.com/yanbigfeg/p/9197375.html 登陆验证四种方式:https://www.cnblogs.c ...
- 05、Linux通配符、转义字符、环境变量
问题:作为Linux运维人员,我们有时候也会遇到明明一个文件的名称就在嘴边但就是想不起来的情况.如果就记得一个文件的开头几个字母,想遍历查找出所有以这个关键词开头的文件,该怎么操作呢? 范例:单个查看 ...