其他
终于把Transformer中的注意力机制搞懂了!!
大家好,我是小寒
今天给大家详细介绍一下 Transformer 中的自注意力机制。
自注意力机制(Self-Attention)
自注意力机制的基本思想是,根据输入序列中的每个元素,计算它与其他所有元素之间的相关性(称为“注意力权重”),并根据这些权重对输入序列进行加权求和,从而得到一个新的表示。
这个新表示包含了序列中所有元素的信息,但更侧重于与当前元素相关的重要部分。
自注意力机制的计算过程包括以下几个步骤。
计算查询(Query)、键(Key)和值(Value)
对于序列中的每个元素,先生成对应的查询向量 Q、键向量 K 和值向量 V。 这些向量是通过线性变换从输入向量生成的。 假设输入向量为
其中,、 和 是可学习的权重矩阵。
计算注意力分数
对于每个查询向量 ,通过点积的方式计算它与所有键向量 的相似度,得到注意力分数。 为了稳定训练过程,这些分数会除以 ,其中 是键向量的维度。 计算注意力权重
将注意力分数通过Softmax函数转换为注意力权重,使得它们和为1。
计算注意力输出
注意力输出是值向量的加权和。
从头开始实现自注意力
1.数据准备
sentence = 'The quick brown fox jumps over a lazy dog'
dc = {s: i for i, s in enumerate(sorted(sentence.replace(',', '').split()))}
print(dc)
#{'The': 0, 'a': 1, 'brown': 2, 'dog': 3, 'fox': 4, 'jumps': 5, 'lazy': 6, 'over': 7, 'quick': 8}
r = [dc[i] for i in sentence.replace(',', '').split()]
sentence_int = torch.tensor(r)
print(sentence_int)
#tensor([0, 8, 2, 4, 5, 7, 1, 6, 3])
2.嵌入句子
import torch
import torch.nn as nn
vocab_size = 50000 # Assume a large vocabulary size
torch.manual_seed(123)
embed = nn.Embedding(vocab_size, 3)
embedded_sentence = embed(sentence_int).detach()
print(embedded_sentence)
该句子现在表示为一个 9x3 矩阵,每个单词被转换为一个三维的向量。
3.自注意力机制
torch.manual_seed(123)
d = embedded_sentence.shape[1] # Dimension of embeddings
d_q, d_k, d_v = 2, 2, 4 # Dimensions for query, key, and value matrices
W_query = torch.nn.Parameter(torch.rand(d, d_q))
W_key = torch.nn.Parameter(torch.rand(d, d_k))
W_value = torch.nn.Parameter(torch.rand(d, d_v))
query = embedded_sentence @ W_query
key = embedded_sentence @ W_key
value = embedded_sentence @ W_value
4.计算注意力分数
注意力分数通过查询和键矩阵的点积计算,然后进行缩放。
import math
import torch.nn.functional as F
attention_scores = query @ key.T
attention_scores = attention_scores / math.sqrt(d_k)
attention_weights = F.softmax(attention_scores, dim=-1)
5.生成上下文向量
最后,我们使用注意权重来计算上下文向量。
context_vector = attention_weights @ value
print(context_vector)
6.封装在模块中
下面,我们来总结一下,将上述代码封装在 python 模块中。
class SelfAttention(nn.Module):
def __init__(self, d, d_q, d_k, d_v):
super(SelfAttention, self).__init__()
self.d = d
self.d_q = d_q
self.d_k = d_k
self.d_v = d_v
self.W_query = nn.Parameter(torch.rand(d, d_q))
self.W_key = nn.Parameter(torch.rand(d, d_k))
self.W_value = nn.Parameter(torch.rand(d, d_v))
def forward(self, x):
Q = x @ self.W_query
K = x @ self.W_key
V = x @ self.W_value
attention_scores = Q @ K.T / math.sqrt(self.d_k)
attention_weights = F.softmax(attention_scores, dim=-1)
context_vector = attention_weights @ V
return context_vector
7.使用自注意力模块
我们实例化 SelfAttention 模块并通过它传递嵌入的句子。
sa = SelfAttention(d=3, d_q=2, d_k=2, d_v=4)
cv = sa(embedded_sentence)
print(cv.shape)
print(cv)
最后
—
今天的分享就到这里。如果觉得近期的文章不错,请点赞,转发安排起来。欢迎大家进高质量 python 学习群「进群方式:加我微信,备注 “python”」
往期回顾
Fashion-MNIST 服装图片分类-Pytorch实现