当前位置: 首页 > news >正文

【大模型入门】3.从头实现GPT模型以生成文本

every blog every motto: You can do more than you think.
https://blog.csdn.net/weixin_39190382?type=blog

0. 前言

从头实现 GPT 模型以生成文本

1. 正文

(Implementing a GPT model from Scratch To Generate Text )

from importlib.metadata import versionimport matplotlib
import tiktoken
import torchprint("matplotlib version:", version("matplotlib"))
print("torch version:", version("torch"))
print("tiktoken version:", version("tiktoken"))
matplotlib version: 3.9.0
torch version: 2.4.0
tiktoken version: 0.7.0
  • 在本章中,我们实现了一个类似 GPT 的大语言模型(LLM)架构;下一章将专注于训练这个 LLM。

4.1 编码一个大语言模型(LLM)架构

(Coding an LLM architecture)

  • 第一章讨论了像 GPT 和 Llama 这样的模型,这些模型按顺序生成单词,并且基于原始 Transformer 架构的解码器部分。
  • 因此,这些大语言模型通常被称为“解码器式”大语言模型。
  • 与传统的深度学习模型相比,大语言模型通常更大,主要是由于它们巨大的参数量,而不是代码的多少。
  • 我们将看到,大语言模型的架构中有许多元素是重复的。
  • 在前几章中,我们使用了较小的嵌入维度来简化令牌输入和输出,以便于说明,确保它们适合在一页纸上显示。

  • 在本章中,我们考虑类似于小型 GPT-2 模型的嵌入和模型大小。

  • 我们将特别编写最小 GPT-2 模型的架构(1.24 亿个参数),如 Radford 等人的 Language Models are Unsupervised Multitask Learners 中所述(请注意,初始报告将其列为 1.17 亿参数,但后来在模型权重库中进行了更正)。

  • 第 6 章将展示如何将预训练的权重加载到我们的实现中,这将与 3.45 亿、7.62 亿和 15.42 亿参数的模型大小兼容。

  • 124 亿参数的 GPT-2 模型的配置细节包括:

GPT_CONFIG_124M = {"vocab_size": 50257,    # Vocabulary size"context_length": 1024, # Context length"emb_dim": 768,         # Embedding dimension"n_heads": 12,          # Number of attention heads"n_layers": 12,         # Number of layers"drop_rate": 0.1,       # Dropout rate"qkv_bias": False       # Query-Key-Value bias
}
  • 我们使用简短的变量名,以避免后续代码行过长
  • "vocab_size" 表示词汇表大小为 50,257 个词,这由第 2 章讨论的 BPE 分词器支持
  • "context_length" 表示模型的最大输入标记数,这是由第 2 章讨论的位置嵌入所支持的
  • "emb_dim" 是令牌输入的嵌入大小,将每个输入令牌转换为一个 768 维的向量
  • "n_heads" 是多头注意力机制中的注意力头数量,参见第 3 章的实现
  • "n_layers" 是模型中 transformer 块的数量,我们将在后续章节中实现
  • "drop_rate" 是 dropout 机制的强度,参见第 3 章;0.1 意味着在训练过程中丢弃 10% 的隐藏单元,以缓解过拟合
  • "qkv_bias" 决定多头注意力机制中的 Linear 层在计算查询(Q)、键(K)和值(V)张量时,是否包含偏置向量;我们将禁用此选项,这是现代 LLM 的标准做法;不过,在第 5 章加载 OpenAI 预训练 GPT-2 权重到我们的重实现时,我们会再次回顾这一点
import torch
import torch.nn as nnclass DummyGPTModel(nn.Module):def __init__(self, cfg):super().__init__()self.tok_emb = nn.Embedding(cfg["vocab_size"], cfg["emb_dim"])self.pos_emb = nn.Embedding(cfg["context_length"], cfg["emb_dim"])self.drop_emb = nn.Dropout(cfg["drop_rate"])# Use a placeholder for TransformerBlockself.trf_blocks = nn.Sequential(*[DummyTransformerBlock(cfg) for _ in range(cfg["n_layers"])])# Use a placeholder for LayerNormself.final_norm = DummyLayerNorm(cfg["emb_dim"])self.out_head = nn.Linear(cfg["emb_dim"], cfg["vocab_size"], bias=False)def forward(self, in_idx):batch_size, seq_len = in_idx.shapetok_embeds = self.tok_emb(in_idx)pos_embeds = self.pos_emb(torch.arange(seq_len, device=in_idx.device))x = tok_embeds + pos_embedsx = self.drop_emb(x)x = self.trf_blocks(x)x = self.final_norm(x)logits = self.out_head(x)return logitsclass DummyTransformerBlock(nn.Module):def __init__(self, cfg):super().__init__()# A simple placeholderdef forward(self, x):# This block does nothing and just returns its input.return xclass DummyLayerNorm(nn.Module):def __init__(self, normalized_shape, eps=1e-5):super().__init__()# The parameters here are just to mimic the LayerNorm interface.def forward(self, x):# This layer does nothing and just returns its input.return x
import tiktokentokenizer = tiktoken.get_encoding("gpt2")batch = []txt1 = "Every effort moves you"
txt2 = "Every day holds a"batch.append(torch.tensor(tokenizer.encode(txt1)))
batch.append(torch.tensor(tokenizer.encode(txt2)))
batch = torch.stack(batch, dim=0)
print(batch)
tensor([[6109, 3626, 6100,  345],[6109, 1110, 6622,  257]])
torch.manual_seed(123)
model = DummyGPTModel(GPT_CONFIG_124M)logits = model(batch)
print("Output shape:", logits.shape)
print(logits)
Output shape: torch.Size([2, 4, 50257])
tensor([[[-1.2034,  0.3201, -0.7130,  ..., -1.5548, -0.2390, -0.4667],[-0.1192,  0.4539, -0.4432,  ...,  0.2392,  1.3469,  1.2430],[ 0.5307,  1.6720, -0.4695,  ...,  1.1966,  0.0111,  0.5835],[ 0.0139,  1.6754, -0.3388,  ...,  1.1586, -0.0435, -1.0400]],[[-1.0908,  0.1798, -0.9484,  ..., -1.6047,  0.2439, -0.4530],[-0.7860,  0.5581, -0.0610,  ...,  0.4835, -0.0077,  1.6621],[ 0.3567,  1.2698, -0.6398,  ..., -0.0162, -0.1296,  0.3717],[-0.2407, -0.7349, -0.5102,  ...,  2.0057, -0.3694,  0.1814]]],grad_fn=<UnsafeViewBackward0>)

Note

  • If you are running this code on Windows or Linux, the resulting values above may look like as follows:
Output shape: torch.Size([2, 4, 50257])
tensor([[[-0.9289,  0.2748, -0.7557,  ..., -1.6070,  0.2702, -0.5888],[-0.4476,  0.1726,  0.5354,  ..., -0.3932,  1.5285,  0.8557],[ 0.5680,  1.6053, -0.2155,  ...,  1.1624,  0.1380,  0.7425],[ 0.0447,  2.4787, -0.8843,  ...,  1.3219, -0.0864, -0.5856]],[[-1.5474, -0.0542, -1.0571,  ..., -1.8061, -0.4494, -0.6747],[-0.8422,  0.8243, -0.1098,  ..., -0.1434,  0.2079,  1.2046],[ 0.1355,  1.1858, -0.1453,  ...,  0.0869, -0.1590,  0.1552],[ 0.1666, -0.8138,  0.2307,  ...,  2.5035, -0.3055, -0.3083]]],grad_fn=<UnsafeViewBackward0>)
  • Since these are just random numbers, this is not a reason for concern, and you can proceed with the remainder of the chapter without issues

4.2 通过层归一化来规范化激活值

(Normalizing activations with layer normalization)

  • 层归一化(也称为 LayerNorm,Ba 等人,2016)会将神经网络层的激活值归一化,使其均值为 0,方差为 1
  • 这能够稳定训练过程,并加速收敛到有效权重
  • 在 Transformer 块中,层归一化会在多头注意力模块的前后进行应用,我们将在后面实现;它还会应用在最终输出层之前
  • 让我们通过一个简单的神经网络层传递一个小的输入样本,来看看层归一化是如何工作的:
torch.manual_seed(123)# create 2 training examples with 5 dimensions (features) each
batch_example 
http://www.lryc.cn/news/607912.html

相关文章:

  • 相对路径 绝对路径
  • UniappDay07
  • sqli-labs:Less-19关卡详细解析
  • Qt 槽函数被执行多次,并且使用Qt::UniqueConnection无效【已解决】
  • 24黑马SpringCloud的Docker本地目录挂载出现相关问题解决
  • Tushare对接OpenBB分析A股与港股市场
  • 解锁智能油脂润滑系统:加速度与温振传感器选型协同攻略
  • 深度学习核心:卷积神经网络 - 原理、实现及在医学影像领域的应用
  • 【Java】在一个前台界面中动态展示多个数据表的字段及数据
  • 定制开发开源AI智能名片S2B2C商城小程序的特点、应用与发展研究
  • 自进化智能体综述:通往人工超级智能之路
  • SpringBoot IOC
  • C++之vector类的代码及其逻辑详解 (中)
  • 【自动化运维神器Ansible】YAML语法详解:Ansible Playbook的基石
  • vue引入阿里巴巴矢量图库的方式
  • Kotlin协程极简教程:5分钟学完关键知识点
  • docker desktop入门(docker桌面版)(提示wsl版本太低解决办法)
  • 【MySQL】增删改查操作 —— CRUD
  • Elasticsearch 混合检索一句 `retriever.rrf`,把语义召回与关键词召回融合到极致
  • MySqL(加餐)
  • 在 AKS 中运行 Azure DevOps 私有代理-1
  • Cursor 与 VS Code 与 GitHub Copilot 的全面比较
  • 字节Seed发布扩散语言模型,推理速度达2146 tokens/s,比同规模自回归快5.4倍
  • [spring6: 分布式追踪]-实战
  • AI赋能测试:技术变革与应用展望
  • 在ChinaJoy ,Soul发布“莫比乌斯·第三弹”ChinaJoy特别款
  • 深入 Go 底层原理(十二):map 的实现与哈希冲突
  • 高性能实时分析数据库:Apache Druid 查询数据 Query data
  • RK3399 启动流程 --从复位到系统加载
  • 变频器实习DAY20 测试经验总结