【多模态大模型】LLaMA in arXiv 2023
一、引言
论文: LLaMA: Open and Efficient Foundation Language Models
作者: Meta AI
代码: LLaMA
特点: 该方法在Transformer的基础上增加了Pre-normalization (RMSNorm)、SwiGLU activation function (SwiGLU)、Rotary Embeddings (RoPE)、FlashAttention。
⚠️ 在学习该方法前,建议补充BatchNorm、LayerNorm、位置编码、Attention的相关知识。
二、详情
Transformer和LLaMA的结构图如下:

可见,其结构差异主要体现在如下方面:
- Transformer采用了左编码器+右解码器(Encoder+Decoder)的结构,LLaMA采用了仅解码器(Decoder-only)的结构。由于仅包含解码器不需要与编码器输出交互,故LLaMA去掉了Transformer中Decoder中间的交叉Multi-Head Attention和Add & Norm。
- LLaMA采用了归一化前置(Pre-normalization)的策略,将归一化操作放在了注意力、FFN前并在线性映射前增加了一个归一化。此外,LLaMA还将LayerNorm替换为了
RMSNorm
。- LLaMA将绝对位置编码替换为了旋转位置编码,即
RoPE
,这是一种只对Q和K进行位置编码的方式。- 为加速训练,LLaMA引入了
FlashAttention
。- LLaMA将ReLU替换为了
SwiGLU
。
2.1 RMSNorm
均方根归一化RMSNorm
简化了LayerNorm
的计算。
要了解RMSNorm
,首先需回顾LayerNorm
的公式:

其中, x \boldsymbol{x} x为输入的token序列, E [ x ] = 1 n ∑ i = 1 n x i {\bf E}\boldsymbol{[x]}=\frac{1}{n}\sum_{i=1}^{n}\boldsymbol{x}_i E[x]=n1∑i=1nxi和 V a r [ x ] = 1 n ∑ i = 1 n ( x i − E [ x ] ) 2 {\bf Var}\boldsymbol{[x]}=\sqrt{\frac{1}{n}\sum_{i=1}^n(\boldsymbol{x}_i-{\bf E}\boldsymbol{[x]})^2} Var[x]=n1∑i=1n(xi−E[x])2为 x \boldsymbol{x} x的均值和有偏方差, ϵ \boldsymbol{\epsilon} ϵ用来防止分母为0, γ \boldsymbol{\gamma} γ和 β \boldsymbol{\beta} β是可学习的参数用来缩放和平移。
RMSNorm
简化了LayerNorm
的计算,其公式如下:

其中, R M S [ x ] = 1 n ∑ i = 1 n x i 2 {\bf RMS}\boldsymbol{[x]}=\sqrt{\frac{1}{n}\sum_{i=1}^{n}\boldsymbol{x}_i^2} RMS[x]=n1∑i=1nxi2是均方根。
可见,RMSNorm
与LayerNorm
主要有如下差别:
RMSNorm
无需计算均值 E [ x ] {\bf E}[\boldsymbol{x}] E[x]。RMSNorm
将有偏方差 V a r [ x ] {\bf Var[\boldsymbol{x}]} Var[x]替换为了均方根 R M S [ x ] {\bf RMS[\boldsymbol{x}]} RMS[x]。RMSNorm
无需平移项 γ \boldsymbol{\gamma} γ。
与LayerNorm
一样,RMSNorm
也能以句子或单词(token)为单位进行归一化,如下给出了以token为单位的代码示例。
import torch
import torch.nn as nnclass MyRMSNorm(nn.Module):def __init__(self, hidden_dim, eps=1e-8):super().__init__()# 防止分母计算为0self._eps = eps# 仿射变换参数,缩放norm后的数据分布self._gamma = nn.Parameter(torch.ones(hidden_dim))def forward(self, input):# input(N,L,C)ms = input.pow(2).mean(dim=-1, keepdim=True) # 计算均方,token-wiseinput = input / torch.sqrt(ms + self._eps) # 执行标准化return input * self._gamma # 仿射变换if __name__ == '__main__':batch_size = 4length = 2hidden_dim = 3input = torch.rand(4, 2, 3)myRMSN = MyRMSNorm(hidden_dim=hidden_dim)MyO = myRMSN(input)pytorchRMSN = nn.RMSNorm(normalized_shape=hidden_dim, elementwise_affine=False) # 不使用可学习的gamma和betapytorchO = pytorchRMSN(input)print(MyO == pytorchO)
2.2 RoPE
旋转位置编码RoPE
使用绝对位置信息设计旋转规则,使旋转后的数据能够表达相对位置信息。
要了解RoPE
,首先我们来了解一下二维空间的旋转。如下图:

其中, X = [ ρ cos ϕ , ρ sin ϕ ] X=[\rho\cos\phi,\rho\sin\phi] X=[ρcosϕ,ρsinϕ]是一个二维向量,逆时针旋转 θ \theta θ度变成 X R ( θ ) XR(\theta) XR(θ)。此时 R ( θ ) = [ cos θ , sin θ − sin θ , cos θ ] R(\theta)=\left[\begin{matrix}\cos\theta,~\sin\theta\\-\sin\theta,~\cos\theta\end{matrix}\right] R(θ)=[cosθ, sinθ−sinθ, cosθ],证明如下:
X R ( θ ) = [ ρ cos ϕ , ρ sin ϕ ] [ cos θ , sin θ − sin θ , cos θ ] = ρ [ cos ϕ cos θ − sin ϕ sin θ , cos ϕ sin θ + sin ϕ cos θ ] = [ ρ cos ( ϕ + θ ) , ρ sin ( ϕ + θ ) ] XR(\theta)=[\rho\cos\phi,\rho\sin\phi]\left[\begin{matrix}\cos\theta,~\sin\theta\\-\sin\theta,~\cos\theta\end{matrix}\right]\\=\rho[\cos\phi\cos\theta-\sin\phi\sin\theta,\cos\phi\sin\theta+\sin\phi\cos\theta]=[\rho\cos(\phi+\theta),\rho\sin(\phi+\theta)] XR(θ)=[ρcosϕ,ρsinϕ][cosθ, sinθ−sinθ, cosθ]=ρ[cosϕcosθ−sinϕsinθ,cosϕsinθ+sinϕcosθ]=[ρcos(ϕ+θ),ρsin(ϕ+θ)]
可见, X X X与 X R ( θ ) XR(\theta) XR(θ)仅差一个 θ \theta θ,所以二维空间逆时针旋转 θ \theta θ度可通过 R ( θ ) R(\theta) R(θ)实现。
旋转只改变角度,不改变长度。
RoPE
将旋转应用在了注意力模块的查询 Q Q Q和 K K K上。它将第 i i i个查询 Q i Q_i Qi旋转 i θ i\theta iθ的角度,再将第 j j j个键 K j K_j Kj旋转 j θ j\theta jθ的角度,那么 Q i K j T Q_iK_j^T QiKjT就会变成一个与相对位置 i − j i-j i−j相关的值。推导过程如下:

i i i和 j j j是查询 Q i Q_i Qi和 K j K_j Kj的绝对位置, i − j i-j i−j是它们的相对位置。
然而, Q i Q_i Qi和 K j K_j Kj的维度通常都是大于2的,我们假设它是 D D D且 D D D是2的整数倍,于是我们可以将 Q i Q_i Qi和 K j K_j Kj分别划分为 d = D 2 d=\frac{D}{2} d=2D个子空间,每个子空间都是二维的。
下图给出了一个 D = 10 D=10 D=10的例子,我们将 Q i Q_i Qi和 K j K_j Kj分为5个子空间并分配1个包括5个角度的旋转序列 Θ = ( θ 1 , θ 2 , ⋯ , θ 5 ) \Theta=(\theta_1,\theta_2,\cdots,\theta_5) Θ=(θ1,θ2,⋯,θ5),每个子空间的旋转角度是在对应旋转序列的基础上乘以 i i i或 j j j。

将其扩展到 d d d个子空间,可以得到如下信息:

其中, X i X_i Xi代指 Q i Q_i Qi或 K j K_j Kj。此时,这种旋转仍然具有相对位置的表达能力,证明如下:

显然,上面的 R ( i Θ ) R(i\Theta) R(iΘ)过于稀疏,为了提升计算效率,通常 d d d个子空间的旋转使用下式表达:

为避免token数过多, i θ k i\theta_k iθk和 j θ k j\theta_k jθk重叠导致相对位置得不到表达(同一个子空间 k k k,绝对位置 i i i和 j j j不同, i θ k − j θ k = 2 m π i\theta_k-j\theta_k=2m\pi iθk−jθk=2mπ时重叠, m m m是一个整数),RoPE
使用了一个递减的等比数列作为 θ \theta θ序列,如下:

θ k \theta_k θk是递减的,这表示token中前几个子空间的旋转角度较大,越往后旋转角度越小。
事实上,为了方便我们通常不是将相邻的两个值划分至同一子空间,而是将D分为前后两个部分,前后各取一个依次组成子空间,例如[q0,q1,q2,q3]被划分为[q0,q2], [q1,q3]而不是[q0,q1], [q2,q3]。以下为使用这种方式进行子空间划分的RoPE
代码:
from torch.nn import functional as F
import torch.nn as nn
import torch
import mathclass Rotator:"""根据hidden_dim,和position_ids 生成对应的旋转位置编码, 和论文中定义略有不同,一个个二维的子空间被分割到了前后两部分,分别进行旋转,然后拼接起来"""def __init__(self, D, position_ids):""" position_ids: [seq_len], D 和单个头的hidden_dim对应 """base = 10000d = D / 2B = base ** (1/d)theta_base = 1.0 / (B ** (torch.arange(0, d))) # 等比数列, $\Theta$thetas = position_ids.outer(theta_base) # [seq_len, D/2]# 这里的子空间划分与讲解不同,[q0,q1,q2,q3] -> [q0,q2],[q1,q3]是两个子空间而不是[q0,q1],[q2,q3]full_thetas = torch.cat((thetas, thetas), dim=-1) # [seq_len, D]self.cos = full_thetas.cos()self.sin = full_thetas.sin()def rotate(self, x):"""x: [bs, num_attention_heads, seq_len, D]q: [bs, num_attention_heads, seq_len, D]cos: [seq_len, D][x,y] @ [[cos, sin], [-sin, cos]] = [x*cos-y*sin, ycos+x*sin] =[x,y]*cos+[-y, x]*sin"""return x * self.cos + Rotator.reverse_half(x) * self.sin@staticmethoddef reverse_half(q):""" q: [bs, num_attention_heads, seq_len, D] trick2 """u = q[..., :q.shape[-1] // 2] # 认为是各个二维子空间的第一维的向量集结v = q[..., q.shape[-1] // 2:] # 认为是各个二维子空间的第二维的向量集结return torch.cat((-v, u), dim=-1)if __name__ == "__main__":batch_size = 2num_heads = 3D = 6 # 单个头的token向量长度hidden_dim = D * num_headsseq_len = 4position_ids = torch.arange(seq_len)rotator = Rotator(D, position_ids)x = torch.randn((batch_size, seq_len, hidden_dim))# 对每个头分别进行旋转,[batch_size,seq_len,hidden_dim] -> [batch_size,seq_len,num_heads,D] -> [batch_size,num_heads,seq_len,D]x = x.view(batch_size, seq_len, num_heads, D).transpose(1, 2)x = rotator.rotate(x)
2.3 FlashAttention
FlashAttention
以分块的形式进行注意力计算,避免了SRAM和HBM之间频繁读写导致的时间浪费。
详情请参考我之前的博客FlashAttention in NeurIPS 2022。
2.4 SwiGLU
激活函数SwiGLU
是门控线性单元(Gated Linear Units, GLU
)的变体,下图红框中表达了GLU
的计算过程:

可见,GLU
会先使用两个带偏执的线性层映射输入 x \boldsymbol{x} x,分别记为 x W 1 + b 1 \boldsymbol{xW_1+b_1} xW1+b1和 x W 2 + b 2 \boldsymbol{xW_2+b_2} xW2+b2;其中一个线性映射后会跟一个非线性激活函数sigmoid
,记为 σ ( x W 1 + b 1 ) \sigma(\boldsymbol{xW_1+b_1}) σ(xW1+b1);然后将左右两边的结果对应元素相乘即完成了GLU
,记为 σ ( x W 1 + b 1 ) ⊗ ( x W 2 + b 2 ) \sigma(\boldsymbol{xW_1+b_1})\otimes(\boldsymbol{xW_2+b_2}) σ(xW1+b1)⊗(xW2+b2)。
SwiGLU
对GLU
做了两点改进:
- 去掉了两个线性映射的偏执项,此时公式变成 σ ( x W 1 ) ⊗ ( x W 2 ) \sigma(\boldsymbol{xW_1})\otimes(\boldsymbol{xW_2}) σ(xW1)⊗(xW2)。
- 将
sigmoid
替换为了Swish
,此时公式变成 Swish β ( x W 1 ) ⊗ ( x W 2 ) \text{Swish}_{\beta}(\boldsymbol{xW_1})\otimes(\boldsymbol{xW_2}) Swishβ(xW1)⊗(xW2)。
Swish
的公式为 Swish β ( a ) = a σ ( β a ) = a 1 + e − β a \text{Swish}_{\beta}(a)=a\sigma(\beta a)=\frac{a}{1+e^{-\beta a}} Swishβ(a)=aσ(βa)=1+e−βaa,在不同的 β \beta β下该非线性激活函数的曲线如下:

可见,当 β \beta β较大时,该曲线与ReLU
十分接近;当 β = 1 \beta=1 β=1时,小于0但接近0的曲线变得更光滑且非单调。
SwiGLU
则选用了 β = 1 \beta=1 β=1的Swish
,于是我们得到SwiGLU
的公式如下:
Swish ( x W 1 ) ⊗ ( x W 2 ) = x W 1 1 + e − x W 1 ⊗ x W 2 \text{Swish}(\boldsymbol{xW_1})\otimes(\boldsymbol{xW_2})=\frac{\boldsymbol{xW_1}}{1+e^{-\boldsymbol{xW_1}}}\otimes\boldsymbol{xW_2} Swish(xW1)⊗(xW2)=1+e−xW1xW1⊗xW2
致谢:
本博客仅做记录使用,无任何商业用途,参考内容如下:
解密旋转位置编码:数学基础、代码实现与绝对编码一体化探索
一文为你深度解析 LLaMA2 模型架构
Llama改进之——SwiGLU激活函数
相关文章:

【多模态大模型】LLaMA in arXiv 2023
一、引言 论文: LLaMA: Open and Efficient Foundation Language Models 作者: Meta AI 代码: LLaMA 特点: 该方法在Transformer的基础上增加了Pre-normalization (RMSNorm)、SwiGLU activation function (SwiGLU)、Rotary Embed…...
(转)java中restful接口和普通接口的区别
RESTful接口是一种遵循REST(Representational State Transfer)架构风格的网络接口,设计上更倾向于资源的表述,通过HTTP方法(如GET、POST、PUT、DELETE)直接操作资源,使得接口更简洁、易于理解和维护。 与普通接口相比…...

灵办AI免费ChatGPT4人工智能浏览器插件快速便捷(多功能)
灵办AI就是您所需的最佳助手!我们为您带来了一款多功能AI工具,不仅能为您提供精准翻译,还能满足您的对话需求、智能续写、AI搜索、文档阅读、代码生成与修正等多种需求。灵办 AI,真正让工作和学习变得轻松高效! 推荐使…...

VulnHub:BlueMoon
准备工作 靶机下载地址,下载完成后使用virtualbox打开虚拟机,网络设置修改为桥接。 信息收集 主机发现 攻击机ip:192.168.31.218,nmap扫描攻击机同网段存活主机。 nmap 192.168.31.0/24 -Pn -T4 目标靶机ip为:192…...
处理filter里抛出的异常
Filter 的异常是在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter()这里扔出来的。Filter是tomcat负责调用执行的,所以会比 servlet(尤其是SpringMVC 的dispatcherServlet )先执行,所以 Filter 里的错误&…...
IndexedDB深度解析:JavaScript的客户端数据库
IndexedDB是一个在用户浏览器中运行的低等级API,用于存储大量结构化数据。作为NoSQL数据库,IndexedDB为Web应用程序提供了丰富的数据存储能力,支持键值对存储、索引、事务和复杂查询等功能。本文将详细介绍IndexedDB的基本概念、工作原理、使…...
C语言中的函数指针和返回值为数组的函数指针对比
函数指针 //定义一个函数指针,函数的参数是int型,返回值为int typedef int (*func)(int);//定义一个函数指针,函数的参数是int*型,返回值为int* typedef int* (*func)(int *);定义一个返回值为数组指针的函数 //定义…...
根据字符串的长度和字符值的大小来对字符串切片进行排序
在 Go 语言中,根据字符串的长度和字符值的大小来对字符串切片进行排序。示例如下: package mainimport ("fmt""sort" )// 自定义类型,以实现排序接口 type byLengthAndValue []string// 实现 sort.Interface 的 Len 方法 func (s b…...

RabbitMQ 的工作原理
下面是rabbitmq 的工作原理图解 1、客户端连接到消息队列服务器,打开一个channel。 2、客户端声明一个exchange,并设置相关属性。 3、客户端声明一个queue,并设置相关属性。 4、客户端使用routing key, 在exchange和queue 之间…...

WPF 资源、引用命名空间格式、FrameworkElement、Binding、数据绑定
资源 对象级别独立文件 静态资源使用(StaticResource)指的是在程序载入内存时对资源的一次性使用,之后就不再去访问这个资源了。 动态资源使用(DynamicResource)使用指的是在程序运行过程中仍然会去访问资源。 显然,如果你确定…...

vue3-03-创建响应式数据的几种方法
响应式数据 一、 ref 创建:响应式数据1)ref 创建:基本类型的响应式数据2)ref 创建:对象类型的响应式数据3)volar 插件自动添加 .value4)customRef 自定义 ref 二、 reactive 创建:响…...

stm32智能颜色送餐小车(openmv二维码识别+颜色识别+oled显示)
大家好啊,我是情谊,今天我们来介绍一下我最近设计的stm32产品,我们在今年七月份的时候参加了光电设计大赛,我们小队使用的就是stm32的智能送餐小车,虽然止步于省赛,但是还是一次成长的经验吧,那…...

对接的广告平台越多,APP广告变现的收益越高?
无论是游戏、社交、工具应用类APP还是泛娱乐类APP,流量变现的方式主要有广告、内购、订阅三种方式。其中,广告变现是门槛最低、适用最广的变现方式。 只要APP有流量,就可以进行广告变现,让APP的流量快速转化为商业价值。作为最常…...

LINUX原始机安装JDK
文章目录 下载 JDK压缩包创建jdk文件夹sftp 远程上传解压缩 tar -zxvf 包名配置环境变量刷新 环境变量验证是否安装成功安装JAVA 依赖yum更新及替换镜像curl 命令下载更新更新yum依赖判断repo文件是否存在生成缓存、启用阿里云镜像 重新下载java依赖再次验证hello world 下载 J…...

MR400D工业级带网口4G DTU:RS232/RS485 TO LTE深度测评
在物联网技术日新月异的今天,数据传输的效率和稳定性成为了各行各业关注的焦点。作为一款集先进性与实用性于一身的物联网设备,工业级带网口的4G DTU(数据传输单元)以其强大的功能特性和广泛的应用场景,赢得了市场的广…...

第四范式发布AI+5G视频营销产品 助力精准获客与高效转化
产品上新 Product Release 今天,第四范式AI5G视频电话互动营销产品全新发布。 相较于以往销效率低、互动差、转化差的传统电话外呼和短信营销方式,视频电话互动营销基于AI、5G等技术,可让用户接听电话时观看个性化视频广告并实时互动…...

DVWA-IDS测试(特殊版本)
起因 浏览DVWA历史更新记录发现有版本带有IDS插件,可以用于平时没有相关设备等场景演示用,所以开启本次测试。 下载 官方最新版本是移除了IDS插件,原因是“从不使用”,所以需要下载移除该插件之前的版本。 https://github.com/…...

轻度自闭症的温柔启航:星启帆的康复之旅
在儿童成长的道路上,自闭症作为一种复杂的神经发展障碍,给许多家庭带来了挑战与困扰。轻度自闭症,作为自闭症谱系中的一个类型,其症状表现相对较轻,但同样需要我们的关注与科学的干预。星启帆自闭症儿童康复机构&#…...
一、OpenTK简介
文章目录 一、历史和发展二、功能和优势(一)强大的图形渲染功能(二)跨平台支持(三)与 C# 的紧密集成(四)开源和活跃的社区(五)性能优化三、适用场景(一)游戏开发(二)科学计算可视化(三)虚拟现实和增强现实应用(四)图形用户界面开发(五)教育和培训应用(六)…...

Dom4j详细介绍
Dom4j 1.1 解析概览 将数据存储为XML格式后,程序化地访问这些数据变得至关重要。虽然Java基础的IO操作能够实现这一目标,但这一过程往往既复杂又繁琐,尤其是在处理大型文件或需要频繁读写操作的场景下。为了解决这些问题,开发者…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...