self.attention 和attention 有什么区别

从字面意思上来理解其实self.attention就是自己和自己做相识度计算,其实就是每个词和句子中其他词计算相识度,利用上下文增强目标词的表达。

image-20220618160217326

Q、K、V三个矩阵来自同一个输入,首先我们要计算Q和K之间的点乘,然后为了防止其过大,会进行一个缩放,具体操作就是 Q * K / \sqrt{ d_k } 这里的d_k指的是每个单词embedding的维度 ,然后送入softmax将其结果归一化为概率分布,然后再乘以V得到权重求和的表示,总结下操作可以表示为 Attention(Q,K,V)=softmax(\frac{QK^T}{\sqrt{d_k}})V

简单用torch实现下

#embedding [batch_size, seq, d_model]
query, key, value = embedding, embedding, embedding
self.Q = nn.Linear(d_model, d_model)
self.K = nn.Linear(d_model, d_model)
self.V = nn.Linear(d_model, d_model)
​
Q = self.Q(query).view(batch_size, -1, n_head, d_head).premute(0, 2, 1, 3)
K = self.K(key).view(batch_size, -1, n_head, d_head).premute(0, 2, 1, 3)
V = self.V(value).view(batch_size, -1, n_head, d_head).premute(0, 2, 1, 3)
​
attn = nn.softmax(torch.matmul(Q, K.transpose(2, 3))/math.sqrt(d_model))
​
context = torch.matmul(attn, V).transpose(1, 2)
context = context.contiguous().view(batch_size, -1, self.d_model)
复制代码

传统的attention一开始是使用再Seq2Seq结构上,将encoder读取输入的句子将其转换为一个定长的向量,然后再输入decoder端一个一个的解码,如果句子太长encoder很难将句子的信息转化为定长的向量,而且类似于rnn这种结构很容易存在长程梯度消失的问题,于是引入attention注意力机制,结构如下:

image-20220618171454365

  • 首先我们利用RNN结构得到encoder中的hidden state [公式]
  • 假设当前decoder的hidden state 是 [公式] ,我们可以计算每一个输入位置j与当前输出位置的关联性, [公式] ,写成相应的向量形式即为 [公式] ,其中 [公式] 是一种相关性的算符,例如常见的有点乘形式 [公式] ,加权点乘 [公式] ,加和 [公式] 等等。
  • 对于 [公式] 进行softmax操作将其normalize得到attention的分布, [公式] ,展开形式为 [公式]
  • 利用 [公式] 我们可以进行加权求和得到相应的context vector [公式]
  • 由此,我们可以计算decoder的下一个hidden state [公式] 以及该位置的输出 [公式]

这里关键的操作是计算encoder与decoder state之间的关联性的权重,得到Attention分布,从而对于当前输出位置得到比较重要的输入位置的权重,在预测输出时相应的会占较大的比重。

\

猜你喜欢

转载自juejin.im/post/7110508153812287519