首页IT科技自注意力机制qkv(【学习】自注意力机制的改进方法、non-autoregressive sequence generation、point network)

自注意力机制qkv(【学习】自注意力机制的改进方法、non-autoregressive sequence generation、point network)

时间2025-06-20 01:01:07分类IT科技浏览4616
导读:一、如何让自注意机制更有效? 在自注意机制里面,我们输入一个序列,输出是另一个序列。输入序列之后我们可以得到一个query和一个key的向量序列,长度为分别都为N(跟输入序列长度相同)。那么在attention matrix里面,我们要做的就是把query和key进行点积,那这个运算的...

一              、如何让自注意机制更有效?

在自注意机制里面              ,我们输入一个序列                     ,输出是另一个序列              。输入序列之后我们可以得到一个query和一个key的向量序列       ,长度为分别都为N(跟输入序列长度相同)                     。那么在attention matrix里面              ,我们要做的就是把query和key进行点积                     ,那这个运算的就是NN级别的       。所以我们要想办法解决这个机制的运算量大的问题       。虽然self attention运算量可能会很惊人       ,但是我们的self attention毕竟是我们的神经网络中的一个小小的一部分(可能有很多个self attention还有别的结构组成)                     。

虽然self attention会对网络的计算量影响很大       ,但是也有可能被其他计算量更大的结构主导网络                     ,那么我们优化self attention计算就没有什么显著的优化              。那什么时候self attention主导网络的计算量呢?当self attention的N很大的时候              ,这样我们加快self attention 才会对神经网络有帮助       。我们经常把self attention应用在图像识别的时候                     。我们的一个图片如果N是256256       ,那我们的运算就会非常大!

1                     、local attention/truncated attention

在self attention里面                     ,我们最大的计算量就是要计算N*N的矩阵              。那我们可以怎么优化呢?也许我们不需要计算这个矩阵所有位置的数值              ,我们可以用人类知识填充!有些问题不需要看整个attention,可以只看前后的邻居。在self attention如果我们只看邻居                     ,那我们就能把很远的地方的值设为0.下图我们把灰色地方设为0                     ,因为那些地方没有必要参与运算                     。而蓝色的就需要计算啦                     。整个方法就是local attention或者truncated attention。但是这个local attention明显有问题,我们在做attention的时候只能看到小范围的数值              ,那这个就跟CNN很像啦!local attention是可以加快我们的attention的方法                     ,但是不一定能得到很好的结果              。下面这个local attention是寻找前后的邻居                     。

2       、stride attention

那么这个stride attention就是       ,取比较远的邻居!下图我们是空2格看的              ,或者是别的方式       。

3       、global attention

以上都是以某个位置为中心看左右的事情                     ,如果我们关心整个sequence       ,那么我们可以用global attention              。我们可以加入一个特殊token到原始的sequence里面                     。在这里       ,global attention会做两件事情:

(1)每个特殊的token都加入每一个token                     ,收集全局信息       。

(2)每个特殊的token都被其他所有的token加入              ,以用来获取全局信息       。

怎么实现呢?第一种       ,我们可以把原来的sequence里面的某些向量选做special token                     。另外一种就是外加额外的token              。如果要把外加token的矩阵attention matrix画出来                     ,每一个cow行代表query              ,每一个column列代表key       。下图中橘色两个横向的地方是有值的,都要计算attention                     ,他们是特殊的token                     ,要加入到所有的其他的key                     。那每一列的前两列也是有值的,他们也会加入到第一个和第二个位置              。从下图可以看出来              ,每一个不是特殊token的query都要加入特殊token。而对于灰色的地方                     ,他们没有值       ,互相之间就没有联系了!

以上我们讲了三张不同的选择              ,那哪一个好呢?我们都选择!对于不同的heads我们选择不同的attention                     。

big bird加入了random attention                     。

4                     、data driving

刚才我们说的方法是人为决定的                     ,哪里有值       ,哪里为0.那我们能不借助人       ,而使用数据驱动的方式吗?在一个self-attention里面的矩阵里面                     ,某些位置有很大的值              ,有些位置又有很小的值       ,那我们就把很小的值变为0                     ,这个可能对我们的结果没有什么影响。那我们是否能估计矩阵哪里有大值              ,哪里有小值吗?

clustering

在reformer和routing transformer两篇文章里面,都用了一个方法——clustering              。

步骤一:我们先把query和key取出来                     ,然后根据query和key的相近程度做clustering                     。对于相近的数据就放在一起                     ,对于比较远的数据就属于不同的cluster       。下面我们有四个cluster,用不同的颜色来标出              。这里可能有个问题              ,我们在做cluster的时候可能会出现运算量大的问题!其实事实上我们的cluster还是有很多快速的方法的                     。

对于query和key形成的attention matrix来说                     ,只有当query和key的cluster是一样的时候       ,我们才计算他们的attention weight       。对于不属于同一个cluster的两个query和key              ,就把他们设为0       。这种方法可以加速我们的运算                     ,这是一种基于数据来决定的!

learnable patterns of sinkhorn sorting network

那有没有方法可以让我们再次改变上面的想法       ,让我们的矩阵是学习出来的呢?下面的方法就是由sinkhorn sorting network学习出来的                     。在sinkhorn sorting network里面       ,直接学习另外一个network来决定怎么输出这个矩阵              。

我们把输入的序列                     ,经过一个NN之后产生另外一排向量序列              ,生成的矩阵就是NN的       。我们要把这个生成的不是二进制的矩阵变成我们的attention matrix                     。这个过程是可以微分的       ,所以是可以在NN里面训练出来的              。

其实我们可以直接输出这个attention matrix                     ,不用经过非二进制矩阵转换为二进制!

但是其实还有个问题              ,就是用另外一个网络生成矩阵真的比我们直接算attention matrix快吗?仔细想想,好像两个没有什么区别吧。事实上                     ,在sinkhorn sorting network里面                     ,有好几个输入的向量会共用一个经过NN产生的向量                     。也就是时候有向量复用啦!

又有另一个问题,我们真的需要一个NN的full attention matrix吗?在一片linformer的文章里面提到              ,在一个attention matrix里会有很多冗余的列                     ,很多列都是重复的       ,这个矩阵是low rank的              ,很多列是依赖其他列的                     。那我们能不能去掉重复                     ,产生小的attention matrix       ,加快attention的速度呢?

怎么做呢?我们有N个key       ,选择K个代表的key。然后与N各query产生一个矩阵                     ,那我们怎么用这个长方形的矩阵产生self -attention layer 的输出呢?我们有N个value              ,也选择K个代表value              。然后我们把这K个value和attention matrix做weight sum加权和       ,就得到输出                     。我们我们要选择代表key                     ,而不选择代表value呢? 但是我们不能改变query呀!因为我们的输出长度可能就会变短了!如果不是输入一个序列输出一个label那就不要这样做了!

减少key的数量

怎么选择代表性的key呢?在一个文章compressed attention里面提到              ,我们输入一个很长的key序列,我们用CNN来扫过                     ,key序列的长度就变短了                     ,那这个就是代表性的key       。在另一个文章linformer里面提到,输入的key序列可以看成是dN的矩阵              ,我们可以把这个key序列乘上一个NK的矩阵                     ,然后就得到了d*K的矩阵              。那这个得到的新矩阵就是代表性key序列       ,这个方法其实是N个key序列的线性组合                     。

注意机制attention mechanism

回顾              ,其实attention的整个过程                     ,其实就是矩阵相乘       ,那我们是否能进行优化呢?

我的输入是一个矩阵I       ,I乘上一个linear transformer Wq得到另外一个矩阵Q(dN)       。然后再做以下的运算:

Q和K的维度d要一样                     ,因为要做点积       。但是V可以不为dN                     。有没有办法加速这个运算呢?

假设我们没有做softmax这个步骤              ,那A=A’       ,O=VKTQ              。

我们可以这样进行优化:是否V和K跟K和Q相乘的运算是差不多的呢?不是的       。

事实上                     ,这两种情况的相乘结果是一样的              ,但是运算量是不一样的!

KT和Q相乘的乘法次数需要NdN次,得到A(attention matrix)                     。V*A的乘法次数是d‘’NN                     ,那总的计算次数就是(d+d’)N^2.

但是我们交换了乘法顺序之后呢?乘法次数只要2dd’N!那上面的计算就会比下面的计算大很多呀              。

如果加上softmax呢?这个原来的计算过程

实际上这个过程是可以简化的!我们有φ的方法:把指数expornatial的矩阵运算变成φ的点积。

然后我们发现                     ,在分母的地方没有出现i,那就能把i提到上面!

然后看分母              ,发现q跟j也没有关系                     ,也可以提出来       ,只求k求和!

看分子              ,我们展开之后                     ,把q相同的项相乘

可以看出来       ,括号里的式子可以看出是一个向量v的权重和                     。那有几个v向量呢?由有几个q决定!

我们再来看看       ,事实上b跟只涉及q这个矩阵                     ,而其他矩阵相乘只需要计算一次!

也就是说我们的每个输入只用分别计算q              ,而其他的不用重复计算啦!但是我们要选择适当的φ才能求得跟原来的网络相似的结果!

那怎么选择φ呢?以下有很多方法

synthesizer

我们真的必须要q和k去计算attention吗?不一定       ,可以用synthesizer                     。那我们的这个矩阵怎么出来呢                     ,可以直接吧attention matrix作为网络参数的一部分              ,而不是求出来的,这样的performance也没有很大的区别。

横轴是速度                     ,纵轴是分数                     ,圈圈大小是attention数目              。

二              、non-autoregressive sequence generation非自回归序列生成

conditional sequence generation条件序列生成

(1)输入语音序列(condition),输出中文序列(sequence modeling)                     。

(2)输入一张图              ,输出这张图的内容                     ,这是一个image caption generation       。

(3)输入一段英文       ,输出中文意思              ,这是一个machine translation              。

我们在翻译的时候一般都用autoregressive model                     。如果是RNN                     ,我们就是逐步输入和逐步输出的       。

在transformer里面       ,虽然是吧输入一次性输入到encoder里面       ,但是decoder还是要逐步输出(依赖前一个输出)       。

这样就会很浪费时间!

那我们能不能让他一次性输入和输出呢?non-autoregressive model                     。我们可以让encoder随意预测一个长度                     ,encoder输入就是放在position embedding              。

问题

在文字转图片的任务里面              ,模型学习到的是一个双头火车!这就很奇妙啦       。

实际上       ,我们的输出相互之间没有什么依赖                     ,我们希望输出第二个能看见第一个位置的值                     。另外              ,我们希望输出层中的每个神经元对应一个像素,而不是会出现两个一模一样的东西!

如果我们用GAN的方法就能实现这种依赖                     ,GAN(autoregressive model之一)是能让generator输出结构的方法              。在我们描述的时候                     ,可能不知道需要显示左边还是右边的火车(no latent variable),这个模型内部可能自己预测很大可能是左边的火车              ,但是因为没有随机的机制                     ,所以到了最后的一个隐藏层       ,我们得到的还是两个火车的叠加!为什么autoregressive model没有这个问题呢?因为autoregressive model会在每个时间点做一个sample的动作              ,他会挑选最大几率的一个                     ,抛弃其他的。不管GAN还是conditional GAN       ,我们在输入的时候都要输入一个噪声(normal distribution z)到G       ,让模型事先决定生成的方向                     。所以这两个方法就会避开上面的问题                     。

我们在翻译的时候                     ,想要将英文输出为中文              ,比如说       ,输入hello                     ,一般我们的输出会有很多种答复。那怎么确定输出哪一个呢?在autoregressive model里面会学习到              ,输入hello的时候,哈和你       、罗和好的几率差不多大                     ,那这样会不会组合错误呢?会!这种问题叫做multi-modality problem              。这是本文主要解决的问题                     。

假如我们想要从一个模型里面生成一张图片                     ,用最简单的方法,deconvolution layer +L2 loss              ,可能会生成模糊图片(生成的图片是很多图片的平均)       。对应在文字上的就是                     ,我们翻译的文字是各种可能的结果的叠加              。如果我们用autoregressive model就能生成很好的图片       ,对应到文字上就是我们需要一个个输出文字                     。除此之外GAN也能生成很好的图片       。在做GAN的时候              ,我们的结构可以用deconvolution layer +L2 loss                     ,而不用autoregressive model       ,结果也很好       。但是目前GAN没有用于文字                     。

对于文字翻译来说       ,我们希望用第一种简单的方法来实现              。在输入的地方                     ,我们对于每个encoder的输入向量都预测一个数字              ,对应到decoder的输出的对应位置       。在我们预测完成之后       ,就对输入进行复制到decoder的输入                     ,那么最后我们预测的数字总和就是我们的输出的长度                     。这种其实代表了我们的decoder对翻译的事先规划              。

1                     、fertility

我们要怎么训练呢?可以用一个外部的工具              ,对于输入我们预测输出有几个字。也可以直接训练一个autoregressive model观察attention weight是怎么分布的                     。从外部工具得到我们想要的fine-tune,目标不一样                     。我们在模型收敛之后会做fine-tune                     ,也就是用reinforce的loss加在fertility classifier上面。

2              、sequence-level knowledge distillation

knowledge distillation

如果我们想要训练一个小模型                     ,想要小模型的表现跟大模型一样好              。那就把小模型当做学生,大模型 作为老师                     。小模型在训练的时候              ,把输入给大模型                     ,让大模型预测出他预测的概率分布       。然后让小模型直接学这个概率分布       ,那小模型就会学的比较好              。这个是knowledge distillation在做的事情                     。

在sequence-level knowledge distillation里面              ,教师模型是autoregressive model                     ,学生模型是non-autoregressive model       。这里跟knowledge distillation不一样       ,学生模型不学习教师模型输出的概率分布       。而是让教师模型把corpus里面的每一句话用greedy decode的方式预测       ,然后让学生模型把输出的这个结果作为正确答案训练                     。为什么用non-autoregressive model解决刚才的multi-modality问题呢?multi-modality problem相互之间没有依赖                     ,错误记录很大              。如果数据集事先给了autoregressive model做decode的话              ,那概率分布就会不一样       ,就避免了模型的错误!

(3)noisy parallel decoding(NPD)

我们在训练好了non-autoregressive model之后                     ,我们的decoder是可以sample不同的数字的(1221)              ,那么就会输出不同的句子!然后这些句子交给教师打分(autoregressive model),选择最好的那个句子作为答案       。这里我们涉及了autoregressive model                     ,有没有可能运算就变慢了?

其实如果让autoregressive model去计算已经出现的句子的概率                     ,只需要一个步骤就可以了!我们会用transformer decoder的方式,teacher focing              ,casual mask                     ,让左边的输入不能涉及右边的输入                     。这个不怎么需要耗费时间              。

在实验中       ,第一列En->De的意思是performance              ,可以看到是递增的;最后一列是速度                     ,基本上是递减的。

第一种方法是刚才说的       ,第二种iteration refinement是在生成了一句话的一部分之后作为输入到decoder里面       ,第三中insertion-based是:输入一个很差的句子到decoder里面                     ,然后在中间进行补足              ,这种方法没有限制句子应该输出多少个字       ,所以可以由机器自己决定                     。第三种方法                     ,比如说我们输入一个D              ,预测B和F,然后有三个字母之后又能预测ACEG                     。这种方法时间复杂度logN                     ,但是这种方法如果在输出一个错字的时候就不能修改了。而第二种方法能对我的输出进行修正              。所以就出现第四种方法                     ,可以让第三种方法出现错误的时候删除错字                     。

方法

1、iterative refinement

我们输入一个X,输出Y0              ,然后可以不断对Y进行修正                     ,最后得到最好的结果Y       。decoder可以加入噪声(用yt+1替换yt       ,或者把yt替换成一个随机的token              ,或者交换yt和yt+1)                     ,模型如下:

Mask-Predict

decoder输入的某些vector用mask token替代

怎么做呢?我们先预测6       ,然后生成6个mask到decoder里面       ,得出第一版本的翻译结果(bad)              。

我们把第一个输出放到输入里面                     ,判断刚才生成的字里面哪些概率比较低              ,把概率低的几个字换成mask token       ,然后再生成一次结果(better)                     。

这是每次要mask几个字的方程:刚开始mask的比较多

样例:黄色的字为几率低的                     ,t=2的时候就能得到正确答案了!

这个方法比前面的好很多!

2                     、iterative refinement

我们有生成到一半的不成型的句子              ,输入有几个输出就几个       。我们把输出的相邻两个相邻相接,两个字中间就有一个recreation       。

我们用recreation来预测要插入的字                     ,如果没有要插入的字                     ,就是end                     。如果预测了字,那就插入输入的句子里              。

训练

加入我们的数据集里面有十个字              ,然后做shuffled打乱顺序       。选择任意的数字                     ,删除那些任意位置的字       ,然后把原来的句子还原                     。

如果删掉两个就算两个loss

uniform policy的策略是进行loss的取平均              ,但是我们有个更好的方法——平衡二叉树策略              。这个方法类似于下面这个字母的例子                     ,得到中间的更容易算出两边的。所以我们会让中间的mask的权重大一点                     。

KERMIT

混合encoder和decoder

这种模型可以中英混合翻译

同时训练五个任务有什么好处呢?从下面看好像刚开始没有变好       ,还变糟糕了                     。但是训练了多个任务之后       ,performance突然变好。

KERMIT还可以做下面的zero-shot clonzeQA

3                     、insertion +delete=>levenshtein transformer

levenshtein distance algorithm

这是一个用法                     ,不过更好的处理是先删除后加入              。

imitation learning

我们有两种句子:需要被删除字的句子和需要加入字的句子                     。看见这个错误的句子              ,算法产生一个00100000       ,交给delete classifier去学习       。看见一个需要加入的句子                     ,算法就产生0200              ,交给insert classifier学习              。还有在包含占位符place holder(PLH)的句子里面,                     ,我们也能算出需要加入什么字                     ,然后交给token classifier学习                     。这样就能训练出levenshtein transformer       。

有效!

4、CTC

输出可以去掉空格,去掉重复              ,得到一个句子       。CTC经常用于语音识别                     。我们很少遇到上面出现很多结果的问题                     ,因为一段语音是有正确答案的!缺点:LAS更优;不能做refined       ,结果文字不能做decoder的输入              ,也就是输出不能修正              。

改良:inputer(CTC+mask-predict)

在输入的地方同时加入token sequence                     ,在t=0的时候       ,token sequence全是mask sequence       。

我们限制在每个时间点都把token换成字       ,block size=3                     ,那三步之内一定可以decoder一个完整的句子!

明显改善错误率                     。

这个imputer也可以放在文字翻译里面:把每个feature分裂成多个feature              ,类似于语音信号              。

CTC居然能胜过之前的所有的模型!

这个方法很强!

下面是三种语言互相翻译:

AT的方法好像不是很能翻译出       ,在一句话更多是同种语言为多。NAT会分辨出一句话三种语言的区别                     。

三              、pointer network

问题的原始描述是有一堆的点                     ,要找出最外围的点              ,使得这些点连起来,能够包围所有的点                     。

我们用NN来解决:输入一大堆数据                     ,经过NN之后                     ,得到一组数据,这些数据就是这些外围点的下标。

好像可以用seq2seq解决!如果就用这种直接训练              ,好像跑不起来              。因为我们在输出的时候选择限制了                     ,如下图       ,限制输出{1,2,3,4,end}              ,那当我扩大了数据了?就选不了别的数字啦!

我们可以做下面的调整:加入x0和y0代表end                     。采用之前的attention-based model                     ,这有个key z0       ,与每个输入的h产生attention weight

我们把z和h计算得到的结果作为distribution       ,然后做argmax                     ,输出最大的值的上标!输入有什么              ,decoder输出就可以选择什么       。

一直输出       ,知道end是作为最大的输出!

这种方法可以用来做总结summarization

声明:本站所有文章                     ,如无特殊说明或标注              ,均为本站原创发布              。任何个人或组织,在未征得本站同意时                     ,禁止复制                     、盗用       、采集              、发布本站内容到任何网站                     、书籍等各类媒体平台                     。如若本站内容侵犯了原著者的合法权益                     ,可联系我们进行处理       。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
服务器正在启动就不动了(如何解决Win10系统开机服务器正在运行中?) 找不到vcruntime140.dll 无法执行删了怎么办?(vc_runtimeMinimum_x64.msi 找不到的解决方法)