基于rope长度外推方法
盘点基于RoPE的长度外推方法演进,从最朴素的位置内插到NTK-RoPE,再到YaRN等方法。
前RoPE时代的长度扩展方法
直接微调适应
就是要多长就训练多长,比如任务需要2048长度就训练2048长度。这样需要较多的算力和数据适应长上下文窗口。
使用弱外推性质位置编码
使用如ALiBE等有弱外推性质的位置编码,在正常的长度训练模型,期待位置编码的弱外推性质进行长度外推。这种方法目前外推能力较弱,因此LLM使用较少。
位置内插(PI)
相对位置的OOD,直接表现就是预测阶段的相对位置超出了训练时的范围,由于没有被训练过,“越界”部分的行为无法预估。位置内插(Position
Interpolation,
PI)通过线性缩放输入位置索引来匹配原始上下文窗口,避免在训练期间未见过的更长上下文长度上进行外推。
方法是对位置索引进行线性缩放,将预测位置的长文本位置编码乘上因子\(\frac{L_{train}}{L_{test}}\),缩放到训练长度内。
训练阶段: \((1,2,3,\dots,n-1,n)\)
预测阶段: \((1,2,3,\dots,n,n+1,\dots,2n-1,2 ...
sinusoidal简介
简介
自注意力机制是没有位置信息的,即对于元素相同的向量序列,打乱顺序后之前每个元素的输出也依旧不变,这在自然语言里是不合理的。因此需要引入位置编码表征token在序列里的位置。
原始Transformer模型使用了Sinusoidal位置编码,不需要训练而是通过加入正余弦信息来为每个token加入顺序信息。标准的Sinusoidal形式如下:
\[
\begin{equation}\left\{\begin{aligned}&p_{k,2i}=\sin(k/10000^{2i/d})\\
&p_{k, 2i+1}=\cos (k/10000^{2i/d} )
\end{aligned}\right.
\end{equation}
\]
基本思路
假设模型为\(f(⋯,x_m,⋯,x_n,⋯)\),其中标记出来的\(x_m,x_n\)分别表示第m,n个输入,不失一般性,设f是标量函数。对于不带Attention
Mask的纯Attention模型,它是全对称的,即对于任意的\(m,n\),都有: \[
\begin{equation}
f(\cdots, x_m, \c ...
rope简介
简介
旋转位置编码(Rotary Position Embedding,RoPE)是论文Roformer:
Enhanced Transformer With Rotray Position Embedding
提出的一种能够将相对位置信息依赖集成到 self-attention 中并提升
transformer 架构性能的位置编码方式。而目前很火的 LLaMA、GLM
模型也是采用该位置编码方式。在RoPE中,出发点就是“通过绝对位置编码的方式实现相对位置编码”。
和相对位置编码相比,RoPE
具有更好的外推性,目前是大模型相对位置编码中应用最广的方式之一。
基本思路
假设通过下述运算来给\(q,k\)添加绝对位置信息: \(\tilde{q}_{m} = f(q,m),
\tilde{k}_{m}=f(k,n)\) 经过这个操作之后,\(\tilde{q}_{m},
\tilde{k}_{n}\)就带有位置\(m,
n\)的绝对位置信息。Attention的核心运算是内积,所以希望内积的结果带有相对位置信息,假设存在恒等关系:
\[
\lang f(q,m)f(k,n) \rang ...
朝花夕拾(一)——Transformer
好的,之前说要做这么一个朝花夕拾的系列,拖了很久也没开始动手,今天下定决心要开一篇出来。今天的回顾的这篇论文是Attention Is All You
Need,提出了Transformer这个架构,并利用Transformer完成机器翻译的任务。Transformer这个架构的论文作为本系列的第一篇应该是相当合适的,因为后续的很多工作将在Transformer这个模型架构下进行。
动机
在Transformer之前主流的序列到序列模型(seq2seq
model)使用的是循环神经网络或者卷积神经网络,包含一个编码器和一个解码器。表现最好的模型还通过注意力机制连接编码器和解码器。循环神经网络需要为每一个位置生成一个隐藏层状态\(h_t\),计算这个隐藏状态需要前一个位置生成的隐藏层状态\(h_{t-1}\)和该位置的输入\(t\)。这种固有的串行计算方式妨碍了训练样本的并行化,在序列长度较长时,序列内部的并行化计算变得非常重要。因为显存约束,限制了通过样本之间的批处理缓解序列内部不能并行计算的问题。意思就是序列较短的时候,RNN还可以用大批量,一次计算多个样本的第\(t\)个位置的隐藏 ...
刷题分享:我写牛客TOP101道编程题
写了也挺久的了吧,今天终于把牛客TOP101道题给写完了,算是有了一些基础编程能力了吧。因为大大小小的事耽误着,其实还写了蛮多天的,写完确实能感觉到有所收获。按时间顺序,也其实就是题目的顺序把剩下的解法都记录在这里。
9月20日
BM 55 没有重复项数字的全排列
url:牛客
BM55
考察知识点:回溯法
做了这题之后我才发现全排列就是原来数组进行两两交换之后的所有结果,当然也可以自己和自己交换,这样就是这步操作不改变结果。那第\(i\)次操作时总共有和后面\(n-i+1\)个元素(包括这个元素自己)进行交换的机会。
这个按字典序的意思就是按a-z,0-9的顺序排序,也就是在做之前排序一下元素即可。
1234567891011121314151617181920212223242526272829303132## 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可## # @param num int整型一维数组 # @return int整型二维数组#class Solution: def permute_item(self, base_num_list ...
利用深度学习将不同说话人从音频中分离
今天我分享一种通过深度学习将不同说话人从音频文件中分离的方法,这个方法的契机是我想从《哆啦A梦》的动画片里面分离主角们的说的台词。我个人是音频处理的门外汉,对很多音频处理的事情知之甚少,很多都是通过直接调用别人训练好的模型或者网上找教程现学现用的,所以如果有错误或者更好的方法,恳请读者批评指正。那接下来进入正题。
方法概述
从音频里面分离不同的说话人是音频领域的研究热点,这个任务的英文名称是说话人分类(Speaker
Diarization),已经有很多研究者提出了各种解决方案。但如果按切分依据主要可以分为两种:第一种是单纯依赖音频信息的单模态说话人识别;第二种是结合语音识别(Auto
Speaker Recognition, ASR)技术的多模态说话人识别。
在有较多可用数据的情况下,单模态说话人识别就能达到比较好的效果了,比如开源库pyannote就提供了在英文数据集上预训练过的模型,在很多英文场景下使用作者提供的speaker-diarazation管道应该就能达到不错的说话人分类效果。对于pyannote是通过这样的流程完成整个说话人分类的:
pyannote进行说话人分类 ...
表达式计算专题
之前做了牛客的BM
49
表达式的计算之后感觉表达式计算确实很神奇。之前也有想自己实现一些查询语法的需求,但因为我没修过《编译原理》的课,于是一直被搁置着。虽然对这种复杂的查询表达式解析可能搞不太定,但是我觉得对四则运算和括号组成的这样的数学表达式应该还是要搞得定的,所以我开了这样一个专题来说明表达式计算背后的方法,也用几道题来实操一下这两个方法。
原理和方法
我们日常使用的表达式一般(夸张一点说,全部)是中缀表达式,这种表达式将操作数置于运算符两边,并通过括号和运算符的计算规则来表达优先级。比如"3+6*(2+5)"就是一个中缀表达式,因为(2+5)是被括号括起来的,因此要先计算括号的值,得到:"3+6*7"。然后又因为乘法优先级更高,所以要先算"6*7",得到:"3+42",最后算出结果是45。
这样的中缀表达式对人来说很自然,通过括号和运算符优先级,我们可以很容易地调整表达式去进行我们想进行的计算。但对于机器来说,这样复杂的优先级规则对编写代码很不友好。还好,前人想出了一种精妙的方法将中缀表达式转换为后缀表达式,后者不需要考虑运算符和括号(准确地说是后缀表达式里没括号)的优先级了 ...
20230908刷题近况
今天也更新两道题,过的速度真是有够慢的。经典的算法还挺多的,每个回顾起来都花不少时间。
BM 48 数据流的中位数
url:牛客
BM48
考察知识点:插入排序、堆
方法一:插入排序
插入排序的方法比较好想到,因为中位数就是排序好的数组中间位置的数嘛。
12345678910111213141516171819202122232425# -*- coding:utf-8 -*-class Solution: num_list = [] def Insert(self, num): # write code here # 用插入排序做一次 num_length = len(self.num_list) for i in range(num_length): if self.num_list[i] >= num: self.num_list.insert(i, num) break # 如果之前都没插进去,那就是最后一个元 ...
快速排序的原理及应用
好久没更新了,之前在忙SMP
2023的那个比赛和实验室的一些事情。好吧,其实也没那么忙,只是感觉很疲惫然后很想休息,一刷题就犯困了。今天要回顾的主题是快速排序,它很有诱惑力的地方是它既是一个平均复杂度在\(\Theta(n \log
n)\)的算法,而且在实现时又不需要额外申请数组,可以就地排序。在实际应用中,它比大多数排序算法都要快,是名副其实的“快速”算法。在这篇文章里,我们会回顾快速排序的原理,也会进行一些防御性操作阻止快速排序陷入最坏条件中,最后也会把之前的两个算法题用快速排序解决一下。
快速排序的基本原理
快速排序是一种分治排序的算法,它将一个数组分成两个子数组,并将两个子数组独立地进行排序。快速排序与归并排序既有区别又有联系,它们的相同点在于都是应用分治法对数组进行排序;不同点在于归并排序是先分后治最后合并,而快速排序则是先治后分,当子数组有序时整个数组就有序了,因此快速排序不需要额外的合并操作了。
快速排序的核心操作在于“切分”,也即我们将实现的partition函数,这个函数将目标元素放在一个合适的位置j,在这个位置左边的数均不大于a[j],在这个位置右边的数均不小于 ...
Python里的isnumeric和isdigit方法异同
好久没写东西了,除了确实比较摆的主观原因之外还有要搞那个SMP
2023的复赛的客观原因。那个项目写着感觉也还学到或者说复习了不少东西,包括正则表达式、操作数据库还有用HuggingFace库对生成式模型的生成参数做调整等,这些以后有时间单独写一篇。
今天这篇只谈一个很小的点,就是假设随便给一个字符串,如何判断里面的文本是不是数字呢?
这个方案其实还挺多,最简单的就是直接float强转一下然后错误处理,出错的肯定就不是数字了。但实际上,Python已经在字符串里给出了很方便的函数来判断是不是数字,但是也比较容易混淆,即isnumeric和isdigit方法。
两者的异同
首先先说一下两者的共同点,就是它们对于阿拉伯整数都有很好地判断能力,比如:
123a = "12345"a.isnumeric(), a.isdigit()# True, True
但是isnumeric的范围是更广的,它甚至可以识别中文的数字表达:
123a = "三百二十一"a.isnumeric(), a.isdigit()# True, False
这非常的夸张,如果我们 ...