目录

引言

自注意力机制介绍

生成Query、Key和Value向量

模型结构与实现

在自然语言处理中的应用


个人主页:东洛的克莱斯韦克-CSDN博客

👀引言

👀在自然语言处理领域,传统的循环神经网络和长短时记忆网络虽然取得了一定的成果,但在处理长序列时会出现梯度消失或梯度爆炸的问题,这限制了它们的性能。

👀为了解决这些问题,谷歌提出了Transformer模型。该模型采用自注意力机制进行信息的交互与传递,具有高效的计算效率和强大的表示能力。

🧠自注意力机制介绍🧠

🧠自注意力机制是一种强大的工具,它允许模型在序列内部的不同位置间直接建立关系,从而提高了模型的性能和灵活性。通过计算注意力权重并生成加权和表示,自注意力机制能够捕捉到序列中的重要长距离依赖关系,并在各种NLP任务中表现出色。

概念

🧠自注意力机制是一种特殊的注意力机制,它通过将序列中的每个位置视为查询(Query),同时作为(Key)和(Value),来计算注意力权重并生成加权和表示。

核心组件

🧠查询(Query)、键(Key)、值(Value):输入序列中的每个元素首先被转换为这三个向量。查询向量用于与键向量进行匹配,值向量则用于生成加权和表示。

🧠注意力权重:通过计算查询向量和键向量的点积(或其他相似度度量),然后经过softmax归一化得到注意力权重。这些权重表示了输入序列中不同位置之间的依赖关系。

生成Query、Key和Value向量

🧠对于序列中的每个嵌入向量,我们会生成对应的Query、Key和Value向量。这通常是通过将嵌入向量与三个不同的权重矩阵(Wq, Wk, Wv)相乘来实现的。这些权重矩阵是随机初始化的,并在训练过程中进行更新。在这个例子中,假设权重矩阵的维度是(64, 512),因此生成的Query、Key和Value向量的维度是64维。生成Query、Key和Value向量

🧠以单词"Games"为例,假设其嵌入向量为X,则:

q = X * Wq

k = X * Wk

v = X * Wv

计算注意力权重

🧠接下来,对于序列中的每个单词(作为Query),我们计算它与序列中其他所有单词(作为Key)之间的相似度。这通常是通过点积(dot product)来实现的,即计算Query向量和Key向量的点积。然后,这些点积值经过softmax函数进行归一化,得到注意力权重。

🧠以单词"Games"为例,当处理它时,我们会计算它与"The"、"2022"、"Beijing"、"Winter"等单词的注意力权重。

加权求和

🧠最后,我们使用注意力权重对Value向量进行加权求和,得到最终的表示向量。这个表示向量将考虑到序列中所有单词与当前单词的相关性。

🧠以单词"Games"为例,其最终的表示向量将是序列中所有单词的Value向量的加权和,其中权重是单词"Games"与这些单词之间的注意力权重。

🧠为了理解自注意力机制,如下是PyTorch框架来编写的一个简单的示例代码

import torch  
import torch.nn as nn  
import torch.nn.functional as F  
  
class SelfAttention(nn.Module):  
    def __init__(self, embed_size, heads):  
        super(SelfAttention, self).__init__()  
        self.embed_size = embed_size  
        self.heads = heads  
        self.head_dim = embed_size // heads  
          
        assert (self.head_dim * heads == embed_size), "Embedding size needs to be divisible by heads"  
          
        self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)  
        self.fc_out = nn.Linear(heads * self.head_dim, embed_size)  
          
    def forward(self, values, keys, query, mask):  
        N = query.shape[0]  
        value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]  
          
        # Split the embedding into self.heads different pieces  
        values = values.reshape(N, value_len, self.heads, self.head_dim)  
        keys = keys.reshape(N, key_len, self.heads, self.head_dim)  
        queries = query.reshape(N, query_len, self.heads, self.head_dim)  
          
        values = self.values(values)   # (N, value_len, heads, head_dim)  
        keys = self.keys(keys)   # (N, key_len, heads, head_dim)  
        queries = self.queries(queries)  # (N, query_len, heads, head_dim)  
          
        # Einsum does matrix multiplication for query, key and then sum the last two dimensions.  
        # query shape: (N, query_len, heads, head_dim), key shape: (N, key_len, heads, head_dim)  
        # output shape: (N, heads, query_len, key_len)  
        energy = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])  
          
        if mask is not None:  
            energy = energy.masked_fill(mask == 0, float("-1e20"))  
          
        attention = torch.softmax(energy / (self.embed_size ** (1/2)), dim=3)  
          
        out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(N, query_len, self.heads * self.head_dim)  
        out = self.fc_out(out)  
          
        return out  
  
# 示例输入  
# 假设有3个序列,每个序列长度为5,嵌入维度为10,头数为2  
embed_size = 10  
heads = 2  
batch_size = 3  
seq_len = 5  
  
# 随机初始化嵌入向量  
values = torch.randn(batch_size, seq_len, embed_size)  
keys = torch.randn(batch_size, seq_len, embed_size)  
query = torch.randn(batch_size, seq_len, embed_size)  
  
# 假设没有mask(在实际应用中,mask通常用于处理填充token)  
mask = None  
  
# 实例化自注意力层  
attention = SelfAttention(embed_size, heads)  
  
# 前向传播  
output = attention(values, keys, query, mask)  
  
print(output.shape)  # 应该输出 (batch_size, seq_len, embed_size)

🏠模型结构与实现🏠

🏠Transformer模型主要由编码器和解码器两部分组成,它们都是由若干个基本的Transformer Encoder/Decoder Block堆叠而成。

嵌入表示层:对于输入文本序列,首先通过输入嵌入层将每个单词转换为其相对应的向量表示。

🏠由于Transformer中没有任何信息能表示单词间的相对位置关系,故需在词嵌入中加入位置编码。

🏠具体来说,序列中每一个单词所在的位置都对应一个向量,这一向量会与单词表示对应相加并送入到后续模块中做进一步处理。

编码器:编码器由多个相同的层堆叠而成,每个层都包含一个Self-Attention层和一个前馈神经网络。

🏠Self-Attention层通过计算输入序列中每个位置之间的相关性,得到一个注意力权重分布,以便更好地进行信息传递。

🏠前馈神经网络则用于捕捉输入序列中的局部信息。

解码器:解码器同样由多个相同的层堆叠而成,但与编码器相比,解码器在Self-Attention层之后还包含一个Encoder-Decoder Attention层。

🏠这个层允许解码器关注编码器的输出,从而利用源语言序列的信息来生成目标语言序列。

✌在自然语言处理中的应用✌

✌Transformer模型在自然语言处理领域取得了广泛的应用,其中最具代表性的模型包括BERTGPT

✌BERT通过使用Transformer模型进行双向上下文信息的捕捉,在多项NLP任务中取得了显著成果;GPT则通过使用自回归的方式进行语言建模,在文本生成、文本摘要等任务中取得了优异表现。

✌此外,Transformer模型还可以用于文本分类、情感分析、问答系统等各种NLP任务中


小编其他文章:

【机器学习】音乐大模型的深入探讨——当机器有了创意,是机遇还是灾难?-CSDN博客

【机器学习】机器的登神长阶——AIGC-CSDN博客

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐