灵哥讲llama3(上)

news/2024/12/29 16:47:15/文章来源:https://www.cnblogs.com/lingerAI/p/18247018

llama3简介

llama3 是meta 2024年4月18日发布的开源的大语言模型, 发布当时是state-of-art(最牛逼)的开源LLM,下图是llama3和其他主流模型评测对比:

llama3官方发布了两个模型的参数:8B和70B(B代表Billion, 10亿),以及发布了用于推理的源代码,官方github地址:https://github.com/meta-llama/llama3
下载代码后,我们主要讲解8B模型, 其中model.py就是模型的核心代码,generation.py是推理代码(我们把模型接收用户输入, 然后吐出输出的计算过程叫做推理:inference)。 接下来上干货, 跟着作者一步一步来拆解这个模型。

llama3主体介绍

llama3主要的技术框架为Transformer, 具体是decode-only transformer, 主体框架和GPT-2差不多.
generation.py的class Llama的build方法来创建model

model = Transformer(model_args)

Transformer是model.py里的Transformer类

model_args是模型参数:

  • max_seq_len: 最大序列长度, 这个长度是推理计算中最长的token长度,后面还会讲到这个长度

  • max_batch_size:最大一批大小,模型一次处理多少次推理(这个可有讲, 以后有机会再讲)

  • vocab_size : token 表大小

模型接受用户输入, 该输入称为prompt(中文为提示,大家知道为什么将大模型使用者叫做提示工程师吗🤣)

tokenizer

首先使用tokenizer, 把输入分割成一个一个token, token并不是和字或者字母一对一对应,有可能是几个单词对应一个token,有可能一个字拆分为几个token,为什么要分割以及根据什么依据来分割, 大家可以问下chatGPT

llama3使用了自己的tokenizer, 每个LLM都会自己的tokenizer.

然后模型根据输入来推理, 然后输出一个token,然后再把输出的token, 拼接到输入后面, 再计算下一个token. 直到遇到代表输出停止的符号(), 整个推理过程完成.

所以LLM又叫做自回归模型(Auto Regression Model). 那你想问为什么用户问LLM问题, LLM能够回答问题.

LLM的训练过程

粗略的来理解一下,LLM在训练的过程中使用了海量文本的数据, 海量的文本数据先切成最大为max_seq_len大小, 切出的分片一般具有完整的语义信息(比如一篇文章的其中一个自然段具有完整的语义信息), 然后以前面的一句或几句话作为输入, 让模型计算下一个token, 模型计算的token 和真实文本的token一般都是不一样的, 这样就产生了误差(loss), 然后再用真实的token添加到输入的后面(是真实的token不是模型产生的token, 该过程在专业术语叫做指导学习), 就这样一个一个token的计算, 直至遇到(token是划分切片的时候人为添加的, 目的是为了让模型学习如何停止). 整个batch结束后, 然后根据累加的loss求出平均loss, 然后反向传播调整模型的参数(反向传播算法是机器学习的灵魂算法).至此模型学会了一种能力,预测下一个token,整个模型可以看作是如下预测下一个token的概率模型

\[P(X_{i+1}|X_{1...i},\Theta) \]

给定输入token \(X_{1...i}\), 与模型的参数\(\Theta\)运算,然后输出下一个token \(X_{i+1}\)的概率

模型输出的大小为vocab_size大小的概率分布, 每个概率值代表着对应的token做为下一个token输出的概率大小, 训练的目标就是使得模型输出下一个真实的(ground truth)token的概率最大化, 如果模型输出下一个token概率分布中真实的token概率为1, 其他的token为0, 那将不会产生loss, loss等于0,不会进行反向传播, 反之输出的真实的token概率不是1, 甚至不是最大的, 那么loss不等于0, loss将会进行反向传播, 逐级传递到每层参数中,然后按照梯度下降的方向调整参数, 使得模型学会输出正确的token。

llama3预测下一个token

llama3还不太一样, 没有完全用最大概率预测下个token

logits = self.model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
if temperature > 0:probs = torch.softmax(logits[:, -1] / temperature, dim=-1)next_token = sample_top_p(probs, top_p)
else:next_token = torch.argmax(logits[:, -1], dim=-1)m=-1)

logits是未归一化(归一化就是使得所有元素之和等于1)的分数, 经过softmax运算后才是概率。temperature就是各种大语言模型里API中的temperature参数,用于控制生成token时的随机性和多样性,通过调整 temperature,可以影响模型生成token的确定性和创造性。sample_top_p是top p算法函数, 原理为输出的token概率按从大到小排序, 选择前m项token,其概率的和刚超过了设定的阈值top_p, 然后再从选择的token中按照其归一化后的概率大小采样(玩过统计概率的都知道采样是什么意思, 通俗的来讲就是抽奖,token概率越大, 被抽中的可能性越高)。

如果temperature为0, 就是简单的取最大概率的token。

生成的token再经过 tokenizer.decode(t) 就可以解码成对应的单词。

llama3结构图

接下来我们讲深入模型内部, 一探究竟。

我们先看下模型的结构图

Nx表示重复N层

⊕ 表示残差连接

太极符号表示旋转位置编码, 每一层的自注意力运算前q和k都加入位置编码信息

中间的自注意力机制使用的是分组查询注意力机制, 并且使用了kv cache缓存

llama3 8B 模型超参数

我们以Meta-Llama-3-8B-Instruct模型为例, 看下模型的超参, 就是params.json

{"dim": 4096,"n_layers": 32,"n_heads": 32,"n_kv_heads": 8,"vocab_size": 128256,"multiple_of": 1024,"ffn_dim_multiplier": 1.3,"norm_eps": 1e-05,"rope_theta": 500000.0
}

dim是token向量的维度

n_layers表示有多少层TransformerBlock

n_heads表示多头注意力机制(Multi-Head Attention)里的头数

n_kv_heads表示分组查询注意力机制(Group Query Attention)里的kv头数

vocab_size表示字典大小

multiple_of表示TransformerBlock中最后的全连接FeadForward中的隐藏层维度hidden_dim的倍数因子(注意哈, 是倍数因子不是倍数, hidden_dim 为 multiple_of 的整数倍)

ffn_dim_multiplier表示上面的hidden_dim放大倍数

norm_eps归一化层用到的很小的数, 以免出现除以0的错误

rope_theta是位置编码用到的参数θ

欲知详情, 请见下回分解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/724579.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang性能优化实践

内存警察 警惕一切隐式内存分配 典型case:函数返回了字符串、切片,警惕一切字符串传进去的输入,函数内部重新分配了一个新的内存返回 对象复用 1.sync.pool 保证有一个ch大小的对象可用 假设有cpu核数那么多并发任务,可以保证gc的时候有保底在2.局部cache sync.pool毕竟加锁…

linux+windows跨端md软件选择(未找到)

目的 windows上使用typora当初是通过破解的方式实现的。现在装双系统时想做做笔记,没有一个管理的软件用起来很不方便。 要求正常编辑,没有难以忍受的问题。 目录管理及大纲(基于标题层级) linux+windows双端,且linux端能够读取。 从粘贴图片能够在相应的img目录下创建图片…

c# 获取年,月,日,时,分,秒,星期几

this.nian.Text = DateTime.Now.Year.ToString(); //获取年 this.yue.Text = DateTime.Now.Month.ToString(); //获取月 this.ri.Text = DateTime.Now.Day.ToString(); //获取日 this.xingqi.Text = DateTime.Now.ToString("dddd"); //获取周几 this.shijian.Text = …

2024-06-13 闲话

2024-06-13 闲话今日最乐

多系统修改默认启动系统,grub

问题 我的电脑装了Windows 和 kUbuntu双系统,但是默认是启动kUbuntu的,作为一个使用了多年windows的普通用户,我更希望默认启动是Windows而不是Linux。因此需要修改顺序。 解决 使用root权限修改/boot/grub/grub.cfg文件。 很多文章里都说windows是4,但是我设置了并没有反应…

php基础语法_面向对象

PHP php代码标记 多种标记来区分php脚本 ASP标记:<% php代码 %> 短标记: 脚本标记: 标准标记(常用): 简写风格: ASP风格:<% php代码 %>注意:简写风格和ASP风格需要在php.ini配置文件中修改以下配置为on,移植性差 short_open_tag = on asp_tags = on<ht…

Linux脚本语言入门.md

0、shell介绍 1)Shell是什么? Shell是一个命令行解释器,它为用户提供一个详Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。 Shell还是一个功能相当强大的编程语言,易编写,易调试,灵活性较强。Shell是解释执行的…

排查Java进程CPU占用高之三板斧

写在前面 线上环境突然出现Java进程CPU占用率持续超过100%的问题,该如何排查并定位呢? 问题一:我们如何知道线上环境的那个服务器(或者哪个Docker容器)出现了CPU持续高的故障了呢? 如果是有比较完善的监控设施,当出现CPU持续高时可以通过发送报警通知的方式告知开发人员…

joker靶场

joker ifconfig看ip先进个rootnmap扫一下,nmap 192.168.1.0/24 扫到了这个开了80端口和8080端口的网段御剑扫一下目录secret.txt/phpinfo.php 可以看到操作系统为Linux的ubuntu,还能看到一些别的配置文件,中间件等信息既然开了8080就去看看啥也没有,看看8080(这里用的文档…

基环树和笛卡尔树

1.基环树 定义:有\(n\)个点和\(n\)条边的图,就是给树连了一条边,此时图中恰好只有一个环 解决这类问题时,通常断环,变成普通的树的问题,然后再特殊处理环 P2607 [ZJOI2008] 骑士 click 断环成树后就跟没上司一样是个树形dp,注意森林,long long就行了,具体细节见这里 P…

vue/cli4跑单个组件测试

环境直接跑一个vue组件,正常的命令是这样的vue serve src/components/demo1.vue输出提示:Command vue serve requires a global addon to be installed.Please run npm i -g @vue/cli-service-global and try again.再次安装npm i -g @vue/cli-service-global