Chapter4.1 Coding an LLM architecture

[复制链接]
发表于 2025-11-14 01:46:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
4 Implementing a GPT model from Scratch To Generate Text



  • 本章节包罗

    • 编写一个雷同于GPT的大型语言模子(LLM),这个模子可以被训练来天生雷同人类的文本。
    • Normalizing layer activations to stabilize neural network training
    • 在深度神经网络中添加shortcut connections,以更有用地训练模子
    • 实现 Transformer 模块以创建差别规模的 GPT 模子
    • 盘算 GPT 模子的参数数目及其存储需求
    在上一章中,学习了多头注意力机制并对其举行了编码,它是LLMs的焦点组件之一。在本章中,将编写 LLM 的其他构建块,并将它们组装成雷同 GPT 的模子
    ​

       

4.1 Coding an LLM architecture



  • 诸如GPT和Llama等模子,基于原始Transformer架构中的decoder部分,因此,这些LLM通常被称为"decoder-like" LLMs,与传统的深度学习模子相比,LLM规模更大,这紧张归因于它们巨大的参数数目,而非代码量。由于它的很多组件都是重复的,下图提供了雷同 GPT LLM 的自上而下视图
​

本章将具体构建一个最小规模的GPT-2模子(1.24亿参数),并展示怎样加载预训练权重以兼容更大规模的模子。


  • 1.24亿参数GPT-2模子的设置细节包罗:
    1. GPT_CONFIG_124M = {
    2.     "vocab_size": 50257,    # Vocabulary size
    3.     "context_length": 1024, # Context length
    4.     "emb_dim": 768,         # Embedding dimension
    5.     "n_heads": 12,          # Number of attention heads
    6.     "n_layers": 12,         # Number of layers
    7.     "drop_rate": 0.1,       # Dropout rate
    8.     "qkv_bias": False       # Query-Key-Value bias
    9. }
    复制代码
    我们使用简短的变量名以克制后续代码行过长

    • "vocab_size" 词汇表巨细,由 BPE tokenizer 支持,值为 50,257。
    • "context_length" 模子的最大输入标记数目,通过 positional embeddings 实现。
    • "emb_dim" token输入的嵌入巨细,将每个token转换为 768 维向量。
    • "n_heads" 多头注意力机制中的注意力头数目。
    • "n_layers" 是模子中 transformer 块的数目
    • "drop_rate" 是 dropout 机制的强度,第 3 章讨论过;0.1 表现在训练期间抛弃 10% 的潜伏单位以缓解过拟合
    • "qkv_bias" 决定多头注意力机制(第 3 章)中的 Linear 层在盘算查询(Q)、键(K)和值(V)张量时是否包罗偏置向量;我们将禁用此选项,这是当代 LLMs 的标准做法;然而,我们将在第 5 章将 OpenAI 的预训练 GPT-2 权重加载到我们的重新实现时重新讨论这一点。

  • 下图中的方框展示了我们为实现终极 GPT 架构所需处理处罚的各个概念的序次。我们将从第一步开始,即一个我们称为 DummyGPTModel 的 GPT 骨架占位符:
    ​

    1. import torch
    2. import torch.nn as nn
    3. class DummyGPTModel(nn.Module):
    4.     def __init__(self, cfg):
    5.         super().__init__()
    6.         self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])
    7.         self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])
    8.         self.drop_emb = nn.Dropout(cfg["drop_rate"])
    9.         
    10.         # Use a placeholder for TransformerBlock
    11.         self.trf_blocks = nn.Sequential(
    12.             *[DummyTransformerBlock(cfg) for _ in range(cfg["n_layers"])])
    13.         
    14.         # Use a placeholder for LayerNorm
    15.         self.final_norm = DummyLayerNorm(cfg["emb_dim"])
    16.         self.out_head = nn.Linear(
    17.             cfg["emb_dim"], cfg["vocab_size"], bias=False
    18.         )
    19.     def forward(self, in_idx):
    20.         batch_size, seq_len = in_idx.shape
    21.         tok_embeds = self.tok_emb(in_idx)
    22.         pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))
    23.         x = tok_embeds + pos_embeds
    24.         x = self.drop_emb(x)
    25.         x = self.trf_blocks(x)
    26.         x = self.final_norm(x)
    27.         logits = self.out_head(x)
    28.         return logits
    29. class DummyTransformerBlock(nn.Module):
    30.     def __init__(self, cfg):
    31.         super().__init__()
    32.         # A simple placeholder
    33.     def forward(self, x):
    34.         # This block does nothing and just returns its input.
    35.         return x
    36. class DummyLayerNorm(nn.Module):
    37.     def __init__(self, normalized_shape, eps=1e-5):
    38.         super().__init__()
    39.         # The parameters here are just to mimic the LayerNorm interface.
    40.     def forward(self, x):
    41.         # This layer does nothing and just returns its input.
    42.         return x
    复制代码

    • DummyGPTModel:简化版的 GPT 类模子,使用 PyTorch 的 nn.Module 实现。
    • 模子组件:包罗标记嵌入、位置嵌入、抛弃层、变更器块、层归一化和线性输出层。
    • 设置字典:设置通过 Python 字典传入,如 GPT_CONFIG_124M,用于通报模子设置。
    • forward 方法:形貌数据从输入到输出的完备流程。盘算嵌入 → 应用 dropout → 通过 transformer blocks 处理处罚 → 应用归一化 → 天生 logits。
    • 占位符:DummyLayerNorm 和 DummyTransformerBlock 是待实现的组件。

  • 数据运动:下图提供了 GPT 模子中数据运动的高条理概述。
    ​

    使用 tiktoken 分词器对由 GPT 模子的两个文本输入构成的批次举行分词:
    1. import tiktoken
    2. tokenizer = tiktoken.get_encoding("gpt2")
    3. batch = []
    4. txt1 = "Every effort moves you"
    5. txt2 = "Every day holds a"
    6. batch.append(torch.tensor(tokenizer.encode(txt1)))
    7. batch.append(torch.tensor(tokenizer.encode(txt2)))
    8. batch = torch.stack(batch, dim=0)
    9. print(batch)
    10. """输出"""
    11. tensor([[6109, 3626, 6100,  345],
    12.         [6109, 1110, 6622,  257]]
    13.       )
    复制代码
    接下来,我们初始化一个包罗 1.24 亿参数的 DummyGPTModel 实例,并将 tokenized batch 输入此中。
    1. torch.manual_seed(123)
    2. model = DummyGPTModel(GPT_CONFIG_124M)
    3. logits = model(batch)
    4. print("Output shape:", logits.shape)
    5. print(logits)
    6. """输出"""
    7. Output shape: torch.Size([2, 4, 50257])
    8. tensor([[[-0.9289,  0.2748, -0.7557,  ..., -1.6070,  0.2702, -0.5888],
    9.          [-0.4476,  0.1726,  0.5354,  ..., -0.3932,  1.5285,  0.8557],
    10.          [ 0.5680,  1.6053, -0.2155,  ...,  1.1624,  0.1380,  0.7425],
    11.          [ 0.0447,  2.4787, -0.8843,  ...,  1.3219, -0.0864, -0.5856]],
    12.         [[-1.5474, -0.0542, -1.0571,  ..., -1.8061, -0.4494, -0.6747],
    13.          [-0.8422,  0.8243, -0.1098,  ..., -0.1434,  0.2079,  1.2046],
    14.          [ 0.1355,  1.1858, -0.1453,  ...,  0.0869, -0.1590,  0.1552],
    15.          [ 0.1666, -0.8138,  0.2307,  ...,  2.5035, -0.3055, -0.3083]]],
    16.        grad_fn=<UnsafeViewBackward0>)
    复制代码

    • 输出张量:输出张量有两行,分别对应两个文本样本。每个文本样本由 4 个标记构成;每个标记是一个 50,257 维的向量,这与标记器的词汇表巨细划一。
    • 嵌入维度:50,257 维对应词汇表中的唯一标记,后处理处罚阶段将其转换回 token IDs 并解码为单词。
       

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表