👀引言
👀在自然语言处理领域,传统的循环神经网络和长短时记忆网络虽然取得了一定的成果,但在处理长序列时会出现梯度消失或梯度爆炸的问题,这限制了它们的性能。
👀为了解决这些问题,谷歌提出了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模型在自然语言处理领域取得了广泛的应用,其中最具代表性的模型包括BERT和GPT。
✌BERT通过使用Transformer模型进行双向上下文信息的捕捉,在多项NLP任务中取得了显著成果;GPT则通过使用自回归的方式进行语言建模,在文本生成、文本摘要等任务中取得了优异表现。
✌此外,Transformer模型还可以用于文本分类、情感分析、问答系统等各种NLP任务中