文章目录

  • 简介
  • 拆解
  • 一些tricks

简介

因为RoPE的优异性能,其已成为各种大模型中位置编码的首选,包括多模态模型;在一些多模态模型或视频理解模型中,甚至会用到多维度RoPE。虽然RoPE已广泛应用,之前也看了不少针对其原理解析的文章,特别是苏神的推导帖,可能是我个人能力问题,也可能是太过于追求原理的问题,对RoPE一直没有理解透彻,总感觉差那么一点。本文会适当弱化RoPE为什么会有效的原理推导,将重点放在RoPE应该如何实现以及具体的实现步骤和一些不同实现方式的解析。

RoPE的核心思想是通过旋转操作将位置信息融入到词向量。在复数域中,一个复数由实部和虚部组成,故一个复数可以看作复数域中的向量。将一个复数与复数 eiθ=cos⁡θ+isin⁡θe^{i\theta}=\cos{\theta}+i \sin{\theta}eiθ=cosθ+isinθ相乘时,相当于在复平面上绕原点旋转了 θ\thetaθ度角。假设有一个复数 v=x+iyv=x+iyv=x+iy,按上述说明,将 vvveiθe^{i\theta}eiθ相乘就是将 vvv绕原点旋转了 θ\thetaθ度角,可以通过公式推导验证:
v′=v∗eiθ=(x+iy)∗(cos⁡θ+isin⁡θ)=cos⁡θx+isin⁡θx+icos⁡θy−sin⁡θy=(cos⁡θx−sin⁡θy)+i(sin⁡θx+cos⁡θy)\begin{align*} v'&=v*e^{i\theta} \\ &=(x+iy)*(\cos{\theta}+i \sin{\theta}) \\ &=\cos{\theta}x+i\sin{\theta}x+i\cos{\theta}y-\sin{\theta}y \\ &=(\cos{\theta}x-\sin{\theta}y)+i(\sin{\theta}x+\cos{\theta}y) \tag{1} \end{align*}v=veiθ=(x+iy)(cosθ+isinθ)=cosθx+isinθx+icosθysinθy=(cosθxsinθy)+i(sinθx+cosθy)(1)

通过公式(1)有 x′=cos⁡θx−sin⁡θy,y′=sin⁡θx+cos⁡θyx'=\cos{\theta}x-\sin{\theta}y,y'=\sin{\theta}x+\cos{\theta}yx=cosθxsinθy,y=sinθx+cosθy。从二维向量的角度看,变换前后的复数 v,v′v,v'v,v其实均可以看作列向量 [xy],[x′y′]\begin{bmatrix} x \\ y \end{bmatrix},\begin{bmatrix} x' \\ y' \end{bmatrix}[xy][xy],公式(1)表示 v′v'v是由 vvv旋转而来,且恰好对应了二维向量空间的旋转矩阵,如下所示:
[x′y′]=[cos⁡θ−sin⁡θsin⁡θcos⁡θ][xy](2)\begin{equation} \begin{bmatrix} x' \\ y' \end{bmatrix}=\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} \begin{bmatrix} x \\ y \end{bmatrix} \end{equation} \tag2[xy]=[cosθsinθsinθcosθ][xy](2)

如公式(2)所示,在二维向量空间中,将一个向量绕原点旋转 θ\thetaθ度就是乘以一个旋转矩阵,即 R(θ)=[cos⁡θ−sin⁡θsin⁡θcos⁡θ]R(\theta)=\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix}R(θ)=[cosθsinθsinθcosθ]。通过上述推导可知,二维向量空间中的旋转和复数乘法在进行旋转时是等价的。

RoPE是将隐向量序列中不同位置的token的特征向量与不同的旋转角对应的旋转矩阵相乘,即将不同位置token的特征向量旋转不同的角度。注意力计算的主要部分是token向量之间的点积运算,可以通过推导展示RoPE是如何在自注意力计算中引入相对位置信息的。

假设目前token的维度为2,有序列中m处的查询向量 qm=[qm,1qm,2]q_m=\begin{bmatrix} q_{m,1} \\ q_{m,2} \end{bmatrix}qm=[qm,1qm,2]和n处的键向量 kn=[kn,1kn,2]k_n=\begin{bmatrix} k_{n,1} \\ k_{n,2} \end{bmatrix}kn=[kn,1kn,2],设旋转基础角度为 θ\thetaθ,序列中不同位置token的旋转角由位置索引与基础角度相乘得到,即上述两个向量的旋转角度为别是 mθ,nθm\theta,n\thetamθ,nθ,RoPE就是给不同位置的token向量与对应位置的旋转角的旋转矩阵相乘,基于前文的推理,有,
qm′=[cos⁡(mθ)−sin⁡(mθ)sin⁡(mθ)cos⁡(mθ)][qm,1qm,2]=R(mθ)qm(3)\begin{equation} q'_m=\begin{bmatrix} \cos(m\theta) & -\sin(m\theta) \\ \sin(m\theta) & \cos(m\theta) \end{bmatrix} \begin{bmatrix} q_{m,1} \\ q_{m,2} \end{bmatrix} = R(m\theta) q_m \end{equation} \tag3qm=[cos(mθ)sin(mθ)sin(mθ)cos(mθ)][qm,1qm,2]=R(mθ)qm(3)
kn′=[cos⁡(nθ)−sin⁡(nθ)sin⁡(nθ)cos⁡(nθ)][kn,1kn,2]=R(nθ)km(4)\begin{equation} k'_n=\begin{bmatrix} \cos(n\theta) & -\sin(n\theta) \\ \sin(n\theta) & \cos(n\theta) \end{bmatrix} \begin{bmatrix} k_{n,1} \\ k_{n,2} \end{bmatrix} = R(n\theta) k_m \end{equation} \tag4kn=[cos(nθ)sin(nθ)sin(nθ)cos(nθ)][kn,1kn,2]=R(nθ)km(4)

旋转后的两个向量进行以下点积计算:
qm′Tkn′=(R(mθ)qm)T⋅R(nθ)kn=qmT⋅R(mθ)T⋅R(nθ)⋅kn=qmT⋅[cos⁡(mθ)sin⁡(mθ)−sin⁡(mθ)cos⁡(mθ)][cos⁡(nθ)−sin⁡(nθ)sin⁡(nθ)cos⁡(nθ)]⋅kn=qmT⋅[cos⁡(mθ)cos⁡(nθ)+sin⁡(mθ)sin⁡(nθ)−cos⁡(mθ)sin⁡(nθ)+sin⁡(mθ)cos⁡(nθ)−sin⁡(mθ)cos⁡(nθ)+cos⁡(mθ)sin⁡(nθ)sin⁡(mθ)sin⁡(nθ)+cos⁡(mθ)cos⁡(nθ)]⋅kn=qmT⋅[cos⁡((n−m)θ)−sin⁡((n−m)θ)sin⁡((n−m)θ)cos⁡((n−m)θ)]⋅kn=qmT⋅R((n−m)θ)⋅kn\begin{align*} q_m^{'T}k'_n &= (R(m\theta) q_m)^T \cdot R(n\theta) k_n \\ &= q^T_m \cdot R(m\theta)^T \cdot R(n\theta) \cdot k_n \\ &= q^T_m \cdot \begin{bmatrix} \cos(m\theta) & \sin(m\theta) \\ -\sin(m\theta) & \cos(m\theta) \end{bmatrix} \begin{bmatrix} \cos(n\theta) & -\sin(n\theta) \\ \sin(n\theta) & \cos(n\theta) \end{bmatrix} \cdot k_n \\ &= q^T_m \cdot \begin{bmatrix} \cos(m\theta)\cos(n\theta) + \sin(m\theta)\sin(n\theta) & -\cos(m\theta)\sin(n\theta) + \sin(m\theta)\cos(n\theta) \\ -\sin(m\theta)\cos(n\theta) + \cos(m\theta)\sin(n\theta) & \sin(m\theta)\sin(n\theta) + \cos(m\theta)\cos(n\theta) \end{bmatrix} \cdot k_n \\ &= q^T_m \cdot \begin{bmatrix} \cos((n - m)\theta) & -\sin((n - m)\theta) \\ \sin((n - m)\theta) & \cos((n - m)\theta) \end{bmatrix} \cdot k_n \\ &= q^T_m \cdot R((n - m)\theta) \cdot k_n \tag5 \end{align*}qmTkn=(R(mθ)qm)TR(nθ)kn=qmTR(mθ)TR(nθ)kn=qmT[cos(mθ)sin(mθ)sin(mθ)cos(mθ)][cos(nθ)sin(nθ)sin(nθ)cos(nθ)]kn=qmT[cos(mθ)cos(nθ)+sin(mθ)sin(nθ)sin(mθ)cos(nθ)+cos(mθ)sin(nθ)cos(mθ)sin(nθ)+sin(mθ)cos(nθ)sin(mθ)sin(nθ)+cos(mθ)cos(nθ)]kn=qmT[cos((nm)θ)sin((nm)θ)sin((nm)θ)cos((nm)θ)]kn=qmTR((nm)θ)kn(5)

上述公式(5)推导过程要使用高中数学知识–三角函数和差定理。可以看到,两个旋转不同角度后向量的点积与它们之间旋转的角度之差有关系,是一种相对位置的体现,即体现了RoPE给序列中不同位置token引入了相对位置信息。

注意:上述旋转均是逆时针旋转!

拆解

上述只是对RoPE的原理进行了简短解释,尽可能直白地说明RoPE原理,但上述讨论局限在二维空间内,而LLMs模型中token向量的维度都很大,接下来对常规的RoPE实现进行拆解,将整个实现过程解剖出来。

  1. 为了沿用二维旋转矩阵的性质,RoPE会将一个token的高维向量看作多个复数,假设向量特征维度为 ddd(基本所有LLMs中的特征维度数是偶数),那么会将一个ddd维的token特征向量视为 d/2d/2d/2个复数
  • 假设一个token向量为 [1,2,3,4][1,2,3,4][1,2,3,4],那么 [1,2][1,2][1,2]是第一个复数,[3,4][3,4][3,4]是第二个复数
  • 同一个token中的不同复数对的旋转角度不同
  • 基础旋转角 θi=10000−2i/d=110000id2\theta_i=10000^{-2i/d}=\frac{1}{10000^{\frac{i}{\frac{d}{2}}}}θi=100002i/d=100002di1;注意,同一token向量中不同位置复数的旋转角是由 iii来决定的。上文已经说到,一个token向量会分成 d/2d/2d/2个复数, i∈[0,d/2)i \in [0,d/2)i[0,d/2),所以 θi\theta_iθi就对应第 iii对复数的旋转角
    • 10000是一个超参数
  1. 同一序列中不同位置的token向量的旋转角也不同,就是基础旋转角与token对应的序列索引乘积,即一个token在序列中的索引为m,那么其对应的最终的旋转角为 θi⋅m\theta_i \cdot mθim
  • 实现时一般会先将 θi\theta_iθi计算出来,再基于序列长度获取不同位置token索引的一维向量,然后两者相乘,得到不同位置token中不同复数维度的准确旋转角度
  1. 将输入沿着特征维度,按顺序每两个为一组作为一对复数进行拆分,向量维度从[batch_size, seq_len, dim]–>[batch_size, seq_len, dim//2, 2]
  • 最后一个维度中,第一组向量为所有复数的实部,第二组向量为所有复数的虚部
  1. 按照二维矩阵中的计算方式,进行旋转矩阵乘法,然后将最终的实部和虚部重新合并为原来的维度[batch_size, seq_len, dim],即完成了RoPE的应用

上述对RoPE的具体操作过程进行了叙述,以下是一种较原始的朴素实现:

import torchdef get_rotary_matrix(seq_len, dim, base=10000):"""生成RoPE的旋转矩阵"""# 生成不同频率的正弦和余弦值theta = 1.0 / (base ** (torch.arange(0, dim, 2).float() / dim))  # shape为[dim//2]# 生成位置索引position = torch.arange(seq_len).float()  # shape为[seq_len]# 计算每个位置和维度对应的角度theta = torch.outer(position, theta)  # 计算外积,其中第(i, j)个元素是position[i] * theta[j];shape为[seq_len, dim//2]# 计算正弦和余弦值cos = torch.cos(theta)  # shape为[seq_len, dim//2]sin = torch.sin(theta)  # shape为[seq_len, dim//2]return cos, sindef apply_rotary_embedding(x, cos, sin):"""应用旋转位置编码"""# 假设x的形状为[batch_size, seq_len, dim]# 将向量视为复数,每两个维度一组x_reshape = x.view(*x.shape[:-1], -1, 2)  # shape为[batch_size, seq_len, dim//2, 2],即沿着特征维度拆分# 构建正弦和余弦矩阵,使其与x_reshape形状匹配cos_expanded = cos.view(1, cos.shape[0], cos.shape[1], 1)  # shape为[1, seq_len, dim//2, 1]sin_expanded = sin.view(1, sin.shape[0], sin.shape[1], 1)  # shape为[1, seq_len, dim//2, 1]# 旋转操作(复数乘法)# [x_real, x_imag] * (cos + i*sin) = [x_real*cos - x_imag*sin, x_real*sin + x_imag*cos]x_out_1 = x_reshape[:, :, :, 0:1] * cos_expanded - x_reshape[:, :, :, 1:2] * sin_expandedx_out_2 = x_reshape[:, :, :, 0:1] * sin_expanded + x_reshape[:, :, :, 1:2] * cos_expanded# 合并结果x_out = torch.cat([x_out_1, x_out_2], dim=-1)  # shape为[batch_size, seq_len, dim//2, 2]return x_out.view(*x.shape)# 示例用法
def apply_rope(x):"""对输入向量应用RoPE位置编码"""batch_size, seq_len, dim = x.shapecos, sin = get_rotary_matrix(seq_len, dim)return apply_rotary_embedding(x, cos, sin)# 测试代码
if __name__ == "__main__":# 创建一个随机输入张量batch_size, seq_len, dim = 2, 10, 512x = torch.randn(batch_size, seq_len, dim)# 应用RoPEx_with_rope = apply_rope(x)print(f"输入形状: {x.shape}")print(f"输出形状: {x_with_rope.shape}")

一些tricks

  • 在对输入的嵌入维度上应用RoPE时,当特征维度很长,或者希望节约资源资源时,可以不对所有维度全部应用,而是可以设置一个比例,即只在前 droped_{rope}drope维度上应用RoPE,后面保持原始数值不变
  • 在计算 θi\theta_iθi时原始论文使用的base为10000,但可以对其进行缩放,实现长度外推;如增加base,可以处理训练过程中未见过的长序列

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

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

相关文章

windows 获取 APK 文件的包名和启动 Activity 名称

使用 aapt 命令确保环境变量配置正确:首先需要确保你的系统环境变量中包含了 Android SDK 的 build-tools 目录路径。这是因为 aapt 工具位于该目录下。运行命令: 打开命令提示符(CMD),然后输入以下命令来查看 APK 的详…

【Mac版】Linux 入门命令行快捷键+联想记忆

Linux Mac 用户终端命令行快捷键 符号速查全解作为一个刚接触 Linux 和终端的 macOS 用户,常常被命令行的各种快捷键和符号弄得头晕脑胀,本文将带你系统地掌握命令行中最常用的快捷键和符号,并通过逻辑联想帮助你轻松记住每一个组合。一、基…

AUTOSAR Mcal Dio - 模块介绍 + EB配置工具介绍

文章目录1. 模块简介2. 主要功能3. 缩略语4. API接口5. 功能介绍5.1. ChannelGroup5.2. Dio_MaskedWritePort6. 序列图6.1.读GPIO电平6.2. 设置GPIO电平7. EB 工具配置7.1.General7.2.DioPort8. 参考资料1. 模块简介 Dio,全称“Digital Input Output”。Dio模块&am…

ICT模拟零件测试方法--晶体管测试

ICT模拟零件测试方法–晶体管测试 文章目录ICT模拟零件测试方法--晶体管测试晶体管测试晶体管测试配置晶体管测试配置晶体管测量选项晶体管测试 i3070 在线测试软件为每个晶体管提供两种测试: 使用二极管测试对晶体管的两个 PN 结进行测试。这是检查设备存在的快速…

AI算法实现解析-C++实例

基于C++实现的AI 以下是基于C++实现的AI/机器学习相关示例,涵盖基础算法、计算机视觉、自然语言处理等领域,适合不同阶段的学习者参考: 基础机器学习算法 线性回归 使用梯度下降法预测连续值,核心公式: 损失函数: 逻辑回归 二分类问题实现,Sigmoid函数: K-Means…

亚马逊云科技实战架构:构建可扩展、高效率、无服务器应用

对于今天的开发者、架构师和技术爱好者而言,云计算早已超越了简单的“虚拟机租赁”或“服务器托管”阶段。它已经演化为一套丰富、强大且精密的工具集,能够以前所未有的方式设计、部署和扩展应用程序。真正的云原生思维,是掌握并运用多种架构…

论文阅读:《无约束多目标优化的遗传算法,群体和进化计算》

前言 提醒: 文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。 其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展…

嵌入式单片机中位带操作控制与实现

STM32 单片机的SRAM有两个区支持位带(bit-band)操作。 那么,什么是位带,位带操作的原理是怎样的呢? 今天来梳理一下这个知识点。 在介绍位带操作之前,先看一看 ARM Crotext-M3 的存储器映射。 CM3 的地址空间是 4GB, 程序可以在代码区,内部 SRAM 区以及外部 RAM 区中执…

考研初试专业分146!上岸新疆大学!信号与系统考研经验,通信考研小马哥。

信号与系统专业课分数146,希望以下的经验能够帮助到正在努力学习的学弟学妹们更好的学习专业课。本人是从四月份开始学习专业课,当时我觉得专业课应该要尽早开始越拖到后期学习压力越大,所以在周边同学还在只学习公共课的时候我就开始了专业课…

负载均衡算法中的加权随机算法

import org.apache.commons.lang3.tuple.Pair;import java.util.Arrays; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors;/*** 加权随机,nacos*/ public class RouterWeightRandom {/**** param list [{"a&q…

AI时代SEO关键词优化策略

内容概要 在人工智能(AI)技术深度融入数字营销的背景下,搜索引擎优化(SEO)的关键词优化策略正经历一场智能变革,这不仅重塑了传统研究方式,还为企业带来了全新的竞争机遇。本文将从AI时代SEO的变…

复矩阵与共轭转置矩阵乘积及其平方根矩阵

设 是一个 的复数矩阵,其共轭转置矩阵(Hermitian 共轭)记为 (即 ),则矩阵 ( )和 ( )的性质如下文所述。1. Hermitian 性(自共轭性&#x…

Vue 框架 学习笔记

作为初学者对于Vue框架的学习笔记 总结了Vue框架的核心知识点,包括:1. 基础概念:渐进式框架、两种使用方式、Vue实例创建流程、模板语法和响应式特性。2. 常用指令:详细介绍了v-html、v-show/v-if、v-for、v-on、v-bind、v-model等…

飞牛系统安装DataEase自定义Docker包

飞牛系统安装DataEase自定义Docker包背景构造DataEase Docker包1.在Linux 系统中(比如我这里选麒麟V10)安装Docker2.准备打包文件3.执行打包4.验证打好的包上传DataEase Docker包1.把本地docker 容器导出1.1查看镜像列表命令:docker images1.…

可配置的PWM外设模块

🔧 可配置的PWM外设模块 基于FPGA的PWM信号发生器,支持 动态周期与占空比配置,无需外部控制信号,适用于 LED 呼吸灯、舵机控制、电机驱动等场景。 仿真波形 参数修改后会晚一个pwm周期才生效📌 模块功能 🧮…

从零到一:我是如何用深度学习打造高性能书籍推荐系统的

作者:笙囧同学 | 发布时间:2025年7月28日 | 阅读时长:15分钟 🎯 前言:为什么要做这个项目? 大家好,我是笙囧同学!最近在学习《机器学习基础》课程时,被推荐系统的魅力深…

OpenRLHF:面向超大语言模型的高性能RLHF训练框架

“四模型协同调度破资源壁垒,让70B模型RLHF训练触手可及” OpenRLHF 是由 OpenLLMAI 团队于2024年推出的开源强化学习人类反馈(RLHF)框架,旨在解决大语言模型(LLM)对齐训练中的多模型协调瓶颈与超大规模扩展…

DMETL安装流程及简单使用

目录 安装调度器 安装执行器 安装管理器 启动服务 进入web管理端 创建数据源 ​编辑 添加表 添加影子表增量 节点监控 DMETL工程流搭建实践 创建表/视图 添加sql脚本 添加数据清洗与转换模块 添加排序模块 创建输出表 连接各模块并启动 查看验证结果 监控管理 …

如何通过代码操作文件?

1. 为什么使用文件不使用文件,我们所写的程序存在电脑内存中,程序结束,内存回收,数据就丢失了。再次运行程序也是看不到上次运行时的数据的,如果想要将数据进行持久化保存,就需要使用文件。2. 文件分类&…

unbuntn 22.04 coreutils文件系统故障

文章目录核心思路具体操作步骤(需借助 Ubuntu Live USB)1. 准备 Ubuntu Live USB2. 从 Live USB 启动并挂载系统分区3. 从安装包中提取完好的 /bin/dir 文件并替换4. 重启系统并验证总结前提说明具体操作步骤(分阶段执行)阶段1&am…