介绍
实现 Transformer块,这是GPT和其他大语言模型架构的基本构建块。在参数量为 1.24亿 的GPT-2架构中,这个块被 重复了许多次
它结合了我们之前提及的多个概念:
- 掩码多头注意力
- 层归一化
- dropout
- 前馈层
- GELU激活函数
Transformer块核心思想
自注意力机制 在 多头注意力块 中用于 识别 和 分析 输入序列中 元素之间的关系。
相比之下,前馈神经网络则在每个位置上对数据进行单独的修改。
这种组合不仅提供了对输入更细致的理解和处理,而且提升了模型处理复杂数据模式的整体能力

Transformer块示意图。输入的词元被嵌入到 768 维的向量中。每一行对应一个词元的向量表示。Transformer块的输出是与输入具有相同维度的向量,这些向量可以传递到大语言模型的后续层中
实现
准备
准备
从 大模型原理:全部代码 复制以下类或函数:
- MultiHeadAttention
- GELU
- FeedForward
- LayerNorm
创建 TransformerBlock块类
这段代码定义 TransformerBlock 类,该类实现功能如下:
层归一化(LayerNorm)应用于这两个组件之前。这种方法也被称为 前层归一化(Pre-LayerNorm)。较早的架构(如最初的Transformer模型)在自注意力和前馈神经网络之后才应用层归一化,这种方法被称为 后层归一化(Post-LayerNorm),这通常会导致较差的训练效果。
多头注意力机制(MultiHeadAttention)。配置字典(cfg,比如GPT_CONFIG_124M)进行配置。
前馈神经网络(FeedForward)。配置字典(cfg,比如GPT_CONFIG_124M)进行配置。
dropout 应用于这两个组件之后,以便对模型进行正则化并防止过拟合。
TransformerBlock类还实现了前向传播,其中每个组件后面都跟着一个 快捷连接,将块的输入加到其输出上。这个关键特性有助于在训练过程中使梯度在网络中流动,并改善深度模型的学习效果
class TransformerBlock(nn.Module):
def __init__(self, cfg):
super().__init__()
self.att = MultiHeadAttention(
d_in=cfg["emb_dim"],
d_out=cfg["emb_dim"],
context_length=cfg["context_length"],
num_heads=cfg["n_heads"],
dropout=cfg["drop_rate"],
qkv_bias=cfg["qkv_bias"])
self.ff = FeedForward(cfg)
self.norm1 = LayerNorm(cfg["emb_dim"])
self.norm2 = LayerNorm(cfg["emb_dim"])
self.drop_shortcut = nn.Dropout(cfg["drop_rate"])
def forward(self, x):
# 在注意力块中添加快捷连接
shortcut = x
x = self.norm1(x)
x = self.att(x)
x = self.drop_shortcut(x)
# 将原始输入添加回来
x = x + shortcut
# 在前馈层中添加快捷链接
shortcut = x
x = self.norm2(x)
x = self.ff(x)
x = self.drop_shortcut(x)
# 将原始输入添加回来
x = x + shortcut
return x
执行
使用之前定义的 GPT_CONFIG_124M 配置字典来实例化一个 Transformer 块,并输入一些测试数据:
GPT_CONFIG_124M = {
"vocab_size": 50257, # 词汇表大小
"context_length": 1024, # 上下文长度
"emb_dim": 768, # 嵌入维度
"n_heads": 12, # 注意力头的数量
"n_layers": 12, # 层数
"drop_rate": 0.1, # dropout率
"qkv_bias": False # 查询-键-值偏置
}
torch.manual_seed(123)
x = torch.rand(2, 4, 768)
block = TransformerBlock(GPT_CONFIG_124M)
output = block(x)
print("输入的 shape:", x.shape)
print("输出的 shape:", output.shape)
执行结果:
输入的 shape: torch.Size([2, 4, 768])
输出的 shape: torch.Size([2, 4, 768])
由打印结果可知:Transformer块在 输出中维持了输入的维度,这表明Transformer架构在处理数据序列时不会改变它们在网络中的形状。
提示:保持形状不变并非偶然,而是设计的,每个输出向量直接对应一个输入向量,保持一一对应的关系。
总结
实现了Transformer块(结合了层归一化、前馈神经网络、GELU激活函数和快捷连接),具备了构建GPT架构所需的所有构建块。如图

提示:其中黑色勾选标记表示我们已构建完成的块