从头搭建GPT(Andrej Karpathy) 笔记

AI摘要

本文通过Andrej Karpathy的教程,详细介绍了如何从头构建一个简单的GPT模型,即nanoGPT。讲解了数据处理、tokenize、计算loss、self-attention的直觉和实现,以及在训练过程中如何逐步改进模型,实现transformer的基本结构。nanoGPT仅涉及预训练步骤,使用莎士比亚的文章作为toy dataset,最终模型的loss有所降低,但生成的句子质量仍有待提升。

本文来自openAI联合创始人,曾担任特斯拉视觉部门总监的Andrej的视频Let’s build GPT。

当然这里的GPT并不是原版GPT,只是一个nanoGPT, 不过大体结构差不多,旨在帮助大家理解GPT的原理。
(nanoGPTgithub地址)
另外,这里只有pre-train步骤,并不涉及fine-tune.

简单介绍

chatGPT的核心是transformer。
它是一个supervised learning, 会根据语言序列预测下一个会出现的文字,不停地重复,就预测出了语句。
预测的是token level, 而不是word level.

这里会用transformer搭建一个类似gpt的模型,
gpt的训练数据来自网络,而且有pre-training, fine-tuning stage, 很复杂。
这里不整那么复杂,就用一个toy dataset训练,
toy dataset是一个包含莎士比亚文章的txt文件。

数据处理部分

下载toy数据

import requests
data_url = 'https://raw.githubusercontent.com/karpathy/char-rnn/master/data/tinyshakespeare/input.txt'
with open('./input.txt', 'w', encoding='utf-8') as f:
    f.write(requests.get(data_url).text)

下完之后要把这个txt里面的string给tokenize.

什么是tokenize

什么是tokenize? 就是把string用a list of integer表示,
举个简单的例子,你可以按顺序unique地列出string中所有出现的字母。
那么每个字母就对应一个index, 你可以用index表示这个string, 如下:
一共65个unique的字母和符号,integer的取值范围在0~65.

在这里插入图片描述

当然上面只是一个简单的例子,实际tokenize的时候可以用google的sentense piece, openAI的tiktoken等. gpt用的是tiktoken.
这种tokenizer是sub word level, 既不是一个字母一个字母地换成integer, 也不是一整个word.
它用的词汇量非常大,所以和上面的相比,integer的list会短一些,但是数字的范围会更大。

不过这里为了浅显易懂,还是用这个简单的tokenizer。
可以看下前1000个字母tokenize之后的样子。
在这里插入图片描述

接下来是拆分train和test集。这里按90%和10%拆分。

在这里插入图片描述
现在拆分出来的训练集和测试集是很长的integer list. 不会一下子放进transformer(内存和计算expensive),
把它们拆成短句子,比如说长度为8的list.

label就是根据一个序列预测的下一个子母,这里用code来解释。
这里取长度为8+1.是为了在长度正好为8时能预测它的下一个字母(第9个字母)。
在这里插入图片描述

定义batch_size, 把短句子压成batch, 让gpu并行处理。
在这里插入图片描述

这里面x是输入的短句子, y是x中到每个字母为止的这段句子预测的下一个字母。
在这里插入图片描述

计算loss

先把这些放入最简单的网络,称为bigramLanguageModel.
这里是用了nn.Embedding得到了65 * 65的table,
token_embedding_table(idx) 就是从table中取出idx对应的那一行向量作为word embedding.
cross_entropy需要的输入shape是(N, C), channel要在第2个,所以做了reshape.
cross_entropy是如何计算的请参考cross entropy用法

在这里插入图片描述

可以看到算出的cross entropy为4.87,
而现有65个unique的字母,平均猜测的话cross entropy应该是-log(1/65), 约为4.17, 可见初始预测不是特别的平均。

上面已经可以evaluate一个model.
现在开始用model生成。

为了节省时间,就不贴那么详细的图了。

直觉上的self-attention

前面都是只考虑一个字母,根据一个字母推测下一个字母,而没有考虑历史信息,
如果把[: t+1]的embedding求平均或求sum, 就可以考虑到之前所有的信息。

有一个trick, 用下三角的ones矩阵 * 矩阵B, 可以得到矩阵C,C的每行是B对应的前面行求和。

在这里插入图片描述

上面求的是sum, 如果平均,只需要把a的每行除以对应一行的和。

在这里插入图片描述

这种求平均也可以用softmax实现,
把上三角的0位置置为-inf
在这里插入图片描述
然后用softmax就相当于每行的每个元素求平均。

每个weight元素都代表了一个token的weight, 也就是self-attention.

embedding size设为32.
前面的token_embedding_table不直接得到logits, 先得到token_embedding, 再过一个linear layer才是logits.
linear映射32的embedding to vocab_size(65)

position embedding
用nn.Embedding再建一个table作为position embedding
最后把word embedding和position embedding加起来。
这种方案在这个简单的模型里面不起作用,因为它只看一个位置,但是在transformer里面有用。

在这里插入图片描述

矩阵乘法实现self-attention:

每个token会产生2个vector, 一个query, 一个key.
query: 我要找谁?
key: 我有什么?
找两个token的关系就用query 点乘 key.

根据这一思想再写一遍weight, 就会看到每个token的weight不是平均的了。

在这里插入图片描述

前面都是直接用weight * input的x,
现在用x过linear产生value vector,
然后用weight * value.

在这里插入图片描述
和CNN相比:CNN是在空间层面操作的,而self-attention你可以理解为散在四处的一堆向量,这些向量之间的互相交流,
它们并没有space的概念,所以你想让它们有空间概念,就需要人为加进去,也就是position embedding.

各batch是独立的,token只在自己的batch里面交流。

目前为止每个token只和它之前的token交流,这并不是绝对的条件。
有时比如你做sentiment analyze, 就需要全句子中所有的token都有交流。
这种情况下就要用到encoder-decoder,
在encoder中,不限制token之后的token和它交流,在decoder中要限制(因为要预测下一个)。

self-attention和cross-attention有什么区别

self-attention中query, key, value都是来源于同一个源的数据,
而cross-attention有可能query来源于一组数据,而key, value来源于其他数据。

attention中为什么要做scaling

看一下attention is all you need的paper中attention的部分:

在这里插入图片描述
前面已经实现了softmax(QKT)V,
但是这里为什么要除一个 d k \sqrt{d_{k}} dk​ ​呢。

这里举了例子:
如果你的输入是0-1高斯分布。k,q也是0,1高斯,那么weight的方差就会是head_size的倍数。
在这里插入图片描述

如果你把(QKT)除以 d k \sqrt{d_{k}} dk​ ​, weight的方差就会变为1.

在这里插入图片描述

为什么不希望方差太大?
因为如果方差比较大,分布不是那么平均的话,经过softmax之后,数值会类似于one-hot vector, 在初始vector最大的数值处值很大,其他地方值很小。这里也举了个例子。
你可以看到第2个例子经过扩大之后分布不是那么平均,过softmax之后初始最后一个最大值处会变成类似one-hot。

在这里插入图片描述

来个完整版的self-attention.

在这里插入图片描述

不过用了self-attention之后,和不用之前相比loss只提高了0.1, 还需要在其他地方下功夫。

继续增加改进的点, 逐步实现transformer

根据transformer结构加入现在没有的模块,
可以看到模块之间有residual.
用了multihead, head后面有Norm layer, 还有feed forward layer.
左边encoder的输入进入右边decoder, 有cross-attention.

在这里插入图片描述

逐步加上模块验证loss:

加上Multihead之后提高到2.28,
multihead类似于group conv, 先分组再结合。
(仅用了几行就实现了multi-head…)

在这里插入图片描述

又加上feedforward, 提高到2.24, 但是生成出来的句子效果仍然不好。

于是再从paper中找idea, 认为网络太深的话backpropagate容易出问题,
这时需要residual block, 而paper中的结构也用到了residual.

再加上projection.
根据Paper,feedforward的channel应该是 x4的,作修改,然后再映射回原来的channel。
在这里插入图片描述

现在loss降到2.08, 但是生成的句子只有一小部分像英语。

接下来做第2个innovation.
图就不贴了,有兴趣的可以看下视频。或者可以看nanoGPT的model.py。

paper中的结构有 layer norm. 注意不是batch norm. 而是layer norm.
batch norm是对列归一化,把batch norm的代码copy 下来,把对列的归一化改为对行,就实现了layer norm…

这几年transformer的结构有一些进化,paper中是在Head之后做了ADD&Norm,
现在是在进入Head前做layer norm, 叫作pre-norm.

加入layer norm后loss降到了2.06.

在feedforward的后面加了dropout.
dropout可以加在residual connection前面,就在相加运算的前面。
multi-head的softmax后面也可以加上dropout.

顺便讲一下dropout,
它是指在训练时,forward和backward中随机把一些neural置0,
而且每次丢掉的都不一样,
这样就像你在训练时训练的时不同sub-network的集合。
在eval时,所有的神经元都在使用状态,就相当于把这些sub-network组合起来,功能更强大。
不过,目前你只需要知道它是一个regularization的手段。
在这里插入图片描述

修改超参,block size, embedding size加大,因为网络加大的关系,learning rate进一步下调。
head个数增加。
loss降到了1.48.

这个简易gpt只用到了transformer paper中的decoder部分,真实的GPT也是只用了decoder,
为什么没有用paper中的encoder和cross attention呢?

因为paper中是机器翻译,在你预测下一个字母时,还要受到原语言的条件限制,
比如从法语翻译到英语。
encoder部分读入法语,不需要做mask, 也就是不需要一个字母只能受过去时间的字母提示,所有字母都参与weight.
decoder部分需要mask. 只能过去的字母有weight.

encoder输出的部分通过cross attention进入decoder.

而这个简易GPT, 输入就只有shakespear, 并没有其他的条件限制,所以只需要用decoder.

真实的GPT训练步骤

pre-training: decoder only
用网络上大量的文章训练,规模如下。
这时训练的GPT并不能回答问题,只是会输出像网络上那样的文章,新闻之类。
你问它问题,它可能会回你更多的问题,或者忽略你的问题,自己继续输出文章。

在这里插入图片描述

从pre-trained model到GPT还需要如下3步:

在这里插入图片描述

  1. 收集数据,这时的数据就是问答形式的数据,一个问题接一个回答。数据不会像网络数据那样多。
  2. GPT给出的若干个回答,由labeler进行打分,从高到低,根据这个打分再训练一个reward model.
  3. 用PPO强化学习算法优化采样的policy, 根据reward model给出的分数。这样就能从GPT给出的若干答案出采样出最优答案。

nanoGPT只是pre-trained阶段。

如果你想要实现其他任务,也就是说不是一个只能产生文件的模型,那么你就需要进行fine-tuning.
fine-tuning可以是一个简单的监督学习,也可以是GPT那样的fancy work.

别再死记硬背了!用Karpathy的nanoGPT项目,手把手带你跑通LLM的Next Token Prediction 本文通过Karpathy的nanoGPT项目,详细解析了LLM中的Next Token Prediction机制。从数据构造、模型架构到训练和推理实现,手把手教你掌握自回归生成的核心技术,特别介绍了有监督微调(SFT)的关键技巧和常见问题解决方案。 阅读详情

相关推荐

[GPT]Andrej Karpathy微软Build大会GPT演讲(下)--该如何使用GPT助手

Andrej通过将提示工程中的技术和模型学习了什么结合起来,我觉得很好的解释了为什么那些提示工程是有效的。我印象最深刻的就是说模型只是一个标记模拟器,为了让他模拟的结果是我们想要的东西,得需要通过你的前文来限制一些内容使得他如果要完成这个文档补全,就需要按照你的说明来。我觉得这个甚至可以作为提示工程的核心guideline。

摩登都市天空---专栏 1718

[GPT]Andrej Karpathy微软Build大会GPT演讲(上)--GPT如何训练

OpenAI的创始人之一,大神Andrej Karpthy刚在微软Build 2023开发者大会上做了专题演讲:State of GPT(GPT的现状)。他详细介绍了如何从GPT基础模型一直训练出ChatGPT这样的助手模型(assistant model)。作者不曾在其他公开视频里看过类似的内容,这或许是OpenAI官方第一次详细阐述其大模型内部原理和RLHF训练细节。难能可贵的是,Andrej不仅深入了细节, 还高屋建瓴的抽象了大模型实现中的诸多概念,牛人的洞察就是不一样。

摩登都市天空---专栏 1915

Andrej Karpathy《Neural Networks: Zero to Hero》:从反向传播到GPT的实战课程

《Neural Networks: Zero to Hero》是AI专家Andrej Karpathy的经典课程,通过8个视频教程系统讲解深度学习核心原理与工程实现。课程从零开始手写神经网络,涵盖micrograd自动微分引擎、字符级语言模型makemore、MLP与批量归一化、CNN/WaveNet架构,到完整GPT Transformer实现等关键技术模块。配套Jupyter Notebook代码与练习题,帮助开发者深入理解反向传播、注意力机制等底层逻辑,适合希望掌握神经网络本质的学习者。

weixin_44579503的博客 1287

Andrej Karpathy大神:我如何使用大型语言模型

大型语言模型(LLM)生态系统正在以惊人的速度增长和演变。OpenAI的ChatGPT自2022年问世以来,已成为行业内公认的**“原始拓荒者”(Original Gangster incumbent)**和功能最丰富的平台。然而,Google的Gemini、Meta的Meta AI、微软的Copilot、Anthropic的Claude、XAI的Grok,以及来自中国(DeepSeek)和法国(Mistral)的模型,共同构成了如今庞大且多样化的AI对话系统格局。本文将深入解析这些LLM的底层运行机制、

老孙 | Ethan Sun 的博客:AI 智能体与 AI 原生软件的工程实践 1648

从零实现GPT模型:Andrej Karpathy的nanogpt项目实践指南

Transformer架构作为现代自然语言处理的核心技术,通过自注意力机制实现了对序列数据的并行化处理。其核心原理是利用多头注意力层和前馈神经网络层堆叠,通过位置编码保留序列顺序信息。这一设计使得模型能够高效捕捉长距离依赖关系,在机器翻译、文本生成等任务中展现出强大能力。在工程实践中,PyTorch框架为Transformer的实现提供了灵活支持,而反向传播算法则是模型训练的关键。Andrej Karpathy的nanogpt项目以极简代码展示了GPT模型的完整实现,从数据预处理、模型构建到训练推理的全流程

weixin_29056101的博客 362

Andrej Karpathy:计算范式的变革者

《Andrej Karpathy:计算范式的变革者》 概述 本文旨在全面探讨 Andrej Karpathy 在计算范式变革中的角色和贡献。Andrej Karpathy 是一位世界级的人工智能专家,程序员,软件架构师,CTO,同时也是计算机图灵奖获得者,计算机编程和人工智能领

AI天才研究院 1303

ROS2+MoveIt2+Gazebo仿真实战:从零搭建六轴机械臂控制闭环

本文详细介绍了如何从零搭建一个完整的ROS2+MoveIt2+Gazebo六轴机械臂仿真控制闭环。通过手写URDF模型、配置MoveIt2运动规划、集成Gazebo物理仿真与ROS2 Control控制器,最终实现RViz中规划轨迹、Gazebo中同步执行的完整数字孪生验证平台,为机器人算法开发和硬件验证提供低成本、高效的仿真解决方案。

weixin_29093017的博客 483

从SN65HVD230芯片手册出发,手把手教你搞定3.3V CAN收发器电路(附典型应用图)

本文详细解析TI SN65HVD230芯片手册,指导完成3.3V CAN收发器电路设计。从关键参数解读到基础电路搭建,再到高级功能实现与EMC优化,提供完整的接口电路设计方案,并附典型应用图和故障排查指南,助力开发者提升CAN总线通信质量。

weixin_29997523的博客 504

从外包到转正:一个华为OD亲历者的真实工作体验与避坑指南

本文分享了一位华为OD员工从外包到转正的真实经历与实用建议。通过详细解析华为OD的日常工作、转正核心指标、机试备考技巧及职场突围策略,为读者提供了一份全面的避坑指南。特别针对机试E卷的高频考点和刷题方法,给出了具体的数据分析和实战经验。

weixin_33686714的博客 691

PCB板设置20H 原则理解

20H原则是PCB设计中抑制EMI辐射的关键方法,要求电源层比相邻地层内缩20倍介质厚度(20H)。在四层板中实现20H原则需采用S-G-P-S层叠结构,确保GND与PWR紧邻。具体步骤包括:确定GND-PWR间介质厚度H,计算20H值(通常80-120mil),并在设计软件中将电源层四周内缩20H,同时保持地层完整不内缩。注意避免常见误区,如混淆介质厚度、地层内缩等。该原则能有效限制边缘场辐射,降低EMI干扰,是四层板EMC设计的重要规范。

qq_37999850的博客 688

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

【数字IC刷题】华为海思数字IC笔试题(1)详细解析版

MoorePlus的博客 4214

在 FreeStyle SAP UI5 应用里优雅落地 Draft 草稿机制:用 DraftManager 封装 DraftController 的一套实战套路

SAP Fiori应用中,Draft草稿机制是解决业务中断、多人协作和长表单填写等痛点的核心能力。本文提出了一套针对FreeStyle SAP UI5应用的Draft管理方案,通过封装sap.ui.generic.app.transaction.DraftController为DraftManager服务类,将复杂的草稿操作逻辑集中管理。该方案实现了草稿的创建、激活、丢弃等核心功能,使控制器只需调用简单意图式API即可完成操作,同时解决了组件化架构下的上下文切换、统一错误处理等问题。文章还详细介绍了后端Dr

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2750

【OD统一考试(B卷)】比赛的冠亚季军,Python 解答

比赛的规则是 0 号和 1 号比赛,2 号和 3 号比赛,以此类推,每一轮,相邻的运动员进行比赛,获胜的进入下一轮,实力值大的获胜,实力值相等的情况,id 小的情况下获胜,轮空的直接进入下一轮。第一轮比赛,id 为 0 实力值为 2 的运动员和 id 为 1 实力值为 3 的运动员比赛, 1 号胜出进入下一轮争夺冠亚军,id 为 2 的运动员和 id 为 3 的运动员比赛,3 号胜出进入下一轮争夺冠亚军;2 号与 0 号,比赛进行季军的争夺,2 号实力值为 4,0 号实力值 2,故 2 号胜出,得季军。

梦想橡皮擦,专栏100例写作模式先行者,现象级专栏 《Python 爬虫 100 例》作者、《滚雪球学 Python 专栏》原创者 1万+

【OS】AUTOSAR架构下MCAL Modules软件分区问题分析

AUTOSAR架构下MCAL Modules软件分区问题分析

qq_36056498的博客 939

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: 简单的例子说明 F.cross_entropy用法
下一篇: CLIP 图文检索,相似度计算
蓝羽飞鸟
博客等级 码龄8年 1万+粉丝 727原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值