前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >层次分解位置编码,让BERT可以处理超长文本

层次分解位置编码,让BERT可以处理超长文本

作者头像
mathor
发布2021-07-09 17:07:06
1.7K0
发布2021-07-09 17:07:06
举报
文章被收录于专栏:mathormathor

我们知道,BERT无法处理超长文本的根本原因是BERT使用了从随机初始化训练出来的绝对位置编码,一般的最大位置设为了512,因此顶多只能处理512个token,多出来的部分就没有位置编码可用了。当然,还有一个重要的原因是Attention的O(n^2)复杂度,导致长序列时显存用量大大增加,一般显卡也finetune不了

本文主要解决第一个问题,即假设有足够多的显存前提下,如何简单修改当前最大长度为512的BERT模型,使得它可以直接处理更长的文本。主要思路是层次分解已经训练好的绝对位置编码,使得它可以延拓到更长的位置

位置编码

BERT使用的是训练出来的绝对位置编码,这种编码方式简单直接,效果也很不错,但是由于每个位置向量都是模型自己训练出来的,我们无法推断其余位置的编码向量,因此有了长度限制。

解决这个问题的一个主流思路是换成相对位置编码,这是个可行的办法,华为的NEZHA模型便是一个换成了相对位置编码的BERT模型。相对位置编码一般会对位置差做个截断,使得要处理的相对位置都在一个有限的范围内,因此相对位置编码可以不受限于序列长度。但相对位置编码也不是完美的解决方案,首先像NEZHA那样的相对位置编码会增加计算量(如果是T5那种倒是不会),其次是线性Attention则没法用相对位置编码,也就是不够通用

读者可能会想到,《Attention is All You Need》不是提出了一种用\sin,\cos表示的Sinusoidal绝对位置编码吗?直接用那种不就不限制长度了?理论上是这样,但问题是目前没有用Sinusoidal位置编码的模型开放,我们自己从零训练一个不太现实

层次分解

所以,在有限资源的情况下,最理想的方案还是想办法延拓训练好的BERT的位置编码,而不用重新训练模型。下面给出苏剑林大佬构思的一种层次分解方案

具体来说,假设已经训练好的绝对位置编码向量为\boldsymbol{p}_1,\boldsymbol{p}_2,...,\boldsymbol{p}_n,我们希望在此基础上构建一套新的编码向量\boldsymbol{q}_1,\boldsymbol{q}_2,...,\boldsymbol{q}_m,其中m>n

\boldsymbol{q}_{(i-1)\times n+j}=\alpha \boldsymbol{u}_i+(1-\alpha)\boldsymbol{u}_j \tag{1}

其中,\alpha \in (0,1)\alpha \neq 0.5是一个超参数,\boldsymbol{u}_1,\boldsymbol{u}_2,⋯,\boldsymbol{u}_n是该套位置编码的"基底"。这样的表示意义很清晰,就是将位置(i−1)\times n+j层次地表示为(i,j),然后i,j对应的位置编码分别为\alpha \boldsymbol{u}_i(1−\alpha)\boldsymbol{u}_j,而最终(i−1)\times n+j的编码向量则是两者的叠加。要求\alpha \neq0.5是为了区分(i,j)(j,i)两种不同的情况

我们希望在不超过n时,位置向量保持跟原来的一样,这样就能与已经训练好的模型兼容。换句话说,我们希望\boldsymbol{q}_1=\boldsymbol{p}_1,\boldsymbol{q}_2=\boldsymbol{p}_2,⋯,\boldsymbol{q}_n=\boldsymbol{p}_n,这样就能反推出各个\boldsymbol{u}_i

$$ \begin{aligned} \boldsymbol{q}_1=\boldsymbol{p}_1 = \alpha \boldsymbol{u}_1+ (1-\alpha)\boldsymbol{u}_1\Rightarrow &\boldsymbol{u}_1=\frac{\boldsymbol{p}_1-\alpha \boldsymbol{u}_1}{1-\alpha}\\ \boldsymbol{q}_2=\boldsymbol{p}_2 = \alpha \boldsymbol{u}_1+ (1-\alpha)\boldsymbol{u}_2 \Rightarrow &\boldsymbol{u}_2=\frac{\boldsymbol{p}_2-\alpha\boldsymbol{u}_1}{1-\alpha}\\ &\vdots \\ &\boldsymbol{u}_i = \frac{\boldsymbol{p}_i - \alpha \boldsymbol{u}_1}{1-\alpha} \end{aligned}\tag{2} $$

不妨令\boldsymbol{u}_1 = \boldsymbol{p}_1,则

\boldsymbol{u}_i = \frac{\boldsymbol{p}_i-\alpha \boldsymbol{p}_1}{1-\alpha}\tag{3}

这样一来,我们的参数还是\boldsymbol{p}_1,\boldsymbol{p}_2,⋯,\boldsymbol{p}_n,但我们可以表示出n^2个位置的编码,并且前n个位置编码跟原来模型是相容的

自我分析

事实上,读懂了之后,读者也许会觉得这个分解其实没什么技术含量,就是一个纯粹的拍脑袋的结果而已?其实确实是这样

至于为什么会觉得这样做有效?一是由于层次分解的可解释性很强,因此可以预估我们的结果具有一定外推能力,至少对于大于n的位置是一个不错的初始化;二则是下一节的实验验证了,毕竟实验是证明trick有效的唯一标准。本质上来说,我们做的事情很简单,就是构建一种位置编码的延拓方案,它跟原来的前n个编码相容,然后还能外推到更多的位置,剩下的就交给模型来适应了。这类做法肯定有无穷无尽的,笔者只是选择了其中自认为解释性比较强的一种,提供一种可能性,并不是最优的方案,也不是保证有效的方案

此外,讨论一下\alpha的选取问题,苏剑林大佬的选择是\alpha=0.4。理论上来说,\alpha\in(0,1)\alpha \neq 0.5都成立,但是从实际情况出发,还是建议选择0<\alpha<0.5n=512,那么这就意味着i=1,2,3,4j=1,2,⋯,512,如果\alpha>0.5\alpha \boldsymbol{u}_i就会占主导,因次位置编码之间差异变小(因为i的候选值只有4个),模型不容易把各个位置区分开来,会导致收敛变慢;如果\alpha<0.5(1−\alpha)\boldsymbol{u}_j,位置编码的区分度更好(j的候选值有512个),模型收敛更快一些

实践效果

苏剑林大佬首先测了MLM任务,直接将最大长度设为1536,然后加载训练好的RoBERTa权重,发现MLM的准确率大概是38%左右(如果截断到512,那么大概是55%左右),经过finetune其准确率可以很快(3000步左右)恢复到55%以上。这个结果表明这样延拓出来的位置编码在MLM任务上是行之有效的。如果有空余算力的话,在做其他任务之前先在MLM下继续预训练一会应该是比较好的。同时,我们对不同的\alpha也做了实验,表明\alpha=0.4确实是一个不错的默认值,如下图所示

不同alpha下MLM的训练准确率

然后测了两个长文本分类问题,分别将长度设为512和1024,其他参数不变进行finetune(直接finetune,没有先进行MLM继续预训练),其中一个数据集的结果没有什么明显变化;另一个数据集在验证集上1024的比512的要高0.5%左右。这再次表明本文所提的层次分解位置编码是能起作用的。所以,大家如果有足够显存的显卡,那就尽管一试吧,尤其是长文本的序列标注任务,感觉应该挺适合的

Reference
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 位置编码
  • 层次分解
  • 自我分析
  • 实践效果
  • Reference
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档