### 关于《Attention is All You Need》的代码复现教程或实现示例
#### Transformer模型的核心组件概述
Transformer是一种基于自注意力机制(Self-Attention Mechanism)的神经网络架构,其设计初衷是为了替代传统RNN/CNN在序列建模中的应用。为了弥补纯注意力机制缺乏时序信息的问题,论文提出了位置编码(Positional Encoding)的概念[^1]。
#### 自注意力机制的核心公式
自注意力机制通过计算查询(Query)、键(Key)和值(Value)之间的关系来捕捉输入序列的不同部分的重要性。具体而言,其核心公式如下所示[^2]:
\[ \text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V \]
其中 \( Q \), \( K \), 和 \( V \) 是分别由输入矩阵线性变换得到的查询、键和值向量;\( d_k \) 表示键向量的维度大小。
#### 位置编码(Positional Encoding)
由于注意力机制本身无法捕获序列中的时间/空间顺序信息,因此需要显式地加入位置编码。位置编码可以采用正弦和余弦函数的形式定义,从而使得模型能够学习到不同位置上的特征差异:
对于给定的位置 \( pos \),以及第 \( i \)-维的位置编码分量:
\[ PE_{(pos, 2i)} = \sin(pos / 10000^{2i/d}) \]
\[ PE_{(pos, 2i+1)} = \cos(pos / 10000^{2i/d}) \]
这种形式化方法允许模型自动推断任意长度序列的位置信息。
#### PyTorch实现示例
下面提供了一个简单的PyTorch版本的Transformer模块实现:
```python
import math
import torch
import torch.nn as nn
import torch.nn.functional as F
class MultiHeadedAttention(nn.Module):
def __init__(self, num_heads, dim_model, dropout=0.1):
super(MultiHeadedAttention, self).__init__()
assert dim_model % num_heads == 0
self.d_k = dim_model // num_heads
self.num_heads = num_heads
self.linears = clones(nn.Linear(dim_model, dim_model), 4)
self.attn = None
self.dropout = nn.Dropout(p=dropout)
def forward(self, query, key, value, mask=None):
if mask is not None:
mask = mask.unsqueeze(1)
nbatches = query.size(0)
query, key, value = \
[l(x).view(nbatches, -1, self.num_heads, self.d_k).transpose(1, 2)
for l, x in zip(self.linears, (query, key, value))]
x, self.attn = attention(query, key, value, mask=mask,
dropout=self.dropout)
x = x.transpose(1, 2).contiguous().view(nbatches, -1, self.num_heads * self.d_k)
return self.linears[-1](x)
def attention(query, key, value, mask=None, dropout=None):
scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(query.size(-1))
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
p_attn = F.softmax(scores, dim=-1)
if dropout is not None:
p_attn = dropout(p_attn)
return torch.matmul(p_attn, value), p_attn
def positional_encoding(max_len, d_model, device=torch.device('cpu')):
pe = torch.zeros(max_len, d_model, device=device)
position = torch.arange(0., max_len, device=device).unsqueeze(1)
div_term = torch.exp(torch.arange(0., d_model, 2, device=device) *
-(math.log(10000.) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
return pe.unsqueeze(0)
```
以上代码片段展示了如何构建一个多头注意力层及其辅助函数`attention()`,同时也给出了位置编码的具体实现方式。
#### 总结
通过对《Attention is All You Need》的理解与实践,我们可以看到Transformer模型的强大之处在于它的高效性和灵活性。无论是机器翻译还是其他NLP任务,Transformer都展现出了卓越的表现力。