NanoGPT 教程及训练推理
这是目前最简单、最快的一个训练/微调中等大小的GPT仓库。
NanoGPT 中文教程
该项目是对minGPT 项目的重构。项目虽然仍处于积极的开发阶段;但是目前其中的train.py
文件在OpenWebText上已经可以复现GPT-2(124M)在8个A100(40GB)上训练四天的效果。此外,代码写的十分简单易读:train.py
是一个300行的训练的模版,而 model.py
是一个300行的GPT模型定义的模版,该模板支持选择加载OpenAI的GPT-2权重。
因为该仓库的代码实在非常简单,因此很容易根据您的需求进行应用、或者从零开始训练新模型以及微调预训练的检查点(例如,目前可用的最大的预训练模型是OpenAI开源的GPT-2 1.3B模型)。
安装条件
1 |
|
依赖的库:
- pytorch <3
- numpy <3
transformers
for huggingface transformers <3 (用于加载 GPT-2 模型的检查点)datasets
for huggingface datasets <3 (如果您想下载并且处理OpenWebText数据集)tiktoken
for OpenAI’s 最快的BEP编码算法 <3wandb
for optional logging <3tqdm
for 加载进度条 <3
简易上手
如果您不是专业从事于深度学习行业的人士,只是想感受GPT的魅力以及自己训练GPT的快感,那么最快的入门方法就是训练一个可以创造莎士比亚作品的GPT。首先,我们先下载一个1MB大小的文件,并将其从原始文本转换为一个大的整数流(将原始数据转化为一个embedding之后的整数流数据):
1 |
|
这会在数据目录中创建train.bin
and val.bin
文件,现在就是时候来训练你的GPT了。而你训练GPT的规模在很大程度上取决于你能提供的算力情况(是否有显卡以及显存的大小是多少):
如果您的设备配置了显卡,那么很棒,我们可以使用在config/train_shakespeare_char.py config file提供的设置很快地训练一个小型GPT
1 |
|
如果您恰好有兴趣观看了代码的细节部分,您将会发现我们正在训练一个上下文大小高达256个字符、384个特征通道,的一个6层的且每层的heads数量有6个的Transformer。在一个A100型号的显卡中,此训练运行大约需要3分钟,最佳验证损失可以减小到1.4697。根据代码中的设置,模型检查点被写入--out_dir
目录out-shakespeare-char
中。因此在训练完成后,我们可以通过将验证脚本sample.py
在最佳的模型进行文本的效果生成。
1 |
|
这会产生一些新的样例,例如:
1 |
|
哇,¯\_(ツ)_/¯
. 对于一个只在GPU上训练了三分钟的用于角色扮演的GPT来说还真不错。 而如果是在此数据集上微调预训练好的GPT-2模型,有很大的可能会获得更好的结果的(详情见后面的微调部分)
如果**您只有一台MacBook或者其他更为便宜的电脑(没有显卡)**怎么办?不用慌 ,我们仍然可以训练一个GPT,只是我们要让事情低调一点,在这里我推荐使用最新版的每晚更新的pytorch,因为这有可能让您的代码变得更加高效。当没有显卡的时候,可以使用下面这个简单的训练脚本。
1 |
|
此时,由于我们是在CPU而非GPU上运行,我们必须设置--device=cpu
并且使用--compile=False
关闭掉PyTorch 2.0版本的compile功能。 然后,当我们在测试时候时,得到的估计结果可以更不精确但是更快(eval_iters=20
,将迭代的次数从200下降到20),此时我们使用的上下文大小范围只有64个字符,而不是256个字符,每次迭代的batchsize只有12个样本,而不是64个样本。我们还将使用一个更小的Transformer结构(4layer,4个head,128个嵌入大小),并将迭代次数响应地减少到2000(相应地,通常使用--lr_decay_iters
将学习率衰减到max_iters左右)。
1 |
|
这样会生成下面这样的样本:
1 |
|
因为是只在cpu上训练了3分钟,因此能输出这样符合语法,和要求格式的样子算很不错了。如果您乐意等待更长的时间,请尽情去调整超参数,并且去增加网络的大小,使用--block_size
去调整上下文的长度
最终,如果是在苹果的M系列处理器上进行实验(最新的pytorch版本),请务必将添加--device=mps
的设置,PyTorch会使用在芯片上的图形处理单元(GPU)来显著加快训练速度(2-3倍),并且允许您使用更大的网络规模。您可以在 Issue 28找到更多相关的内容
复现GPT-2
一些更专业的深度学习从业者也许会更关注如何去复现GPT-2的效果。因此,让我们开始,我们首先将数据集进行tokenize,以OpenWebText数据集(OpenAI的WebText的开放版本)为例:
1 |
|
这会下载并将 OpenWebText 数据集进行分词化.这将会创造一个保存了train.bin
和val.bin
1 |
|
如果您有集群环境可以使用,并且您拥有多个GPU节点,您可以使GPU在2个节点上进行,例如:
1 |
|
在您的计算机系统中对内部连接(例如使用iperf3工具)进行性能测试是一个很好的主意。如果您没有安装Infiniband技术,那么在上述启动命令前还应该添加NCCL_IB_DISABLE=1
。这样您的多节点训练可以正常进行,但很可能速度会非常慢。默认情况下,检查点会定期写入到--out_dir
指定的目录中。我们可以通过简单地执行python sample.py
命令从模型中进行抽样。
最终,如果想在单个GPU上进行训练,您只需要简单的运行python train.py
脚本即可。看看args中的这些参数,着脚本是如此的易读,易用以及是可迁移的。您可以根据您的需要在这些变量中进行随意地调整。
基线
OpenAI GPT-2的提供的模型保存点允许我们为openwebtext数据集建立一些基准测试。我们可以按照以下方式获得这些数值:
1 |
|
并且可以观察到在训练集和测试集上的损失:
model | params | train loss | val loss |
---|---|---|---|
gpt2 | 124M | 3.11 | 3.12 |
gpt2-medium | 350M | 2.85 | 2.84 |
gpt2-large | 774M | 2.66 | 2.67 |
gpt2-xl | 1558M | 2.56 | 2.54 |
然而,我们必须要注意到一点,GPT-2实际上是在未开源的,甚至是从未发行过的WebText数据集上进行训练的,而OpenWebText只是对这个数据集的最大努力地复制。这意味着数据集之间的差异是显著存在的。事实上,我们使用GPT-2 (124M) 的检查点,利用OpenWebText数据集进行微调,不一会就能观察到损失会降低到2.85左右,对与复现来说,这是实际上是更为合适的基线。
模型微调
微调和训练的差别并不大,我们只需要保证要从一个预训练的模型进行初始化并且用一个更小的学习率进行训练即可。如果想了解如何在新的数据集上微调GPT模型,您可以参考shakespeare的例子:转到data/shakespeare
目录并运行prepare.py
,以下载tiny shakespeare数据集并使用GPT-2的OpenAI BPE分词器,将其处理成train.bin
和val.bin
文件。不像使用OpenWebText数据集从零开始训练,这会在几秒钟内完成。微调可能需要很少的时间,甚至是在单个GPU上仅需几分钟。我们可以像这样运行一个微调的例子:
1 |
|
这将加载写在config/finetune_shakespeare.py
中的配置参数(虽然我没有太多调整它们)。基本上,我们使用init_from
从一个GPT2的模型保存点初始化,并像通常一样进行训练,只是训练时间更短,学习率更小。如果您在训练过程中发现显存溢出的情况,您可以尝试减小模型大小(可选的有'gpt2'
, 'gpt2-medium'
, 'gpt2-large'
, 'gpt2-xl'
),或者可能减小block_size
(上下文长度)。最佳的模型保存点(验证损失最低)会在out_dir
目录中,根据配置文件例如默认情况下会保存在out-shakespeare
中。然后,你可以运行在sample.py --out_dir=out-shakespeare
中的代码:
1 |
|
Emmm,此时GPT似乎产生了一些不能解释(黑洞)的东西。我并没有真正对配置中的超参数进行太多调整,请随时尝试!
采样推理
使用sample.py
脚本可以从OpenAI发布的预训练GPT-2模型或者从您自己训练好的模型中进行内容生成。例如这里您可以通过这样的方式从目前最大的gpt2-xl
模型中进行推理:
1 |
|
If you’d like to sample from a model you trained, use the --out_dir
to point the code appropriately. You can also prompt the model with some text from a file, e.g. python sample.py --start=FILE:prompt.txt
.
提高效率
对于简单的模型基准测试和性能分析,bench.py
可能会很有用。它与train.py
中训练循环的核心部分所发生的事情相同,但省略了许多其他一些复杂的东西。
请注意,默认情况下代码使用的是PyTorch 2.0。在撰写本文时(2022年12月29日),这使得torch.compile()
在每日更新版本中可用。torch.compile()
所带来的提升是显著的,例如,将迭代时间从约250毫秒/次迭代减少到135毫秒/次迭代。PyTorch团队牛逼!
可以做的事情
- 进行调研并使用FSDP代替DDP
- 在标准评估上评估了零样本的困惑度(例如LAMBADA? HELM? 等)
- 可以微调 finetuning script,我认为超参数设置得不太好
- 在训练过程中安排线性增加批量大小
- 合并其他嵌入(如旋转嵌入,alibi嵌入)
- 我认为应该在检查点中将优化缓冲区与模型参数分开
训练实践
训练西游记
照搬上面教程:
prepare.py
1 |
|
train_west_journey.py
1 |
|
1 |
|
训练凡人修仙传
1000次,12层,效果如下:
Overriding: out_dir = out-human/
number of parameters: 22.81M
Loading meta from data/human/meta.pkl…
“元磁神光!”
韩立只听了一声,就脸色一变的失声出口,同时心中法决一催。
顿时金色电光只是一闪,又一根金色电丝从指尖处激射而出,一闪即逝下,就没入韩立 身躯之中,不见了踪影。
下一刻,韩立面色一白之下,一声低喝,单手虚空一抓,一座尺许高的黑色山峰,从其 身躯中一飞而出,并一个闪动的在手中一迎而出。
黑色山峰毫不客气的往下一模糊的一扎。
一声接一声闷响!
黑色山峰、紫色符文手臂一模糊下,竟在狠狠一投而出,并立刻在金光闪过处,化为了 一座黑色山峰,狠狠的往高处一砸而去。
一声闷响!
黑色山峰一下寸寸的爆裂而开,并瞬间的爆裂而开。
一团乌光从乌光中激射而出,一下化为一个直径数十丈的黑色山峰,散发着惊人黑芒的 将整座山峰全都笼罩在了其中。
第十一卷 真仙降世 第两千一百一十七章 金光界
“你真想伤我,想不到可以直接打开此山?”女子也在此威能之下,发出了一声惊怒的尖 叫,仿佛下一刻,一下活过的样子。
而那只金色拳头一个闪动下,就一下一下到了女子手中,并狠狠一拳击在了黑色山峰上 。
虽然韩立的修为不说,但除了这只魔兽外,其他人和十几名弟子,清秀的看到一个宽广 的圆形空间。在其中一处,则有一个男子站在那里,正有六七名修士,正在陪着一名面色冰 冷的姓中年修士,也一副神态恭敬的盯着他们。
“大哥,这是……”这名老者一到白家弟子面前,忽然一个淡淡的声音传出,似乎带有一丝 微弱之意,仿佛进入到了什么地方。
“不错。你们两个修士,正在闭关之中呢。”
“哼!这话是什么意思?看来我们二人都已经动了手脚了,竟然还等候大哥的样子。”白 芸馨面无表情的回了一句。
两名老者听到白家弟子这般一说,也不禁露出一丝苦笑,几步走了过去。
“两个弟子,我要你们两个,是不是将这些弟子全都灭杀,等大家不到千万为密,我们过去看看还不是什么遗憾之事。好了,我给两人带路!”白芸馨毫不犹豫的回道。
“这位是哪位前辈到此的,不过是听说这些弟子的消息,那位前辈是来自圣界的两名弟子了。”另外两名老者也一口同意了下来,急忙的赔罪道,同时脸上满是狡黠之色。
“那我等还是先离开这里,再说一下吧。”白芸馨点点头,并未再接口什么。
于是三人再商量了几句后,当即就
此女一见韩立带队离去,口中一声轻咦,目光神通一下变得小心异常起来。
“哼,找死。我要不是你另有矛盾,我一人就可以偷袭了。”女子冷哼一声,脸上现出一 丝狡诈之色,随即一只玉手一抬,反手蓦然多出一只碧绿色的储物袋。
袋口一阵扭曲,顿时一股黑气从中一喷而出,并一个翻滚下,一只只紫色大手浮现而出 。
此手掌看似普通之极,但是一抓下,竟然平静异常,并被一摄而起的一把捞进了手中。
这时,韩立却仔细打量了手中的黑色山峰两眼。
这黑气翻滚不定,仿佛什么东西的凝聚而成,竟然正是成熟体的。
韩立面上露出了沉吟之色,但是手中长袖却一抖,一团银色火焰从中一飞而出,一凝之 后,竟化为一只银色火鸟。正是噬灵火鸟!
在此鸟上空,韩立先将此鸟一把抓到了手中,然后用一只大手轻轻一拍。
银色火鸟从其身上一涌而出,一个盘旋后就化为了丈许般巨大,然后一个盘旋,化为一 只银色火鸟,双翅一展的直奔韩立激射而来。
此火鸟大惊之下,双翅一展,一下扎进了韩立身体中。
韩立顿时只觉身形一震,身躯就一下被吸入了其中,身形一沉,接着在一股奇香中,同 样直接倒地不动
韩立面无表情的不再理会艳丽女子,反而轻笑一声后,身上五色光霞一涨之下,竟向女 子徐徐飘去,丝毫不给男修发现一丝喘息之机。
这时,韩立已经在原地等候着,目光闪动不已,凝望着对面女子的遁去。
若是没有人去接近此女,自然只能看到美女将自己幻化收取走的那一刻,才诡异的停在 原地不动了。
不过看她的举动,显然是被戏耍了。
一旁的白瑶怡听得清楚,明明那蓝色光头大汉一言不发,但是目光略一扫下,却落在了 韩立身后数丈远处。
此女双眸苍白异常,头发如花,眸中闪过一丝怪异。
“怎么,你认得我!”韩立眼中蓝芒一闪,盯着此女面孔不禁一下轻咦了一声。
“怎么,这位是……”一看清楚此人面容后,白瑶怡一下失声起来,声音顿时从白光中清楚 楚动人的传来。
“嘿嘿,你不是在感应之下,还是我本体亲自出来吧。”韩立轻笑一声,竟一口将自己受 到扎根打算的事情说出口来。
“前辈莫非忘了晚辈姓名,还是晚辈的确……”白瑶怡轻描淡写的回道,显得颇为的难以置 信,明显不肯答应韩立的真正修为。
“现在起来吧。”韩立嘴角一翘,随即镇定的说道。
“我是因为她身
只见在那边另有一名中年人,正将手中的一口银色断剑,一口咬住了马车上的绿衫女子 ,而那圆钵则仍然被一切而开,似乎被人轻易的毁坏了一个大伤。
“启禀前辈爷爷,那里是……”黄衫女子一见银月,双目蓝芒一闪的问道。
“银月,你……”黄衫女子毫不迟疑的答应一声,一扬手,一团银光激射而出。
银月闻言,毫不犹豫的化为一道银虹,没入了身下的雾海之中。
“多谢前辈出手相助。”黄衫女子心中有些欣喜,低首恭敬的说道。
“银月,你这是什么意思?”韩立眉头一皱的问道。
“前辈不用过虑。我已经打算回黄枫谷,只在附近寻找一些东西,并不太精神。但是现在嘛,我是不是太吃亏了。”黄衫女子思量了一下,急忙回道。
韩立愣了一下,但并未追问什么。而是招呼圭灵一声,应对了过去。
倒是黄衫女子一见韩立,目光一瞥之下,重新打量了韩立两眼,才面露为难的表情,但 马上想起了什么,神色一下平静了下来。
“不瞒前辈,晚辈是不是说得另一个说不清楚,更不敢打扰前辈的。只是前辈在傀儡兽身上释放了不知名灵石,那晚辈也是第一次听说过此名字的。”韩立摸了摸下巴,若有所思的说道。
就在这时,下方突然一阵低沉的鸣叫声传来,大片血丝一下从下方激射而出,往回一卷 ,竟然正好击在了那名身穿血红战甲的戎族人身上,两只手臂只是一晃,就被一股无形之力 一弹而开,将戎族人身形彻底淹没在了其中。
此异族大惊,但不敢再怠慢,口中一声低喝,十指蓦然一弹。
五色大手闪电般的一下在身前浮现而出,五指一张之下,就要将此异族一下摄离的血傀 儡直接抓到青年本体上。
青年见此情形,脸色微微一变,手中法诀却忽然一催,一团青色光球从中一飞而出,一 个闪动下就到了其身前处。
青甲大汉一声冷哼,身形一动,就一下没入二者身躯中。
一股强烈之极的力量从巨人身上一卷而出,同时一股可怕力量从青甲大汉肉身中一涌而 出,从巨人口中一卷而出,将二者身形一下包裹进了其中。
“我是什么联手之人。竟敢在我面前动手,就此灭杀你了。”青甲大汉听到这话,目中凶 光一闪,厉声的喝道。
“虚天鼎!”青年脸色变得苍白无血了,当即冷哼一声的单手一掐诀,一团青光从其头颅 内一飞而出,一个闪动下就化为了数十丈高的一个青色巨鼎。
青袍青年也不甘示弱的单手一掐诀,一张口,冲青年一喷而出。
“阁下是何人?”韩立心中一凛,但口中自然说出了这样的话来。
“晚辈是圣王长老,原来是和血魂前辈有过一面之缘,原来前辈就是附近数万年来的道友。在下从未听说过,前辈只是当时和晚辈交情一二罢了。”白璧双目一亮,一字字的说道。
这次,韩立已经问过此事了,其他人自然一同告辞了。
“既然前辈没有意见,那晚辈就不再犹豫什么了,前辈若是只是出手,晚辈一定不肯出手的。”韩立心中一松的回道,并随之遁光一闪,化为一道青虹激射而走。
一小会儿工夫后,韩立终于出现在了一片蔚蓝无云的无边湖泊边上,远远看见无边的一 片小湖,一前一后,向湖面望去。
在那里,有一座二十余丈的巨大湖泊,上面隐隐有一个人影,但又有一条条淡青色的怪 异舟队。
在那里,一名白裙女子,端坐在那里,而在一旁,则正和韩立面前两名女子交谈着什么 。
“咦,道友是……”韩立目光一闪,落在了那名貌美如花的女子身上。
“道友原来是冰魄道友!”女子吃惊起来,但还是谨慎的问道。
“放心,道友尽管拿我等几个去处理一下吧。”韩立哑然一笑,并未说什么。
女子见此,也同样露出一丝笑意,也
韩立眉头微微一皱,一只手掌蓦然冲远处一招。
顿时一股黑气从指间滚滚而出,一个闪动下,就化为一只亩许大的黑色山峰,并排一排 。
这些黑气一个个模糊不清,并往中心处滚滚的一聚,竟凝成一只体积数亩大小的漆黑魔 兽。
这些魔兽通体乌黑,但通体遍布灰白魔纹,并散发出一种诡异的怪异气息,竟有好几分 酷似的妖异模样。
“这为何疯狂。不过这种损伤恐怖的魔兽不是普通魔兽可以轻易侵入的,否则当初只不过是一时的事情。”韩立又在洞府中一一的说道。
“恐怕有些麻烦了!韩兄,你没事吧。这些魔兽又是如何出现在此地的。它们不过是一些普通魔兽,又怎能不知道密密麻麻的。”银月忍不住的想问一句。
“哼,如此说来,我倒也看看能否找出那些魔族有关其他魔兽的踪迹,再寻到这些魔兽了。”韩立嘴角抽搐一下后,不客气的说道。
“这倒不是。我虽然已经和银月月许久的。但是紫言鼎的本命之火,可和其对此只是同一只魔兽,威能之大可想而知了。”
“你若没有猜错的话,那些魔兽若是有圣祖级别的魔兽存在,自然是无用的。这些魔兽虽然有一定的神通,但一旦被我等发现,又有谁能奈何了我等,立刻逃之
“嘿嘿!你们的天狐之体,竟然是自由之身!”男子冷笑一声,不客气的反讥道。
“什么,难道你们天狐族还真是是族中的第一人。”
“我是那个是在外边修炼的第三道……”
竟然是宋姓女子“咯咯”一阵轻笑,似乎有些不太相信自己的预感,黛眉一皱。
“我是从不开口说话的。至于第三层,我若没有什么后手,却有自信和道友说起来。这一次的试炼,所有人都可以参加此次天狐之王,但是若是身处此地,我们也不会对族内什么人 之争。你们虽然成为合体修士,但可能都是一对双修之手的。”银衫女子竟有些恍然了。
“倒是黛儿姐姐不妨再多禀一声道友,先前的神通不一定非同小可的。”白瑶怡一笑起来 。
“就算在下同样的不敢出手,那人也感应到远处天狐云笼的一缕神念之力,我等还是能做到的。”女子双目一眯的说道。
“哼,以你这般境界,想来又不是不能接下我们的进入。”银衫女子却轻哼一声的说道。
“如此说来,倒的确有些麻烦的。不过,这个人不是天狐之身,我等也不想就这般死撑到此地的。若是此人真要了,等他们回去将他们毁去再说。回去后,她们再找另一个人联手, 再寻那人身上的。”银衫女子阴沉
“这倒是。”
而玉佩中的一脸的踌躇之色,显然还不知道韩立如何发现的。
就在这时,突然从雾海中飞射出来两道人影,一个盘旋的到了韩立身前处,两手一挥下 ,两口绿色飞剑一下暂时没入了雾海之中,随即“噗”的一声,化为一口尺许长的碧绿竹尺, 冲韩立狠狠一斩而去。
绿尺方一接触,就一下化为尺许长的飞剑,并在一声轰鸣声中自行爆裂开来,化为一道 绿色光柱从空中激射而出,一闪即逝的没入了雾海中。
韩立见此情形,并不迟疑,身形一晃,就到了雾海边缘处。
只是略一用法力就蓦然从雾海中射出,只是几个闪动,就到了韩立身前处,光芒闪动, 一下没入下方雾海中不见了踪影。
一声闷响后,雾海一分,雾海再次现出了原形,并不太轻,大半雾海都被卷入雾海之中 ,并随着雾海扩散消失,这个雾海竟然变得如同小山的样子。
等他一口气钻进了那片雾海中,才发现里面竟有数座尺许大小的巨型迷你小山,但滴溜 溜一转后,就一下自行的腾空飞来,直奔下方的雾海激射而去。在雾海边缘处,一个遍布大 半雾海的半空中,出现了一座无边无际的漆黑山峰。
此山峰除了留下一颗黑乎乎的不知名山石外,韩立竟无法看出
训练唐诗
下载诗词数据集,数据清洗,生成tang_poet.txt。
format_data.py
1 |
|
prepare.py
1 |
|
资料补充
中文预训练数据集
这里会搜集一些小型的,适合于nanoGPT进行训练的中文数据集的仓库 其大多是常用的NLP训练语料,但我给出整理数据以适应nanoGPT的要求
目前已有:
对话能力实现
主要参考VatsaDev/nanoChatGPT: nanogpt turned into a chat model
目前已有的nanoGPT资料收集
视频资料
- (30) Let’s build GPT: from scratch, in code, spelled out. - YouTube
- 从零开始手搓一个LLM(一)把参数缩减到足够单卡训练的NanoGPT_哔哩哔哩_bilibili
- 【自制中英字幕】【Andrej Karpathy】让我们从头开始,在代码中构建GPT_哔哩哔哩_bilibili
博客资料
- NanoGPT Tutorial - WHY42 (riguz.com)
- Andrej Karpathy 的 nanoGPT lecture demo 详解
- 迷你版ChatGPT开源,教你怎么用nanoGPT训练一个写小说的AI机器人!
- NanoGPT的Pytorch2.0版本实现及分析
开源仓库
- karpathy/nanoGPT: The simplest, fastest repository for training/finetuning medium-sized GPTs.
- HuZixia/nanoGPT-lecture: This nanoGPT-lecture code git, including Andrej Karpathy’s nanoGPT, ng-vedio-lecture, gpt_dev.ipynb and my learning notes. Welcome to like and follow
- VatsaDev/nanoChatGPT: nanogpt turned into a chat model
- Andrei-Aksionov/nanoGPTplus
- https://github.com/sanjeevanahilan/nanoChatGPT
- nanoGPT训练一个写唐诗的GPT