GitHub狂揽2k 大神Kapathy一键三连 从零复现Llama3代码库爆火
让大神Andrej Karpathy一键三连❤️(点赞+转发+评论),一个教你 从头开局成功Llama3 的代码库爆火。
X上转赞收藏量超6.8k,GitHub揽星2k+。
火就火在,它教你从头用Meta开源的权重启动推理, 详细解释和倒退了留意力机制中多个头的矩阵乘法、位置编码以及一切两边层 。
换句话说,他解释了每行代码都在干啥。
Karpathy看后直呼打造者 Nishant Aklecha (后文暂称“纳哥”)是个有品的人:
网友们对其也是赞不绝口,纷繁致敬:
话不多说,一同来看纳哥是如何手把手教的。
(量子位在不扭转原意的基础上,启动了编译整顿)
从头成功llama3
在运转纳哥提供的文件前,大伙儿须要预先下载Meta官网提供的Llama3模型权重。
纳哥示意自己没搞分词器,介绍用Karpathy的现成繁复版BPE代码。
“字节级(byte-level)”BPE算法,在UTF-8编码的字符串上运转,宽泛运行于大模型分词。Karpathy提供的这个代码库蕴含两个分词器,都能在给定文本上训练分词器的词汇表和兼并规定、将文本编码为token、将token解码为文本。
读取模型文件的模式理论取决于model classes的编写模式以及class中变量的命名。但由于纳哥是从头开局成功Llama3,所以将一一张量地读取文件内容。
经过此性能可以推断出模型的结构和参数消息,例如模型蕴含的Transformer层数、多头留意力块中的头数,以及词汇表的大小等细节。
将文本转换为token时,纳哥经常使用tiktoken作为分词器。
接上去,纳哥展现了在代码中将token转换为高维的嵌入示意。这是代码库中惟一经常使用内置神经网络模块的局部。
[17x1]的token矩阵变成了[17x4096]的嵌入矩阵。也就是说,每个token被转换为一个长度为4096的嵌入向量,总共有17个这样的嵌入向量。
而后,纳哥对嵌入启动RMS归一化。经过这一步后,嵌入的状态不会扭转,只要数值被归一化了。纳哥强调须要一个norm_eps,防止异常将RMS值设为0造成除以0的失误。
以下是公式:
构建Transformer的第一层,启动归一化解决,从模型字典中访问layer.0(即第一层)。归一化之后,张量的状态依然是[17x4096],与嵌入时相反,但数值已被归一化。
跟着纳哥从头成功留意力机制,加载Transformer第一层的留意力头。
从模型中加载query、key、value和output向量时,它们的状态区分是 [4096x4096]、[1024x4096]、[1024x4096] 和 [4096x4096]。
纳哥示意乍一看有点奇异,由于现实状况是每个留意力头的q、k、v和o向量是独立的。而代码作者将它们捆绑在一同,是为了繁难并行计算留意力头的矩阵乘法。
把一切这些向量解包开来:
下一步,纳哥将从多个留意力头中解包query,解包后的状态是[32x128x4096],32是Llama3中的留意力头数量,128是query向量的大小,4096是token嵌入的大小。
在这里,纳哥访问了第一层第一个留意力头的query权重矩阵,query权重矩阵的大小是[128x4096]。
将query权重矩阵与token嵌入相乘,取得每个token的query向量。结果的状态为[17x128],有17个token,每个token对应一个长度为128的query向量。
接上去须要位置编码。
如今曾经为prompt中的每个token生成了query向量,但每个独自的query向量并不知道它在prompt中的详细位置。
例如,query:“the answer to the ultimate question of life, the universe, and everything is ”(生命、宇宙和一切的终极疑问的答案是)。
在这个prompt中,经常使用了三次”the”,须要依据它们在prompt中的位置,使这三个”the”token的query向量有所不同(每个向量的大小为[1x128])。
经过经常使用RoPE(旋转位置嵌入)来启动这些旋转操作。
上一步中,纳哥将query向量分红对,并对每一对运行一个旋转角度偏移。
由此,失掉的向量大小为 [17x64x2],这是将长度为128的query向量对每个prompt中的token分红64对。这64对中的每一对都会依据m*(theta) 启动旋转,其中m是要旋转query的token的位置。
经常使用双数的点积来旋转一个向量:
如今每个token的query元素都有一个双数(角度变动向量),可以将query向量(之前分红的对)转换为双数,而后经过点积依据位置旋转query向量。
取得旋转后的向量后,可以经过将双数从新视为实数来失掉成对的query向量。
旋转后的对如今曾经兼并,有一个新的query向量(旋转后的query向量),其状态为[17x128],其中17是token的数量,128是query向量的维度。
key与query简直相反。
纳哥示意自己不会详细解说key的数学原理,只要要记住以下几点:
key生成的key向量维度也是128;key的权重只要query的四分之一,这是由于key的权重在同一期间内被4个头共享,来缩小计算量;key也会旋转加上天位消息,要素与query相反。
此时,纳哥曾经为每个token取得了旋转后的query和key。每个query和key如今的状态都是[17x128]。
下一步,纳哥将对query矩阵和key矩阵启动相乘操作。这样做会生成一个评分矩阵,将每个token关联起来。这些评分形容了每个token的query与每个token的key之间的相关性,这就是自留意力机制。
留意力评分矩阵(qk_per_token)的状态为[17x17],其中17是prompt中的token数量。
接上去须要对query key评分启动掩码解决。在Llama3的训练环节中,未来token的qk评分是被掩码的,只经过过去的token来预测token。
因此,在推理时,要将未来的token评分设置为0。
接上去是value,凑近留意力机制的最后一步。
这些评分(0-1)用于确定每个token经常使用多少value矩阵。
和key一样,value的权重也在每4个留意力头之间共享,所以上方value权重矩阵的状态是[8x128x4096]。
第一层,第一个留意力头的value权重矩阵如下所示:
而后是value向量。
经常使用value权重来失掉每个token的留意力值,矩阵的大小是[17x128],其中17是prompt中的token数量,128是每个token的value向量的维度。
留意力:与每个token的value相乘后失掉的留意力向量的状态为[17x128]。
如今有了第一层第一个头的留意力value。而后纳哥运转一个循环,对第一层的每个头口头与上方的计算齐全相反的数学运算。
而后失掉了第一层一切32个头的qkv_attention矩阵,接上去将一切留意力得分兼并成一个大小为[17x4096]的大矩阵。
关于第0层留意力机制的最后步骤,其一是将留意力得分矩阵与权重矩阵相乘。
这是一个繁难的线性层,所以只要启动矩阵乘法。
如今失掉了留意力机制后的嵌入value变动,应该被参与到原始的token嵌入中。
对嵌入增量启动归一化解决,而后经过嵌入增量运转一个前馈神经网络。
在Llama3中,加载前馈权重并成功前馈网络。经常使用了一种名为SwiGLU的前馈网络,这种网络结构在模型须要的时刻,能够有效地参与非线性。
如今成功了第一层之后每个token的新嵌入。如今只剩下31层了,只要经过一个循环来成功。
纳哥示意可以将这个编辑后的嵌入构想成蕴含了第一层中一切查问消息的嵌入。随着层数的参与,每一层都会对输入的消息启动越来越复杂的解决,直到最终失掉一个能够片面了解下一个须要预测的token的嵌入。
之前做的一切事件,对每一层都重复一次性。
而后失掉了最终的嵌入,这是模型对下一个token的最优预测。这个嵌入的状态与惯例的token嵌入相反,为[17x4096],其中17是token的数量,4096是嵌入的维度。
最后,将嵌入解码成token值。
经常使用输入解码器将最终的嵌入转换成一个token。
接上去看纳哥经常使用最后一个token的嵌入来预测下一个value,宿愿预测的结果是42。
由于依据《河汉系遨游指南》一书中的说法,42是“生命、宇宙及一切的终极疑问的答案”。大少数LLM在这里都会回答42,这将验证整个代码的正确性。
模型预测下一个token的编号为2983。这个编号对应数字42吗?
OK,完结。
“让钻研变得愈加触手可及”
繁难引见一下Nishant Aklecha。
Nishant Aklecha是构建和改良定制言语模型平台Glaive AI的钻研员,曾任职于摩根士丹利,担任训练和微调大言语模型。
此外,他还和好友一同创立了一个钻研试验室,名为A10(AAAAAAAAAA)。
他们的指标可以总结成一句话:让钻研变得愈加触手可及。
除了放出这个代码库,Nishant Aklecha堪称恶人做究竟。
网友想更好地理解这个代码库的内容,Nishant间接一个YouTube视频甩了上来:
之前Nishant Aklecha还曾写过一篇Blog,详解了潜在分歧性模型(LCM),雷同收获了不少好评。
啥也不说了,感兴味的家人们连忙码住吧。
GitHub链接:
原文链接: