首页 > 其他分享 >Attention机制学习

Attention机制学习

时间:2022-12-26 18:33:45浏览次数:62  
标签:dim attention self Attention 学习 hid 机制 hidden size


Attention机制

回顾RNN结构

  • 讲attention之前先回顾一下RNN的各种结构

N to N

Attention机制学习_Pre-LN

  • 如:语音处理,时间序列处理

N to 1

Attention机制学习_multiattention_02

  • 如:情感分析,输入一段视频判断类型

1 to N

Attention机制学习_人工智能_03

Attention机制学习_attention_04

  • 如:从图像生成文字,从类别生成语音或音乐

N to M

  • 这种就够又叫​​encoder-decoder​​​模型,或​​Seq2Seq​​模型

Attention机制学习_attention_05

Attention机制学习_人工智能_06

  • 如:机器翻译,文本摘要,阅读理解,语音识别…

回归正题Attention

  • 在​​encoder-decoder​​结构中,显然当要处理的信息长度很长的时候,一个c存储不了那么多信息,导致处理精度下降
  • 所以我们打算计算很多个c
  • 这样翻译不同的y的时候,对于x就有不同的权重

Attention机制学习_attention_07

  • 计算结构如下
  • 每一个c会去选取和当前所要输出的y最合适的上下文信息。
  • 具体的,我们用Attention机制学习_人工智能_08来衡量encoder中第j阶段的Attention机制学习_attention_09(hidden state),和当前decoder中第i阶段的相关性
  • 以机器翻译为例
  • 上图标有红色的地方就是和decoder当前阶段最相关的地方,对应的值较大;其他的地方对应的值较小。这里就是attention的精髓所在了——每个decoder的状态对于每个encoder的状态分配注意力(当然,Attention机制学习_人工智能_10
    Attention机制学习_算法_11

  • 接下来就是求Attention机制学习_Pre-LN_12
  • Attention机制学习_算法_13
  • 那么我们的score是怎么计算的呢
  • 最简单的方方法就是直接计算点乘,点积类似计算相似度。
  • 而,attention极值就是来解决这个问题的,定义如下
  • 给定一组向量集合​​value​​​,以及一个向量集合​​query​​​,attention机制就是根据​​query​​​计算​​value​​的加权求和机制

attention的本质思想

Attention机制学习_人工智能_14

Query(Q),Key(K),Value(V),Source是有<Key,Value>的数据对构成

  • 1、给定Target中的某个元素Query,通过计算Query和各个Key的相似性
  • 2、得到每个Key对应Value的权重系数
  • 3、然后对Value进行加权求和,即得到了最终的Attention数值

本质上Attention机制是对Source中元素的Value值进行加权求和,而Query和Key用来计算对应Value的权重系数,可写为如下公式
Attention机制学习_multiattention_15

具体计算可分为两个过程:

  • 1、根据Query和Key计算权重系数(可分为如下两个阶段)
  • 一(阶段一)、根据Query和Key计算两者的相似性
  • 二(阶段二)、对第一阶段的原始分值进行归一化处理
  • 2、根据权重系数对Value进行加权求和

Attention机制学习_Pre-LN_16

attention 的效果

Attention机制学习_attention_17

  • 上图为英语-德语翻译的注意力概率分布(可视化地展示了在英语-德语翻译系统中加入Attention机制后,Source和Target两个句子每个单词对应的注意力分配概率分布。)

主要也就一块代码

class AttDecoder_RNN(nn.Module):
def __init__(self, word_num, hidden_dim, dropp=config.drop_p, max_length=config.max_length):
super(AttDecoder_RNN, self).__init__()
self.word_num = word_num
self.hidden_dim = hidden_dim
self.embed = nn.Embedding(word_num, hidden_dim)
self.gru = nn.GRU(hidden_dim, hidden_dim)
self.dropout = nn.Dropout(dropp)

self.attn = nn.Linear(2 * hidden_dim, max_length)
self.attn_C = nn.Linear(2 * hidden_dim, self.hidden_dim)

self.out = nn.Linear(self.hidden_dim, self.word_num)

def forward(self, encoder_state, input, hidden=None):
batch_size = input.size(0)
if hidden is None:
hidden = t.rand(1, batch_size, self.hidden_dim)

emb = self.embed(input)
emb = self.dropout(emb)

att_w = F.softmax(self.attn(t.cat((emb, hidden[0]), 1)), dim=1) #先用上一层hidden与input拼接,然后通过网络映射到max_length得到权重a,得到权重再softmax
att_c = t.bmm(att_w.unsqueeze(0).permute(1, 0, 2), encoder_state.permute(1, 0, 2)) #用权重a与encoder的hidden相乘得到c,(permute是pytorch调整维度)

output = t.cat((emb, att_c.permute(1, 0, 2)[0]), 1) #再把input与c拼接
output = self.attn_C(output).unsqueeze(0) #将长度映射还原,拼接之后hidden长度会加倍

output, hidden = self.gru(output, hidden)
output = F.log_softmax(self.out(output[0]), dim=1)
return output, hidden, att_w

self-attention模块——扔掉RNN

  • 一般任务的Encoder-Decoder框架中,输入Source和输出Target内容是不一样的,比如一边英文一边中文,Attention机制发生在Target的元素Query和Source中的所有元素之间
  • 而self-attention机制,Attention机制发生在Source内部元素之间或者Target内部元素之间,也可以理解为Target=Source这种特殊情况下的注意力计算机制(就是计算对象发生了变化,Q=K=V)
  • 具体的,比如翻译“I arrived at the bank after crossing the river”,要翻译“bank”是银行还是河岸,需要结合river这个词,所以我们需要在翻译“bank”的时候,river的Attention Score就有较高的值;
  • 而普通的RNN在两词相距较远的时候效果较差,而且顺序处理效果较低
  • 步骤效果如下,思路很简单,就这样就把RNN扔掉了
  • transformer模型中的相似性使用的是缩放点积模型(scaled dot-product attention):
    Attention机制学习_人工智能_18
  • 流程图如下

Attention机制学习_算法_19

  • 不过没有了RNN,encoder过程就没有了hidden state,那怎么办?
  • 我们对每一个word做embedding,然后用embedding代替hidden state来self-attention
  • 所以Q矩阵装的都是word embedding(K,V也一样)
  • Attention机制学习_算法_20是第i个word的embedding,对Attention机制学习_算法_20的attention为下面第一个
  • 注意,在decoder中的self-attention的流程和encoder中的差不多,不过encoder中的word是一次性全部输入进去的,decoder中的word是从一遍生成的(如从左到右),那么对于Attention机制学习_Pre-LN_22是没有机会和Attention机制学习_attention_23做attention的,这个时候我们需要使Attention机制学习_人工智能_24,有Attention机制学习_人工智能_25
  • 这个其实相当于一个masked的操作,就是transformer模型中的masked muti-head attention中在decoder中的操作

优点

  • 优点
  • 引入Self Attention后会更容易捕获句子中长距离的相互依赖的特征
  • Self Attention对于增加计算的并行性也有直接帮助作用

Multi-head Attention模块

  • muti-head attention就是多个self-attention结构的结合,每个head学到不同表示空间中的特征。
  • 将模型分为多个头,形成多个子空间,可以让模型关注不同方面的信息
  • 如下图,两个head学到的特征可能会不同
  • Attention机制学习_算法_26

  • 其实就是把self-attention进行stacking,把每个word的embedding拆分成几块分别作self-attention最后拼接起来

Attention机制学习_算法_27

  • 步骤大致如下

Attention机制学习_人工智能_28

  • 上面那几个Attention机制学习_multiattention_29映射矩阵可以用Attention机制学习_multiattention_30的linear layer实现

Layer Normalization与残差连接

Attention机制学习_Pre-LN_31

可以发现在“Multi-Head Attention”旁还有一条直连的边,这里用的即是ResNet中的残差(F(X)+X)。

  • 原文写的公式是:LayerNorm(X + SubLayer(X)),然后attention的部分就是我们现在要学习的部分SubLayer(X)(即F(x))

LN放的位置探究

就是这么简单的改变,可以大大提升模型的调参难度与学习效率。

  • 在Post-LN中,transfomer对参数的变化十分敏感,需要仔细的调参以及使用warm-up的学习策略,非常的慢。主要的问题再LN的位置,导致layer的梯度范数级增长

简要代码如下

if self.pre_lnorm:
pre = self.self_attn_norm(src)
src = src + self.self_attn(pre, pre, pre, src_mask) # residual connection

pre = self.pff_norm(src)
src = src + self.pff(pre) # residual connection
else:
src = self.self_attn_norm(src + self.self_attn(src, src, src, src_mask)) # residual connection + layerNorm
src = self.pff_norm(src + self.pff(src)) # residual connection + layerNorm

简要实现如下

class MultiHeadAttentionLayer(nn.Module):
def __init__(self, hid_dim, n_heads, dropout, device):
super().__init__()

assert hid_dim % n_heads == 0

self.hid_dim = hid_dim # in paper, 512
self.n_heads = n_heads # in paper, 8
self.head_dim = hid_dim // n_heads # in paper, 512 // 8 = 64

self.fc_q = nn.Linear(hid_dim, hid_dim)
self.fc_k = nn.Linear(hid_dim, hid_dim)
self.fc_v = nn.Linear(hid_dim, hid_dim)

self.fc_o = nn.Linear(hid_dim, hid_dim)

self.dropout = nn.Dropout(dropout)

self.scale = torch.sqrt(torch.FloatTensor([self.head_dim])).to(device) # sqrt(64)

def forward(self, query, key, value, mask = None):

batch_size = query.shape[0]

#query = [batch size, query len, hid dim]
#key = [batch size, key len, hid dim]
#value = [batch size, value len, hid dim]

Q = self.fc_q(query)
K = self.fc_k(key)
V = self.fc_v(value)

#Q = [batch size, query len, hid dim]
#K = [batch size, key len, hid dim]
#V = [batch size, value len, hid dim]

Q = Q.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
K = K.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)
V = V.view(batch_size, -1, self.n_heads, self.head_dim).permute(0, 2, 1, 3)

#Q = [batch size, n heads, query len, head dim]
#K = [batch size, n heads, key len, head dim]
#V = [batch size, n heads, value len, head dim]

energy = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale

#energy = [batch size, n heads, query len, key len]

if mask is not None:
energy = energy.masked_fill(mask == 0, -1e10)

attention = torch.softmax(energy, dim = -1)

#attention = [batch size, n heads, query len, key len]

x = torch.matmul(self.dropout(attention), V) #x = [batch size, n heads, query len, head dim]

# 将x还原成linear layer可以process的size
x = x.permute(0, 2, 1, 3).contiguous()
# contiguous 返回一个内存连续的有相同数据的tensor,如果原tensor内存连续,则返回原tensor. 一般与transpose,permute, view搭配使用
# transpose、permute等维度变换操作后,tensor在内存中不再是连续存储的,而view操作要求tensor的内存连续存储,所以需要contiguous来返回一个contiguous copy


x = x.view(batch_size, -1, self.hid_dim) #x = [batch size, query len, n heads, head dim]

x = self.fc_o(x) #x = [batch size, query len, hid dim]

return x, attention


标签:dim,attention,self,Attention,学习,hid,机制,hidden,size
From: https://blog.51cto.com/u_15923198/5970019

相关文章

  • 带修改的莫队算法学习小记
    简介莫涛大神创造出的离线询问算法的带修改版。算法基础:需要掌握​​莫队算法​​,会打暴搜(暴力)。一个叫莫的双端队列。只支持单点修改操作方法普通的不带修改的莫队算......
  • A Neural Algorithm of Artistic Style论文学习
    ANeuralAlgorithmofArtisticStyle文章大致:算法基于深度神经网络,能将任意图片根据任意画家的风格转化,并提供一种方法了解人类如何创造和感知艺术意象featuremap(特征映......
  • 关系型数据库学习手记——初见倾心PostgreSQL、MySQL、SQLite、MongoDB
    一、关系型数据库系统理论知识1.1学习笔记​​数据库系统概念读书笔记-引言​​数据库系统概念读书笔记-关系数据库数据库系统概念读书笔记-数据库发展史(上)数据库系统概念......
  • 【学习网站链接收藏】PHP开发工程师网站收藏
    PHP1.优雅的CodeIgniter中文文档:​​https://codeigniter.org.cn/user_guide/​​2.Yii2.0权威指南:​​https://www.yiichina.com/doc/guide/2.0/intro-yii​​3.Laravel......
  • 强化学习如何保存模型?
    保存模的关键在于知道决定模型的东西是什么?框架和参数,有了框架保存参数,没有框架,全部保存。模型保存模型保存本质上是保存训练好的参数,便于重复利用模型,随时可以调用。......
  • angular学习笔记
    *ngSwitch1.用法<div[ngSwitch]="num"><div*ngSwitchCase="0">0</div><div*ngSwitchCase="1">1</div><div*ngSwitchDefault>默认的</div></di......
  • .NET机器学习 ML.NET 1.4预览版和模型生成器更新
    ​​ML.NET​​​是面向.NET开发人员的开源和跨平台机器学习框架。​​ML.NET​​​ 还包括​​ModelBuilder​​​ (一个简单的UI工具)和 ​​CLI​​ ,使用自动机......
  • turtle的学习3
    turtle的学习3准备工作新建一个文件创建一个画笔设置画布的颜色代码操作第一种方式'bgcolor'的就是'backgroundcolor'单词的缩写,意思是背景颜色同时要注意,这个......
  • 关系型数据库与非关系型数据库的区别(学习了解记录)
    前言​ 在工作中经常遇到不同的使用,对他们彼此间的关系不甚清楚,所以抽时间整理一下网络大神的详解,作为自己的学习笔记。关系型数据库(SQL)​ 关系型数据库是指使用关系模......
  • 复现经典:《统计学习方法》​第17章 潜在语义分析
    第17章潜在语义分析本文是李航老师的《统计学习方法》一书的代码复现。作者:黄海广备注:代码都可以在github中下载。我将陆续将代码发布在公众号“机器学习初学者”,可以在这......