🗒️大模型之LLaMA2
type
status
date
slug
summary
tags
category
icon
password
Llama 2: Open Foundation and Fine-Tuned Chat Models
2023年7月,Meta推出了Llama-2开源大模型,并且推出了Llama-2-Chat对话模型
与一代LLaMA主要区别体现在更多的训练数据、更⻓的上下文窗口、GQA技术等
LLaMA与LLaMA2对比

模型结构的变动主要是体现在GQA和FFN缩放上
- MHA改成GQA:整体参数量会有减少
- FFN模块矩阵维度有扩充:增强泛化能力,整体参数量增加
- 上下文长度是llama两倍(长度从2048->4096) 训练语料增加约 40%,体现在1.4T->2.0T的Tokens llama2-34B和llama2-70B使用了GQA,加速模型训练和推理速度
常见大模型处理流程
(1)输入数据
LLM的输入数据是一段文本,可以是一个句子或一段话。文本通常被表示成单词或字符的序列。
(2)Tokenization
之后需要将文本进行Tokenization,将其切分成单词或字符,形成Token序列。之后再将文本映射成模型可理解的输入形式,将文本序列转换为整数索引序列(这个索引就是单词或字符在语料库中的index),这个过程通常由一些开源的文本Tokenzier工具,如sentencepiece等来处理
(3)Embedding
文本信息经过Tokenization之后变成了token序列,而Embedding则继续将每个Token映射为一个实数向量,为Embeding Vector
(4)位置编码
对于Token序列中的每个位置,添加位置编码(Positional Encoding)向量,以提供关于Token在序列中位置的信息。位置编码是为了区分不同位置的Token,并为模型提供上下文关系的信息。
(5)Transformer
在生成任务中,模型只需要用到Transformer 的decoder阶段,即Decoder-Only,比如GPT、LLaMA 都是。
(6)自回归生成
在生成任务中,使用自回归(Autoregressive)方式,即逐个生成输出序列中的每个Token。在解码过程中,每次生成一个Token时,使用前面已生成的内容作为上下文,来帮助预测下一个Token。
(7)输出处理
生成的Token序列通过一个输出层,通常是线性变换加上Softmax函数,将每个位置的概率分布转换为对应Token的概率。根据概率,选择概率最高的Token或者作为模型的预测结果。或者其他的的方法生成next token ,比如:
LLaMA2模型结构
可以说目前主流的LLM处理模型都是基于Transformer而进行构建的,Llama 2也不例外,而LLM这种生成式的任务是根据给定输入文本序列的上下文信息预测下一个单词或token,所以LLM模型通常只需要使用到Transformer Decoder部分,而所谓Decoder相对于Encoder就是在计算
Q*K时引入了Mask以确保当前位置只能关注前面已经生成的内容。Llama 2的模型结构与标准的Transformer Decoder结构基本一致,主要由32个 Transformer Block 组成,不同之处主要包括以下几点:
- 前置的RMSNorm层,llama中已经使用
- Q在与K相乘之前,先使用RoPE进行位置编码,llama中已经使用
- K V Cache,并采用Group Query Attention
- FeedForward层
KV Cache
大模型推理性能优化的一个常用技术是KV Cache,那么什么是K V Cache呢?首先这里的K V 值得分别是Attention计算时的KV,而非哈希存储引擎中的Key和Value,这里的Cache也不是那个会发生Cache Missing的Cache , 这里的K V Cache就是将Attention 中的KV缓存下来,通过空间换时间的方式来加速计算Attention。
从第一节处理流程中可以知道,在LLama 2模型的推理阶段是采用自回归的方式来进行推理,即每一个Token的生成都是由之前所有生成的所有token作为输入而得到的。

举个例子,假设有这样一个生成任务
而第四次的处理过程是用"将进酒:人生得" 来预测下一个"意"字,所以需要把 "将进酒:人生得" 进行token化后再进行Attention计算,即 ,如下图所示

不难发现在第三次处理的时候,就已经把 "将进酒:人生" 所对应的Q,K,V进行过相关的运算,所以没必要在对他们进行Attention计算,这样就能节省大部分算力,由此K V Cache便是来解决这个问题的:通过将每次计算的K和V缓存下来,之后新的序列进来时只需要从KV Cache中读取之前的KV值即可,就不需要再去重复计算之前的KV了。此外,对于Q也不用将序列对应的所有 QiQi都计算出来,只需要计算最新的 QnewtokenQnewtoken , (即此时句子长度为1), K V同理,所以用简易代码描述一下这个过程就是
至于为什么不用缓存Q? 我理解这是一种单向注意机机制,他只管每次进来的token与past tokens的注意力,而past tokens不会管后面token的注意力,所以就不需要也就不需要缓存Q
MQA和GQA
GQA和MQA都是注意力的变体,其中多个查询头关注相同的键和值头,以减少推理过程中 KV 缓存的大小,并可以显著提高推理吞吐量。
MHA、GQA、MQA的区别和联系,具体的优点如下:
Mutil-Head Attention因为自回归模型生成回答时,需要前面生成的KV缓存起来,来加速计算。
Multi-Query Attention多个头之间可以共享KV对,因此速度上非常有优势,实验验证大约减少30-40%吞吐。
Group Query Attention没有像MQA那么极端,将query分组,组内共享KV,效果接近MQA,速度上与MQA可比较。

Llama-2中使用了8个KV映射,即GQA-8,GQA在多数任务上与MHA效果相当,且平均效果优于MQA;GQA和MQA均比MHA有更好的吞吐量。
GQA实现的代码
FeedForWard层
与标准的Transformer一样,经过Attention层之后就进行FeedForward层的处理,但LLama2的FeedForward与标准的Transformer FeedForward有一些细微的差异,这块没啥好讲的,看代码就行,需要注意的地方就是SiLU激活函数x
有关Notion安装或者使用上的问题,欢迎您在底部评论区留言,一起交流~
- Twikoo
Last update: 2024-08-08
-- 感谢您的支持 ---