Transformer为什么需要“位置编码”?

在这里插入图片描述

坐标苏州的学员,通过训练营的项目和面试辅导,拿下苏州某国企大模型offer,年薪30w+,虽然相比于互联网不高,但是在二线城市国企,也很稳定了,恭喜上岸!

01

Transformer的位置编码

对于序列处理模型,他的位置信息需要通过显式或者隐式的方式传入给模型。

transformer 系列模型的位置编码常用包括:包括绝对位置编码(包括静态位置编码和可学习位置编码)、相对位置编码、旋转位置编码,下面详细介绍这种位置编码的原理和优缺点。

02

位置编码

(1)静态位置编码

transformer 原始位置编码方式,通过正弦/余弦函数得到位置编码,为什么要使用正余弦交替出现的方式来得到位置编码呐?

公式1

主要的考虑的点如下:

  • 每个 token 的向量是唯一值;

  • 利用三角函数做位置编码可以保证编码的值在 [-1,1] 之间,是有界函数;

  • 不同的位置向量是可以通过线性变化得到的,这样 token 的位置信息不仅包含了绝对位置还包含了相对位置信息;

三角函数静态编码的重要性质如下图:

class SinPositionEncoding(nn.Module):`    `def __init__(self, max_sequence_length, d_model, base=10000):`        `super().__init__()`        `self.max_sequence_length = max_sequence_length`        `self.d_model = d_model`        `self.base = base``   ``   `    `def forward(self):`        `pe = torch.zeros(self.max_sequence_length, self.d_model, dtype=torch.float)  # size(max_sequence_length, d_model)`        `exp_1 = torch.arange(self.d_model // 2, dtype=torch.float)  # 初始化一半维度,sin位置编码的维度被分为了两部分`        `exp_value = exp_1 / (self.d_model / 2)``   ``   `        `alpha = 1 / (self.base ** exp_value)  # size(dmodel/2)`        `out = torch.arange(self.max_sequence_length, dtype=torch.float)[:, None] @ alpha[None, :]  # size(max_sequence_length, d_model/2)`        `embedding_sin = torch.sin(out)`        `embedding_cos = torch.cos(out)``   ``   `        `pe[:, 0::2] = embedding_sin  # 奇数位置设置为sin`        `pe[:, 1::2] = embedding_cos  # 偶数位置设置为cos`        `return pe``   ``   ``SinPositionEncoding(d_model=4, max_sequence_length=10, base=10000).forward()``   

(2)可学习的位置编码

主要存在于 BERT、VIT 等变种系列模型,直接将位置作为可学习的参数,让模型自己学习。

class TrainablePositionEncoding(nn.Module):`    `def __init__(self, max_sequence_length, d_model):`        `super().__init__()`        `self.max_sequence_length = max_sequence_length`        `self.d_model = d_model``   ``   `    `def forward(self):`        `pe = nn.Embedding(self.max_sequence_length, self.d_model)`        `nn.init.constant(pe.weight, 0.)`        `return pe

(3)相对位置编码

相对位置编码的实现可以参考之前的文章

(4)旋转位置编码

旋转位置编码(Rotary Position Embedding,RoPE)是论文 Roformer: Enhanced Transformer With Rotray Position Embedding 提出的一种能够将相对位置信息依赖集成到 self-attention 中并提升 transformer 架构性能的位置编码方式。

而目前很火的 LLaMA、GLM 模型也是采用该位置编码方式。

和相对位置编码相比,RoPE 具有更好的外推性(在训练时和预测时的输入长度不一致,导致模型的泛化能力下降的问题),目前是大模型相对位置编码中应用最广的方式之一。

对于 self- attention 中的 KQV 通过如下方式得到:

其中 qm 表示第 m 个 token 对应的词向量 xm 集成位置信息 m 之后的 query 向量。

而 kn 和 vn 则表示第 n 个 token 对应的词向量 xn 集成位置信息 n 之后的 key 和 value 向量。

对于 transformer 的位置信息是三角函数,所以函数 f 为 x_m+p_i,其中 p_i 是根据公式 1 计算得到的;

对于 BERT 等可学习位置编码,它的f函数是 x_m+p_i,其中 p_i 是模型学习得到的;

对于图例如下:
在这里插入图片描述

# 旋转位置编码计算``def apply_rotary_emb(`    `xq: torch.Tensor,`    `xk: torch.Tensor,`    `freqs_cis: torch.Tensor,``) -> Tuple[torch.Tensor, torch.Tensor]:`    `# xq.shape = [batch_size, seq_len, dim]`    `# xq_.shape = [batch_size, seq_len, dim // 2, 2]`    `xq_ = xq.float().reshape(*xq.shape[:-1], -1, 2)`    `xk_ = xk.float().reshape(*xk.shape[:-1], -1, 2)`    `    # 转为复数域`    `xq_ = torch.view_as_complex(xq_)`    `xk_ = torch.view_as_complex(xk_)`    `    # 应用旋转操作,然后将结果转回实数域`    `# xq_out.shape = [batch_size, seq_len, dim]`    `xq_out = torch.view_as_real(xq_ * freqs_cis).flatten(2)`    `xk_out = torch.view_as_real(xk_ * freqs_cis).flatten(2)`    `return xq_out.type_as(xq), xk_out.type_as(xk)``   ``   ``class Attention(nn.Module):`    `def __init__(self, args: ModelArgs):`        `super().__init__()``   ``   `        `self.wq = Linear(...)`        `self.wk = Linear(...)`        `self.wv = Linear(...)`        `        self.freqs_cis = precompute_freqs_cis(dim, max_seq_len * 2)``   ``   `    `def forward(self, x: torch.Tensor):`        `bsz, seqlen, _ = x.shape`        `xq, xk, xv = self.wq(x), self.wk(x), self.wv(x)``   ``   `        `xq = xq.view(batch_size, seq_len, dim)`        `xk = xk.view(batch_size, seq_len, dim)`        `xv = xv.view(batch_size, seq_len, dim)``   ``   `        `# attention 操作之前,应用旋转位置编码`        `xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs_cis)`        `        # scores.shape = (bs, seqlen, seqlen)`        `scores = torch.matmul(xq, xk.transpose(1, 2)) / math.sqrt(dim)`        `scores = F.softmax(scores.float(), dim=-1)`        `output = torch.matmul(scores, xv)  # (batch_size, seq_len, dim)`  `# ......

上面介绍了 transformer 处理序列时的常用位置编码,包括包括绝对位置编码(包括静态位置编码和可学习位置编码)、相对位置编码、旋转位置编码。

随着大模型的兴起,需要模型有更好的外推性,传统的相对和绝对位置编码无法满足时,LLM 是如何处理的。接下来我们介绍 LLM 中常用的位置编码。

位置编码的作用:

  • 克服 transformer 的位置不变性,因为双向注意力是位置不敏感的,所以需要位置编码;

  • 注入位置相关的先验知识,大部分的位置编码都带有“位置越近,越重要”的先验知识。

传统位置编码的问题:

  • 可学习位置编码:不具备外推性

  • 正余弦位置编码:有一定的外推性,但是缺少相对位置关系,效果较差;

LLM 的位置编码:

  • **Rope:**旋转位置编码,将位置编码通过旋转矩阵的方式,添加到注意力机制中;

  • **ALIBI:**添加一个不可学习的偏置项,来代表位置编码,添加到注意力机制中;

  • **NTK:**神经正切核,他是一种 scaling 位置编码的算法,常用 NTK-Rope 和 NTK-Alibi;

  • **YaRN:**在 Rope 的基础上进行改进,使其有更好的外推性;

  • **Cope:**考虑上下文的编码,解决了以往位置编码与 token 无关,只与位置有关的问题;

03

新型编码介绍

(1)Rope

旋转位置编码不像原始的绝对位置编码(在输入中单独加入位置编码信息),而是在计算注意力时,考虑 token 之间的位置关系。

和原始的 transformer 的区别,是在 qkv 中增加位置信息,得到新的 qkv:

在做注意力计算时,将位置信息通过旋转矩阵的方式引入,

注意:截图来自于论文,矩阵中 m 实则为位置差 m-n。

RoPE 形式上和 Sinusoidal 位置编码有点相似,只不过 Sinusoidal 位置编码是加性的,而 RoPE 可以视为乘性的。这么做的其实很大程度上依赖于三角函数的特性。

**优点:**去掉了量级笨重且难训练的位置向量矩阵,显著化了相对位置在注意力中的重要性,让每个变量更关注相对位置的变化,增加了模型的外推性。

(2)ALiBi

alibi 的原理相对简单,也是在计算注意力时引入位置关系,但是他是直接通过添加一个不可学习的偏置项,来弱化远距离的注意力系数,强化近距离的注意力系数。

m 的取值与 attention head 有关,假设有 H 个头,那么 m 的取值是:

其中 h 为第 h 个头。

(3)NTK

**问题引入:**无论是 Rope 还是 Alibi 位置编码,都存在训练数据长度有限,但是推理时长度要求更高的场景(现在很多大模型都支持上百 k 的输入长度)。

那么如何提升模型处理长文本的能力那,直接想法有两种:

**线性内插:**压缩输入长度到模型原本训练的长度,训练数据最大长度 l,需要支持的推理最大长度 L,那么需要将 L 压缩到 l 的长度。

具体做法是:

**线性外推:**线性外推(直接外推)就是不做任何处理,直接扩充l到L的长度。

两者的缺点:

  • 线性内插:会将不同视野大小下统一缩减,导致相邻位置的差异变小,损失视野分辨率。尤其是原先就在训练范围内的相邻位置(高频),因此需要重新训练。

  • 线性外推:因为训练时没有处理过较长文本,所以效果比较差,不如线性内插。

神经正切核(NTK)方式(NTK-aware RoPE)

这里要引入位置编码进制转换,主要参考的是苏剑林:高频外推,低频内插的思想。

位置编码进制转换就是用 2/8/10/16 进制数来表示位置坐标,即同样表示 2048,直接表示是 2048,用 10 进制表示是 [2,0,4,8]。

这样做的好处是:既缩小了数字的跨度,又没有缩小相邻数字的差距(因为直接表示,0 和 2048 跨度太大,梯度优化器不容易优化,直接压缩相邻差距又会变小)。

NTK 的作用是基于 NTK 理论,证明了神经网络无法直接学习高频信号(低维信息),所以高频信号要采用外推的方式,低频信号内插。

NTK-Rope

NTK-Alibi

ntk-alibi 是将 alibi 的 m 缩放成:

动态 NTK(Dynamic NTK)

Dynamic NTK 主要提出了动态的缩放因子。对于自回归模型而言,其所处理的序列是不断变化的,每一步比前一步增加一个 token。

在这种情况下有两种插值的方法:

  • 在整个推理阶段,使用固定的缩放因子 a=L’/L, 其中 L’ 是预测阶段文本长度

  • 在每轮前向传播中,位置编码更新缩放因子 a = max(1, l’/L), 其中 l’ 是当前序列的长度

方案 1 的问题在于,当序列长度小于 L’ 时,模型性能可能会有一点小折扣;而当序列长度大于 L’ 时,模型性能则会突然下降,而使用方案 2 可以使模型性能下降的更少。

在推理阶段不断调整缩放因子的方式称为 Dynamic 缩放,即动态 NTK 插值。

(4)YaRN

NTK-by-parts

温度系数

YaRN 除了上面说的 NTK-by-parts,还引入了一个在计算 softmax 时的温度系数。

(5)CoPE

上下文位置编码(Contextual Positional Encoding,简称 CoPE)。

对于传统位置的位置编码(可学习或不可学习)和相对位置编码(Rope、ALIBI)是独立于上下文编码的,而且相对位置编码在处理长文本时,位置注意力是个递减的趋势。

因此 Cope 提出了根据上下文的位置编码:

Cope 主要的思想是引入一个“门控”机制来控制当前 token 是否参与注意力计算,门控值是根据公式:

04

总结

位置编码是 transformer 中非常重要的组成部分,随着 LLM 的发展,也要求位置编码有更好的泛化性,适配更多的不同长度的处理场景,随机产生了 NTK/YaRN 等编码,Cope 是考虑了上下文,把 token 信息也考虑到位置编码中。总之,位置编码还在不断改进,值得持续关注和研究。

如何学习AI大模型 ?

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。【保证100%免费】🆓

CSDN粉丝独家福利

这份完整版的 AI 大模型学习资料已经上传CSDN,朋友们如果需要可以扫描下方二维码&点击下方CSDN官方认证链接免费领取 【保证100%免费】

读者福利: 👉👉CSDN大礼包:《最新AI大模型学习资源包》免费分享 👈👈

(👆👆👆安全链接,放心点击)

对于0基础小白入门:

如果你是零基础小白,想快速入门大模型是可以考虑的。

一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。

👉1.大模型入门学习思维导图👈

要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。

对于从来没有接触过AI大模型的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。(全套教程文末领取哈)
在这里插入图片描述

👉2.AGI大模型配套视频👈

很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,每个章节都是当前板块的精华浓缩。

在这里插入图片描述
在这里插入图片描述

👉3.大模型实际应用报告合集👈

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。(全套教程文末领取哈)

在这里插入图片描述

👉4.大模型落地应用案例PPT👈

光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。(全套教程文末领取哈)

在这里插入图片描述

👉5.大模型经典学习电子书👈

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。(全套教程文末领取哈)
img

在这里插入图片描述

👉6.大模型面试题&答案👈

截至目前大模型已经超过200个,在大模型纵横的时代,不仅大模型技术越来越卷,就连大模型相关的岗位和面试也开始越来越卷了。为了让大家更容易上车大模型算法赛道,我总结了大模型常考的面试题。(全套教程文末领取哈)

在这里插入图片描述
👉学会后的收获:👈
基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;

能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;

基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;

能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习

CSDN粉丝独家福利

这份完整版的 AI 大模型学习资料已经上传CSDN,朋友们如果需要可以扫描下方二维码&点击下方CSDN官方认证链接免费领取 【保证100%免费】

读者福利: 👉👉CSDN大礼包:《最新AI大模型学习资源包》免费分享 👈👈

(👆👆👆安全链接,放心点击)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值