如何修改大模型的位置编码 --以LLama为例

从ChatGLM到LLaMA,聊聊大模型都在用的RoPE位置编码(附PyTorch核心代码) 本文深入探讨了旋转位置编码(RoPE)在大模型如ChatGLM和LLaMA中的应用,解析其如何通过复数空间中的旋转矩阵革新位置编码技术。RoPE不仅解决了传统编码的长度外推性问题,还提升了模型处理长文本的能力,成为现代Transformer架构的关键组件。文章包含PyTorch核心代码实现,帮助开发者快速集成RoPE到自定义模型中。 阅读详情

最近在看RoPE相关内容,一些方法通过简单修改位置编码就可以无需训练支持更长的文本内容。由于一些模型,已经训练好了,但是怎么修改已经训练好的模型位置编码。查了以下相关代码,记录一下。原理这里就不细讲了,贴几个相关博客。
十分钟读懂旋转编码(RoPE)
Transformer升级之路:11、将β进制位置进行到底
Transformer升级之路:10、RoPE是一种β进制编码

NTK

下图为NTK的原理证明:截取自Transformer升级之路:10、RoPE是一种β进制编码
在这里插入图片描述
在这里插入图片描述

看了上面的公式,我在考虑为什么需要建立 λ \lambda λ和k之间的关系?

因为我们要修改 β \beta β进制为 β λ \beta\lambda βλ,由于k我们是可以知道的比如我们需要把位置编码缩小为10倍,直接设置k为10,但是采用NTK的方式,维度缩小为10倍,那么我们就不确定, λ \lambda λ怎么设置了。所以需要简历 λ \lambda λ和k之间的关系,从上图可知, λ = k 2 / ( d − 2 ) \lambda=k^{2/(d-2)} λ=k2/(d−2)。
下面开始理解如何修改RoPE为NTK的形式:
以下为LLama的RoPE代码实现

class LlamaRotaryEmbedding(nn.Module):
    def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None, scaling_factor=1.0):
        super().__init__()
        self.scaling_factor = scaling_factor
        self.dim = dim
        self.max_position_embeddings = max_position_embeddings
        self.base = base
        inv_freq = 1.0 / (self.base ** (torch.arange(0, self.dim, 2, dtype=torch.int64).float().to(device) / self.dim))
        self.register_buffer("inv_freq", inv_freq, persistent=False)
        # For BC we register cos and sin cached
        self.max_seq_len_cached = max_position_embeddings
        t = torch.arange(self.max_seq_len_cached, device=device, dtype=torch.int64).type_as(self.inv_freq)
        t = t / self.scaling_factor
        freqs = torch.outer(t, self.inv_freq)
        # Different from paper, but it uses a different permutation in order to obtain the same calculation
        emb = torch.cat((freqs, freqs), dim=-1)
        self.register_buffer("_cos_cached", emb.cos().to(torch.get_default_dtype()), persistent=False)
        self.register_buffer("_sin_cached", emb.sin().to(torch.get_default_dtype()), persistent=False)

    @property
    def sin_cached(self):
        logger.warning_once(
            "The sin_cached attribute will be removed in 4.39. Bear in mind that its contents changed in v4.38. Use "
            "the forward method of RoPE from now on instead. It is not used in the `LlamaAttention` class"
        )
        return self._sin_cached

    @property
    def cos_cached(self):
        logger.warning_once(
            "The cos_cached attribute will be removed in 4.39. Bear in mind that its contents changed in v4.38. Use "
            "the forward method of RoPE from now on instead. It is not used in the `LlamaAttention` class"
        )
        return self._cos_cached

    @torch.no_grad()
    def forward(self, x, position_ids):
        # x: [bs, num_attention_heads, seq_len, head_size]
        inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1)
        position_ids_expanded = position_ids[:, None, :].float()
        # Force float32 since bfloat16 loses precision on long contexts
        # See https://github.com/huggingface/transformers/pull/29285
        device_type = x.device.type
        device_type = device_type if isinstance(device_type, str) and device_type != "mps" else "cpu"
        with torch.autocast(device_type=device_type, enabled=False):
            freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
            emb = torch.cat((freqs, freqs), dim=-1)
            cos = emb.cos()
            sin = emb.sin()
        return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)

λ \lambda λ和k之间的关系,那么代码怎么实现呢,我们只需要修改 β λ \beta\lambda βλ的结果即可,其中 β \beta β为 1000 0 2 / d 10000^{2/d} 100002/d。
参考代码为:点击

import transformers

old_init = transformers.models.llama.modeling_llama.LlamaRotaryEmbedding.__init__
def ntk_scaled_init(self, dim, max_position_embeddings=2048, base=10000, device=None):

    #The method is just these three lines
    max_position_embeddings = 16384
    k = 8 #Alpha value
    base = base * k ** (dim / (dim-2)) #Base change formula

    old_init(self, dim, max_position_embeddings, base, device)
transformers.models.llama.modeling_llama.LlamaRotaryEmbedding.__init__ = ntk_scaled_init

为什么采用base = base * k ** (dim / (dim-2)),原始的base为10000, 而 β \beta β为 1000 0 2 / d 10000^{2/d} 100002/d,发现在代码里面修改的仅仅是base的结果, β \beta β= b a s e 2 / d base^{2/d} base2/d,而 λ = k 2 / ( d − 2 ) \lambda=k^{2/(d-2)} λ=k2/(d−2),我们需要把k和base进行融合,修改成,base*k的形式形成新的base, λ \lambda λ等于k的指数 2 / ( d − 2 ) ∗ d / 2 ∗ 2 / d = d / ( d − 2 ) ∗ 2 / d 2/(d-2)*d/2*2/d=d/(d-2)*2/d 2/(d−2)∗d/2∗2/d=d/(d−2)∗2/d, λ = ( k d / ( d − 2 ) ) 2 / d \lambda=(k^{d/(d-2)})^{2/d} λ=(kd/(d−2))2/d,因为2/d在RoPE的代码里面已经计算过了:

inv_freq = 1.0 / (self.base ** (torch.arange(0, self.dim, 2, dtype=torch.int64).float().to(device) / self.dim)

所以我们则赋值新的base为base * k ** (dim / (dim-2))。

Dynamic NTK

Dynamic在NTK的基础上进行简单的修改,采用NTK的时候更加灵活。
截图源于:RoPE到底是何方神圣(数学推理+优化方法)
在这里插入图片描述
代码实现:

class LlamaDynamicNTKScalingRotaryEmbedding(LlamaRotaryEmbedding):
    """LlamaRotaryEmbedding extended with Dynamic NTK scaling. Credits to the Reddit users /u/bloc97 and /u/emozilla"""

    def forward(self, x, position_ids):
        # difference to the original RoPE: inv_freq is recomputed when the sequence length > original length
        seq_len = torch.max(position_ids) + 1
        if seq_len > self.max_position_embeddings:#只有长度超过了预训练的阈值,进行NTK
            base = self.base * (
                (self.scaling_factor * seq_len / self.max_position_embeddings) - (self.scaling_factor - 1)
            ) ** (self.dim / (self.dim - 2))
            inv_freq = 1.0 / (
                base ** (torch.arange(0, self.dim, 2, dtype=torch.int64).float().to(x.device) / self.dim)
            )
            self.register_buffer("inv_freq", inv_freq, persistent=False)  # TODO joao: this may break with compilation

        cos, sin = super().forward(x, position_ids)
        return cos, sin
开源大模型长文本能力增强:位置编码插值原理与LS-LLaMA实战 在自然语言处理领域,Transformer架构因其强大的序列建模能力而成为大语言模型的基石。其核心组件之一——位置编码,负责为输入序列中的每个词元注入位置信息,是模型理解词序和依赖关系的关键。传统绝对位置编码或旋转位置编码(RoPE)在训练长度内表现良好,但面临长序列外推时,模型会出现“失忆”或性能急剧下降的挑战。为解决这一瓶颈,位置编码插值(Position Interpolation, PI)及其改进版NTK-aware插值等技术应运而生。它们通过将推理时的长位置索引线性或非线性地“压缩”回模型熟悉的训 阅读详情

相关推荐

Vicuna-13B本地部署实战:llama.cpp量化推理与GGUF优化指南

大语言模型本地部署是AI工程化落地的关键环节,其核心在于平衡显存占用、推理精度与运行效率。Vicuna-13B作为主流开源对话模型,具备较强中文理解能力,但原生PyTorch加载易触发CUDA内存溢出;而llama.cpp通过GGUF格式封装、细粒度量化(如Q4_K_M)及C++底层优化,显著提升稳定性与可控性。GGUF不仅存储权重,更固化RoPE参数、词表映射等运行时元数据,保障跨平台行为一致;量化则需在精度与资源间权衡,非越低越好。本文聚焦显存受限环境(如单卡RTX 3090),详解从编译、模型验证、P

cuixie2370的博客 542

ollama修改模型的下载位置解决C盘空间不足问题

列举了WIndows和Linux操作系统修改默认ollama的模型保存地址方法,解决c盘空间被挤满的问题

lujx_1024的博客 5万+

从LLaMA到ChatGLM:为什么大模型都爱用RoPE旋转位置编码?附PyTorch手写实现

本文深入探讨了RoPE旋转位置编码在大语言模型(如LLaMA和ChatGLM)中的应用优势。RoPE通过将位置信息转化为旋转矩阵,在保持计算高效的同时,显著提升了模型的外推能力和性能表现。文章还提供了PyTorch手写实现RoPE的核心代码,帮助开发者深入理解这一技术。

weixin_30696427的博客 624

如何修改Ollama的模型下载位置

目前ollama下载的模型都默认存在C盘的用户目录下,太占用C盘磁盘,C盘系统满了,系统将会卡顿并且运行不起来,那么如何修改模型下载的位置了?

m0_50572459的博客 1万+

常见大模型(llama,qwen,gpt)的结构,这些架构的区别

结构本质一致:三者都是基于Transformer解码器的自回归语言模型,主要区别在实现细节和部分技术创新。Qwen强化中文:Qwen针对中英混合、中文Token优化做了更多本地化处理。LLaMA关注轻量与开放:LLaMA更强调公开透明及高效推理。GPT结构更神秘:OpenAI对GPT-4及后续版本的结构细节披露更少,但大体还是在Transformer解码器技术线上。

ttest11的博客 2384

【AI】修改 Ollama 默认模型存放路径的完整指南

ollama在构筑AI应用时是用于统一管理模型库的核心组成部分。默认存放ollama模型库的位置是C盘的用户文件夹的.llama-》model下。但是这样C盘很容易占满。好了,有没有办法改变ollama的默认模型存放位置呢?插一句话,越来越觉得不分区有不分区的方便。

每日出拳老爷子的博客 2万+

Llama为何要采用RoPE旋转位置编码?

最近在做 LLM 窗口外推的相关工作,因此刚好也回顾一下目前最流行的位置编码 RoPE。01RoPE(Rotary Position Embedding),是苏剑林大神在 2021 年就提出的一种 Transformer 模型的位置编码。RoPE 是一种可以以绝对位置编码形式实现的相对位置编码,兼顾了模型性能和效率。2023 年上半年的时候,大模型位置编码尚有 Alibi 和 RoPE 在相互比拼,而到了 2023 年下半年,及今 2024 年,新开源出来的模型,大部分都是使用 RoPE 了。

m0_64752471的博客 1370

ollama在linux更改模型存放位置,全网首发2024!

ollama在linux更改模型存放位置 ​ 更改ollama拉取量化模型的存储路径,只需要在启动ollama serve的时候,更改OLLAMA_MODELS环境变量: export OLLAMA_MODELS=/root/autodl-tmp 然后启动ollama serve,当然如果以服务运行的话可以: sudo systemctl restart ollama

拥抱具身智能,昇腾Ascend C 4328

【AI大模型面试题】Llama为何要采用RoPE旋转位置编码?

RoPE(Rotary Position Embedding),是苏剑林大神在 2021 年就提出的一种 Transformer 模型的位置编码。 RoPE 是一种可以以绝对位置编码形式实现的相对位置编码,兼顾了模型性能和效率。 2023 年上半年的时候,大模型位置编码尚有 Alibi 和 RoPE 在相互比拼,而到了 2023 年下半年,及今 2024 年,新开源出来的模型,大部分都是使用 RoPE 了。当然 Alibi 也有其优势,这个在讲 Alibi 的时候来说。

Android23333的博客 1627

百川Dynamic NTK-ALiBi的代码实现:无需微调即可推理更长文本

NTK-ALiBiNTK-ALiBi:通过插值实现大模型ALiBi位置编码的长文本外推。

qq_44193969的博客 1751

Meta开源大模型:羊驼系列

旋转位置编码(Rotary Position Embedding,简称RoPE)是一种高效且有效的位置编码方法,用于增强(每个)自注意力机制在处理序列数据时的位置敏感度,特别适合于处理长序列和动态长度的序列。它的主要目的是稳定和加速训练过程,通过调整激活值的尺度,确保它们在一个合适的范围内变化,从而避免梯度消失或爆炸问题。总的来说,LLaMA和GPT在架构和训练过程上有一些差异,LLaMA通过一些架构修改和使用公开数据集等方法实现了与GPT相当的性能,同时具有更好的可访问性和可复现性。

982

【AI大模型面试真题】Llama为何要采用RoPE旋转位置编码?

在文本长度不长的情况下(比如 Bert 时代基本都是 256/512 token 的长度),相对位置编码和绝对位置编码在使用效果上可以说没有显著差别。 如果要处理更大长度的输入输出,使用绝对位置编码就需要把训练数据也加长到推理所需长度,否则对于没训练过的长度(训练时没见过的位置编码),效果多少会打些折扣。

Android23333的博客 1135

Vivado ChipScope Debugging: Overcoming Common DRC Errors in FPGA Design

本文深入解析Vivado ChipScope调试中常见的DRC错误,特别是AVAL-244和AVAL-245等时钟相关问题,提供实用的Tcl命令解决方案和最佳实践。通过将DRC错误降级为警告的技巧,帮助FPGA设计者高效完成调试流程,同时强调何时应保留DRC检查以确保设计可靠性。

weixin_30335575的博客 416

Llama-Factory是否允许修改位置编码(Positional Encoding)?

本文探讨Llama-Factory是否支持修改位置编码,揭示其通过配置驱动的方式实现RoPE缩放、ALiBi迁移等操作,无需修改代码即可扩展上下文长度,适用于长文本处理与低资源部署场景。

weixin_35972981的博客 346

C#实战:基于ONNX与SCRFD/ArcFace的高效人脸识别系统开发

本文详细介绍了如何在C#环境中,利用ONNX Runtime高效部署SCRFD人脸检测与ArcFace人脸识别模型,构建一个完整的、高性能的人脸识别系统。内容涵盖环境搭建、模型推理、人脸对齐、特征提取等核心模块,并提供了从Demo到生产系统的优化思路与实战代码,为.NET开发者提供了一套开箱即用的解决方案。

weixin_29061821的博客 488

告别GIS软件!用R语言ggplot2+ggmapcn绘制出版级世界地图(附5种投影对比图)

本文提供了一份完整的实践指南,教你如何利用R语言及其强大的ggplot2生态系统,结合ggmapcn包,绘制出出版级的世界地图。文章详细对比了五种经典地图投影(如摩尔维德、罗宾森投影)的代码实现与视觉差异,并讲解了如何添加比例尺、指北针等专业元素,最终导出高清PDF,实现从数据分析到专业可视化的全流程代码化操作,彻底告别传统GIS软件。

p5l2m9n4o6q的博客 407

什么是RoPE-旋转位置编码?

我们知道句子中不同词语之前的位置信息十分重要,但是self-attention框架无法直接利用位置信息,因此研究者提出了许多方法将位置信息编码到学习过程中。一是绝对位置编码方法,将位置信息直接加入到输入中;二是相对位置编码方法,研究者通过微调attention的结构,使它具有识别token位置信息的能力。本文作者详细梳理了位置编码的流派,提出了一种旋转位置编码方式RoPE,并从数学角度证明RoPE带来的诸多优点。

TFATS的博客 4635

【UE5+Quest3】手部模型替换---3-0

这次手部模型替换遇到了一些小问题,不过好在是bug一个个都处理掉了,我会分开几个章节去整理。详细的视频教程可以参考油管大佬的视频手部素材放到文章末尾,自行下载使用。(仅用作学习研究,不可用于商用)

qbbmnnnnnn的博客 944

为什么Llama、Gemma等大模型都选择RoPE?位置编码技术解析

RoPE成为主流大模型位置编码选择,不仅因其设计精巧实现相对位置编码,更因其工程友好性:零额外参数、计算效率高、易于扩展。尽管ALIBI、DAPE等方法在特定评估上表现更优,但巨大的计算开销和难以优化使其难以在工业界应用。工业界在效果、效率、稳健性和可扩展性之间选择了近乎完美平衡的RoPE,在没有颠覆性方案出现前,它仍将是首选。

WANGJUNAIJIAO的博客 1018

ST MotorControl Workbench 6.2.1 自定义硬件配置避坑指南

本文详细介绍了ST MotorControl Workbench 6.2.1在自定义硬件配置中的常见问题与解决方案,涵盖功率板配置、采样电路校准、电机参数设置及代码生成避坑指南,帮助开发者高效完成电机控制项目开发。

red88的博客 1023

stop pin/ignore pin/exclude pin/float pin

stop pin、ignore pin、exclude pin、float pin的区别

m0_61544122的博客 7288

长文本理解挑战:Llama-Factory对位置编码的优化策略

Llama-Factory通过支持RoPE与ALiBi等现代位置编码机制,实现对长文本的高效微调。其模块化架构可自动适配多种模型的位置编码类型,并提供动态扩展、低资源训练等功能,显著提升大模型在金融、法律等长上下文场景中的理解能力。

weixin_28949937的博客 549

国债期货的日线趋势跟踪策略实现(基于backtrader框架)

通过backtrader框架,我们可以轻松地实现国债期货的日线趋势跟踪策略,并进行回测和验证。通过这种策略,我们可以尝试捕捉国债期货价格的短期趋势,并根据趋势的方向进行交易决策。backtrader提供了许多内置的指标、订单类型和其他功能,可以帮助你进一步优化和改进你的策略。它提供了丰富的工具和功能,使我们能够快速实现和验证我们的交易想法。方法中,我们根据当前价格和前一天的价格判断趋势的方向,并根据趋势的变化进行买入或卖出操作。然后,我们设置了初始资金和交易手续费,并将我们定义的策略。来跟踪每日的收盘价。

NisyPhilosophy的博客 404

大模型位置编码全解析:从基础原理到 RoPE、ALiBi 实战对比

问题 1:位置编码不一致。训练时没见过 512 以后的位置,位置信息无效;问题 2:注意力范围变大。推理时 Attention 要处理更多 token,计算逻辑和训练时不一致,导致性能暴跌。若做短文本任务(≤训练长度):训练式绝对编码足够用,实现简单;若做长文本推理(> 训练长度):优先选 RoPE 或 ALiBi,天然支持长度外推;若追求算力效率:ALiBi 最优(无额外计算开销);若兼顾绝对与相对位置:RoPE 是目前的 “最优解”(LLaMA、GLM 等主流大模型都在用)。

ppbk_的博客 642

FPGA 学习笔记:Vivado 配置IO引脚约束

FPGA 学习笔记:Vivado 配置IO引脚约束

坚韧与专注 2万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

上一篇: Mixtral MOE代码理解
下一篇: Query2doc——Query改写
Re:fused
博客等级 码龄9年 474粉丝 162原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值