从零理解Transformer架构:注意力机制与位置编码
从零理解Transformer架构:注意力机制与位置编码
Transformer架构自2017年提出以来,已成为自然语言处理和深度学习领域的基石。其核心创新是使用注意力机制,完全抛弃了传统的卷积神经网络(CNN)和循环神经网络(RNN)。本文将从零开始解析Transformer架构,重点介绍其中的注意力机制与位置编码,并附带PyTorch代码实现。
一、Transformer架构概览
Transformer是由Encoder和Decoder两部分组成,通常用于序列到序列的任务,如机器翻译、文本生成等。Transformer的核心思想是通过自注意力机制(Self-Attention)来捕捉输入序列中的全局依赖关系,而不是像传统RNN那样顺序地处理信息。
1.1 Encoder-Decoder结构
Transformer架构可以简化为两大模块:
- Encoder:负责对输入序列进行编码,产生对输入数据的理解。
- Decoder:基于Encoder的输出,生成目标序列。
每个Encoder和Decoder都是由多个相同的子层(Layer)堆叠而成。每个Encoder层包括:
- 自注意力层(Self-Attention)
- 前馈神经网络(Feed-Forward Neural Network)
- 残差连接和层归一化
每个Decoder层与Encoder层类似,但是它还包括一个额外的跨注意力层(Cross-Attention),用于从Encoder的输出中获取信息。
二、注意力机制
在Transformer中,最关键的技术是注意力机制(Attention Mechanism)。传统的RNN是通过递归计算逐步更新信息的,而注意力机制则通过“赋予”每个输入元素不同的权重,使得模型能够灵活地关注输入序列中的重要部分。这种方法能够高效地并行化计算并更好地捕捉长程依赖。
2.1 注意力机制的原理
注意力机制的核心思想是:对于每一个输入的单元(如单词、词向量),我们都要计算它与其他输入单元的相似度,然后基于相似度加权求和,从而得到该单元的“注意力”向量。
常见的注意力计算方法是Scaled Dot-Product Attention,其计算公式为:
其中:
- QQ:查询(Query)矩阵
- KK:键(Key)矩阵
- VV:值(Value)矩阵
- dkdk :键的维度,作为缩放因子
2.2 计算过程
- 计算相似度:通过点积计算查询向量QQ与键向量KK的相似度。
- 缩放:通过除以dkdk 进行缩放,避免点积值过大。
- 应用Softmax:对相似度结果进行Softmax归一化,得到每个值的权重。
- 加权求和:用这些权重对值VV进行加权求和,得到输出。
2.3 PyTorch代码实现
import torch
import torch.nn.functional as F
def scaled_dot_product_attention(Q, K, V):
# 计算相似度
matmul_qk = torch.matmul(Q, K.transpose(-2, -1))
# 缩放相似度
d_k = Q.size(-1)
scaled_attention_logits = matmul_qk / torch.sqrt(torch.tensor(d_k, dtype=torch.float32))
# 应用Softmax
attention_weights = F.softmax(scaled_attention_logits, dim=-1)
# 加权求和
output = torch.matmul(attention_weights, V)
return output, attention_weights
# 示例数据
Q = torch.randn(1, 5, 64) # 查询向量
K = torch.randn(1, 5, 64) # 键向量
V = torch.randn(1, 5, 64) # 值向量
output, attention_weights = scaled_dot_product_attention(Q, K, V)
print("Output Shape:", output.shape)
print("Attention Weights Shape:", attention_weights.shape)
在此代码中,Q、K和V分别是查询、键和值的矩阵,scaled_dot_product_attention函数实现了注意力机制的计算。
三、位置编码(Positional Encoding)
由于Transformer完全基于自注意力机制,输入的序列数据没有显式的顺序信息,因此需要引入位置编码来为每个单词(或词向量)添加位置信息。位置编码通过向每个词的表示中加入一个特定的向量,使得模型能够区分单词在句子中的顺序。
3.1 位置编码的数学公式
位置编码通常采用正弦和余弦函数来生成,这些函数的频率随着维度的增加而变化。公式为:
其中:
- pospos:表示单词在句子中的位置
- ii:位置编码向量中的维度索引
- dmodeldmodel :词向量的维度
3.2 位置编码的作用
位置编码为每个位置生成唯一的向量,并将其加到输入的嵌入向量中。通过这种方式,Transformer能够区分不同位置的词语,同时保持序列中的顺序信息。
3.3 PyTorch代码实现
import numpy as np
def positional_encoding(seq_len, d_model):
pe = np.zeros((seq_len, d_model))
position = np.arange(0, seq_len).reshape(-1, 1)
div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))
pe[:, 0::2] = np.sin(position * div_term) # 偶数维度
pe[:, 1::2] = np.cos(position * div_term) # 奇数维度
return torch.tensor(pe, dtype=torch.float32)
# 示例:生成一个长度为10,维度为512的位置编码
seq_len = 10
d_model = 512
pe = positional_encoding(seq_len, d_model)
print(pe.shape)
这段代码生成了一个形状为seq_len×d_modelseq_len×d_model的矩阵,其中每一行是一个位置的编码。
四、Transformer层的实现
4.1 Encoder层
一个标准的Encoder层由以下几个主要组件组成:
- 自注意力机制(Self-Attention)
- 前馈神经网络(Feed Forward Network)
- 残差连接和层归一化(Residual Connection & Layer Normalization)
Encoder层的计算顺序是:
- 输入首先通过自注意力机制。
- 经过前馈神经网络处理。
- 在每个子层之间有残差连接,并进行层归一化。
4.2 PyTorch代码实现
class TransformerEncoderLayer(torch.nn.Module):
def __init__(self, d_model, n_heads, ff_hidden_dim):
super(TransformerEncoderLayer, self).__init__()
self.self_attention = torch.nn.MultiheadAttention(d_model, n_heads)
self.feed_forward = torch.nn.Sequential(
torch.nn.Linear(d_model, ff_hidden_dim),
torch.nn.ReLU(),
torch.nn.Linear(ff_hidden_dim, d_model)
)
self.layer_norm1 = torch.nn.LayerNorm(d_model)
self.layer_norm2 = torch.nn.LayerNorm(d_model)
self.dropout = torch.nn.Dropout(0.1)
def forward(self, x):
# 自注意力层
attention_output, _ = self.self_attention(x, x, x)
x = self.layer_norm1(x + self.dropout(attention_output)) # 残差连接 + 层归一化
# 前馈神经网络
ff_output = self.feed_forward(x)
x = self.layer_norm2(x + self.dropout(ff_output)) # 残差连接 + 层归一化
return x
# 示例:初始化一个Encoder层
encoder_layer = TransformerEncoderLayer(d_model=512, n_heads=8, ff_hidden_dim=2048)
input_tensor = torch.randn(10, 32, 512) # (seq_len, batch_size, d_model)
output = encoder_layer(input_tensor)
print(output.shape) # 输出形状
五、总结
本文深入解析了Transformer架构的核心机制——注意力机制和位置编码。通过具体的数学公式与PyTorch代码实现,帮助理解Transformer如何通过自注意力机制来捕捉序列中的长程依赖,同时通过位置编码来补充顺序信息。希望通过这篇文章,读者能够对Transformer的内部工作原理有更深入的了解,并能够动手实现自己的Transformer模型。
在实际应用中,Transformer已经被广泛应用于自然语言处理、图像生成等领域,成为现代深度学习模型的基础架构之一。