查看原文
其他

终于把Transformer中的注意力机制搞懂了!!

程序员小寒 程序员学长
2024-09-13

大家好,我是小寒

今天给大家详细介绍一下 Transformer 中的自注意力机制。

Transformer 中的自注意力机制是该模型的核心组件之一,负责捕捉序列数据中的依赖关系,使得模型能够在处理长距离依赖问题时更加高效

自注意力机制(Self-Attention)

自注意力机制的基本思想是,根据输入序列中的每个元素,计算它与其他所有元素之间的相关性(称为“注意力权重”),并根据这些权重对输入序列进行加权求和,从而得到一个新的表示。

这个新表示包含了序列中所有元素的信息,但更侧重于与当前元素相关的重要部分。

自注意力机制的计算过程包括以下几个步骤。

  • 计算查询(Query)、键(Key)和值(Value)

    对于序列中的每个元素,先生成对应的查询向量 Q、键向量 K 和值向量 V。
    这些向量是通过线性变换从输入向量生成的。

    假设输入向量为

    其中, 是可学习的权重矩阵。

  • 计算注意力分数

    对于每个查询向量 ,通过点积的方式计算它与所有键向量 的相似度,得到注意力分数。

    为了稳定训练过程,这些分数会除以 ,其中   是键向量的维度。

  • 计算注意力权重

    将注意力分数通过Softmax函数转换为注意力权重,使得它们和为1。

  • 计算注意力输出

    注意力输出是值向量的加权和。

从头开始实现自注意力

我们将使用 PyTorch 实现一个简单的自注意力机制。
在本示例中,我们将使用句子 "The quick brown fox jumps over a lazy dog" 并遵循自注意力过程的每个步骤。

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实现

python 探索性数据分析(EDA)案例分享

深度学习案例分享 | 房价预测 - PyTorch 实现

万字长文 |  面试高频算法题之动态规划系列

面试高频算法题之回溯算法(全文六千字)  

    



如果对本文有疑问可以加作者微信直接交流。

继续滑动看下一个
程序员学长
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存