用code去探索理解Llama架构的简单又实用的方法

news2024/11/25 0:45:01

除了白月光我们也需要朱砂痣

      我最近也在反思,可能有时候算法和论文也不是每个读者都爱看,我也会在今后的文章中加点code或者debug模型的内容,也许还有一些好玩的应用demo,会提升这部分在文章类型中的比例

      今天带着大家通过代码角度看一下Llama,或者说看一下Casual-LLM的Transfomer到底长啥样

     对Transfomer架构需要更了解的读者,可以先看这个系列

小周带你读论文-2之"草履虫都能看懂的Transformer老活儿新整"Attention is all you need(1) (qq.com)

小周带你读论文-2之"草履虫都能看懂的Transformer老活儿新整"Attention is all you need(2) (qq.com)

小周带你读论文-2之"草履虫都能看懂的Transformer老活儿新整"Attention is all you need(3) (qq.com)

小周带你读论文-2之"草履虫都能看懂的Transformer老活儿新整"Attention is all you need(4) (qq.com)

       友情提示,看代码和debug都不需要GPU,在你的PC上就可以做

       首先先安装transfomer库

       pip install transfomers

       然后进入到库下面,一般在这

图片

       进去就能找到Transfomers的库,往下拉到models,可以发现各种模型都在里面

图片

找到Llama,包含以下文件

图片

      点进modeling_llama.py发现1200多行,根本没法看(一般人没那么多耐心,但是其实仔细看两遍还是很有收获的),然后点击左边outline 大纲,(或者ctrl+shift+o),就可以有选择的看你想要研究的具体网络层,这样感觉压力瞬间小了百分之80以上

图片

      我想查某个函数的代码块,想对它加深了解,举个例子,看起来比较怪异命名的,这个线性扩展RoPE embedding的函数

图片

       然后ctl按住函数名字就能查到它作用于attetion的机制里面,在这种情况下即使我不知道它到底干啥,也能猜个89不离10,至少和什么主模块相关我清楚了

图片

     本章的话,我们先从模型主体部分看起,点LlamaModel,就能看到非常清晰的逻辑

    

图片

    主体部分包含3个子模块:

  • 先要embedding token

  • 再要包含一个通过for循环,不断的持续经过的decoder层

  • 还要包含一个Normal(RMSNorm)

     

     从大面上看也就这么3个操作

     初始化部分,初始了哪些模块我们看完了,再看看细节,从forward看起(大家看任何网络都要重点看forward)

图片

 forward输入部分,要求输入的参数:

  • input_ids:输入序列标记的索引,形状为(batch_size, sequence_length)的torch.LongTensor。

  • attention_mask:避免对填充标记进行注意力计算的掩码,形状为(batch_size, sequence_length)的torch.Tensor

  • position_ids:输入序列标记在位置嵌入中的索引,形状为(batch_size, sequence_length)的torch.LongTensor

  • past_key_values:包含预先计算的隐藏状态(自注意力块和交叉注意力块中的键和值),用于加速顺序解码的tuple,推理用的,当use_cache=True时,会返回这个参数,训练不用管

  • inputs_embeds:直接传入embedding表示而不是input_ids,形状为(batch_size, sequence_length, hidden_size)的torch.FloatTensor

  • use_cache:是否使用缓存加速解码的布尔值,当设置为True时,past_key_values的键值状态将被返回,用于加速解码

  • output_attentions:是否返回所有注意力层的注意力张量,布尔值,当设置为True时,会在返回的结果中包含注意力张量

  • output_hidden_states:是否返回所有层的隐藏状态,布尔值,当设置为True时,会在返回的结果中包含隐藏状态

  • return_dict:是否返回utils.ModelOutput对象而不是普通的元组,布尔值,当设置为True时,会返回一个ModelOutput对象

         我们继续看,下面就是一些操作步骤,输入的input_id,会被向量化,生成hidden_states

图片

    hidden_states然后就被扔进了若干个hidden_layer被for循环来回的操作,比如Llama7B的32层

   

图片

     我们简单写一段逻辑描述上述的代码

     比如在把"我爱你"已经分词的情况下 我=100,爱=200,你=300

  input_ids = [100,200,300]

  input_ids  -> nn.Emebdding(dims=3) -> hidden_states

  hidden_states = [[0.1,0.2,0.3],[0.4,0.5,0.6],[0.7.0.8.1.1]]

  hidden_states ->layer1 ->layer2 ------>layer32

  最终还是hidden_states

  也就是最终的shape和初始的hidden_states的shape的相同的

   hidden_states -> Norm -> hidden_states

   其实没必要把hidden_states理解的那么悬,就当它是个中间变量就可以了

     Layer里面都有什么呢?我们点进去Layer里面就能看到

图片

     包含了我们在Transfomer里学到的attention层,MLP层,LayerNorm这些层

     继续往下

图片

     我们可以看到首先定义了残差,然后hidden_states在没过layer之前就先被Normal了一下(这个知识点以前也讲过,Llama RMS LN是前LN),然后过attetion,过MLP,最后hidden_states=residual+hidden_states, 这样就把位置编码啥的也都带过来了

     然后我们点击进入attetion这块,看看它是咋做的

图片

      这块其实感觉都不用讲了,我觉得全部代码就这块写的逻辑是最清楚的

图片

,QKV矩阵就是下面前三个线性层,然后分别主管生成qkv,上面的参数也解释了多头,和多头dim是咋算出来的,GQA咋算,这块代码写的实在清晰,属实没啥可说的

       最后看一眼MLP层,就是FFN

图片

      这一层是由3个线性层组成的gate+up+down,和标准transfomer的FFN是真不一样,主要有两点不同:

1- 原始transfomer是由两个线性层组成,这里有3个,原因就在于 SwiGLU 激活函数比类似 ReLU 的激活函数,需要多一个 Linear 层(gate)进行门控,所以你说SwiGLU是比ReLU效率高了,还是低了呢?

图片

(当然这个门控可以并行操作)

2- 原始Transfomer第一个线性层先将维度映射为4h维,第二个线性层再映射回h维,接着进行激活函数操作。而llama则是将原有4h变成一个常量作为输入,且计算方式也略有不同,可能是因为4h这个说法如果模型太大会罩不住,就用一个常量来代替了(我瞎猜的)

        这基本网络就讲完了,其实大家看看也没啥玩意,比较简单

      再比如说我们像看一下Llama是咋做下游任务的,modeling里面有2个,我们挑CLM任务(主管生成的任务,CasualLM)来看

图片

     如上图所示,就是在Llama的基础模型之上,加了一个线性层

     然后我们展开LlamaForCausalLM

图片

      可以看到它包含很多内容,这里面重点肯定还是forward(前向),我们就看一下它的前向是怎么进行的,输入是啥,输出是啥?

图片

      我们先看forward输入部分,要求输入的参数和前面都一样唯一的区别就是Label

  • Labels:没法解释,就是字面上的Labels

    图片

    图片

     输出这块我们就关注hidden_states就行了,这也是最重要的

图片

      然后hiden_states和你的labels进行匹配求交叉熵损失,最后损失最小的就是最高概率生成的token 

      下面那个文本分类的其实也是一样的,只不过它计算Loss的时候会有说明,单标签就是回归任务,多标签就变分类任务了

图片

     通过这些简单的方法,就能把读者们把以前理解不太透彻的网络模块都理一遍,加深印象      

     本章完

图片

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[算法前沿]--059-大语言模型Fine-tuning踩坑经验之谈

前言 由于 ChatGPT 和 GPT4 兴起,如何让人人都用上这种大模型,是目前 AI 领域最活跃的事情。当下开源的 LLM(Large language model)非常多,可谓是百模大战。面对诸多开源本地模型,根据自己的需求,选择适合自己的基座模型和参数量很重要。选择完后需要对训练数据进行预处…

Redis——缓存的持久化

1、持久化机制 Redis的所有数据都保存在内存中,如果没有配置持久化功能,Redis重启后数据就会全部丢失,所以需要开启Redis的持久化功能,将数据保存到磁盘上,这样当Redis重启后,可以从磁盘中恢复数据。Redis…

第六篇【传奇开心果系列】Vant of Vue 开发移动应用示例:深度解析响应式布局支持

传奇开心果系列 系列博文目录Vant开发移动应用示例系列 博文目录前言一、Vant响应式布局介绍二、媒体查询实现响应式布局示例代码三、短点设置实现响应式布局示例代码四、响应式工具类实现响应式布局示例代码五、栅格系统实现响应式布局示例代码六、响应式组件实现响应式布局示…

LeetCode.144. 二叉树的前序遍历

题目 144. 二叉树的前序遍历 分析 这道题目是比较基础的题目,我们首先要知道二叉树的前序遍历是什么? 就是【根 左 右】 的顺序,然后利用递归的思想,就可以得到这道题的答案,任何的递归都可以采用 栈 的结构来实现…

【单片机】简单的自定义延时程序设计(代码演示)

前言 大家好吖,欢迎来到 YY 滴 单片机系列 ,热烈欢迎! 本章主要内容面向接触过单片机的老铁 主要内容含: 欢迎订阅 YY滴C专栏!更多干货持续更新!以下是传送门! YY的《C》专栏YY的《C11》专栏YY…

洛谷UVA题目Unknown Error

UnexpectedResponseStatus: expect status code: 301 Moved Permanently on https://onlinejudge.org/index.php?optioncom_comprofiler&tasklogin, got: 200 OK 如果你绑定了账号,去原站Online Judge - Home 登录一下,好久没登陆,需要激…

ElasticSearch级查询Query DSL上

目录 ES高级查询Query DSL match_all 返回源数据_source 返回指定条数size 分页查询from&size 指定字段排序sort 术语级别查询 Term query术语查询 Terms Query多术语查询 exists query ids query range query范围查询 prefix query前缀查询 wildcard query通…

vs2019 - signtool签名和验签的手工操作

文章目录 vs2019 - signtool签名和验签的手工操作概述笔记导入根证书时间戳服务器的选择code sign - 签名文件在代码签名(code sign)前后的区别签名后, 查看属性, 是正常的.用signtool命令行进行验签移除签名END vs2019 - signtool签名和验签的手工操作 概述 signtool是进行c…

【深度学习:MPT-30B】提高开源基础模型的标准

【深度学习:MPT-30B】提高开源基础模型的标准 MPT-30B家族MPT-30B (Base)MPT-30B-InstructMPT-30B-Chat使用 MosaicML Inference 部署 MPT-30B 模型通过 MosaicML 培训定制 MPT-30BLLM Foundry 下一步是什么? 附录致谢数据MPT-30B 8k 上下文窗口微调数据…

2.12作业

程序代码&#xff1a; #include<stdlib.h> #include<string.h> #include<stdio.h>//递归实现n! int n(int element) {if(0element)return 1;return element*n(element-1); }//递归实现0-n的和 int sub_sum(int element) {if(0element)return 0;return eleme…

Java的接口

目录 1.接口的概念 2.语法规则 3.接口的使用 4.接口的特性 总结&#xff1a; 5.实现多个接口 6.接口间的继承 1.接口的概念 接口就是公共的行为规范标准&#xff0c;大家在实现时&#xff0c;只要符合规范标准&#xff0c;就可以通用。 在Java中&#xff0c;接口可以看成…

C语言求解猴子分桃子

问题&#xff1a;海滩上有一堆桃子&#xff0c;五只猴子来分。第一只猴子把这堆桃子平均分为五份&#xff0c;多了一个&#xff0c;这只 猴子把多的一个扔入海中&#xff0c;拿走了一份。第二只猴子把剩下的桃子又平均分成五份&#xff0c;又多了 一个&#xff0c;它同样把多的…

【Java】Spring如何扫描自定义的注解?

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋…

重温阿里云宝塔面板部署前后端项目

首先祝大家新年快乐啊&#xff01; 回到老家&#xff0c;便打算趁这一段空闲时间提升一下自己&#xff0c;重点是学习实践一下echarts相关内容&#xff0c;很多公司项目都需要实现可视化&#xff0c;所以在bilibili上找了黑马的一个教程开始学习&#xff0c;不同的是&#xff…

每日五道java面试题之java基础篇(五)

第一题. final、finally、finalize 的区别&#xff1f; final ⽤于修饰变量、⽅法和类&#xff1a;final 修饰的类不可被继承&#xff1b;修饰的⽅法不可被重写&#xff1b;修饰的变量不可变。finally 作为异常处理的⼀部分&#xff0c;它只能在 try/catch 语句中&#xff0c;…

Nginx与history路由模式:刷新页面404问题

使用nginx部署前端项目&#xff0c;路由模式采用history模式时&#xff0c;刷新页面之后&#xff0c;显示404。 路由模式 前端路由的基本作用为&#xff1a; ①当浏览器地址变化时&#xff0c;切换页面&#xff1b; ②点击浏览器后退、前进按钮时&#xff0c;更新网页内容&…

【python】网络爬虫与信息提取--requests库

导学 当一个软件想获得数据&#xff0c;那么我们只有把网站当成api就可以 requests库:自动爬取HTML页面&#xff0c;自动网络请求提交 robots协议&#xff1a;网络爬虫排除标准&#xff08;网络爬虫的规则&#xff09; beautiful soup库&#xff1a;解析HTML页面 工具&…

使用Cargo创建、编译与运行Rust项目

在 Rust 开发中&#xff0c;Cargo 是一个非常重要的工具&#xff0c;它负责项目的构建、管理和依赖管理。以下是如何使用 Cargo 创建、编译和运行 Rust 项目的详细步骤。 1. 创建新项目 首先确保你已经在计算机上安装了 Rust 和 Cargo。然后&#xff0c;在命令行中输入以下命…

美比特币ETF持仓跨越20万枚BTC大关,成为华尔街有史以来最受欢迎的ETF!

号外&#xff1a;教链内参2.10《内参&#xff1a;BTC真的存在春节模式吗&#xff1f;》 自SEC在2024年1月份一口气批准了十多支比特币现货ETF之后&#xff0c;机构们“不待扬鞭自奋蹄”&#xff0c;在吸收客户上使出浑身解数&#xff0c;激烈竞争。贝莱德&#xff08;IBIT&…

基于微信小程序的在线课堂的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…