在这里插入图片描述

动机

对于transformer中的位置编码,我对他一直有很多不解,但是也没有一直深挖下去,今天偶然看见一篇很好的文章,感触颇多,故在此记录一下,加深印象,同时分享 Transformer学习笔记一:Positional Encoding(位置编码)

思考

为什么需要位置编码

因为人类在处理序列数据的时候,能轻松地获得潜在信息,诸如:

  1. 数据在序列中的绝对位置
  2. 数据在序列中的相对位置 即哪个数据在前面,哪个数据在后面
  3. 数据之间的距离
  4. 整个序列的长度

但是transformer在计算自注意力的时候,并不能获得这些潜在信息,从而会导致其效果和性能变差。同时,这也是设计位置编码所需要实现的点

如何设计一个好的位置编码

用最简单的整型值来做位置编码

假如有一个序列{L1,L2,L3,L4,L5,L6,L7,L8,L9}
有一个最简单的思路来设计位置编码,那就是我按照顺序,一个一个加,L1我添加数值1作为其位置编码,L2我添加数值2作为位置编码,以此类推

但是显而易见的,这种设计虽然简单,但是问题非常多:

  1. 这样子直接将位置编码加入tokens中,影响token中所提取的特征,假入当前特征值只是5,但是他在序列中的第100个位置,那位置编码100,这就导致这个值本身的特征被大大覆盖了(这个只是个举例,相应的理解下就好了)
  2. 如果在训练时tokens长度只有128,但是实际推理时可能超过128,那么对于从来没见过位置,模型无法理解其意思,因为位置编码的数值是一直增加的,没有范围。导致模型的泛化能力差。

用[0,1]的固定范围值来做位置编码

例如对于三个序列长度的序列,就分别做[0,0.5,1],同样的,四个序列长度,即[0,0.33,0.66,1]

这样子确实可以解决上面的两个问题,即解决了位置编码覆盖特征值的问题以及保证了位置编码的值在训练和推理时范围相同。

但是随之而来的问题是,随着序列长度的变化,序列中的相对距离也产生了变化,用简单地整型值来做位置编码,序列中的相对距离变化也是1 * 距离长度, 但是用当前这种方法,在面对不同长度的序列是,相对距离就不是固定的了。

用二进制编码来做位置编码

加入序列的embed_dim = 3

一共有7个序列,
那么可以分别做位置编码
[0,0,0]
[0,0,1]
[0,1,0]
[0,1,1]
[1,0,0]
[1,0,1]
[1,1,0]
[1,1,1]

将其加入tokens中,这样也很好,即固定了范围,又可以计算元素之间的相对距离

但是他还是有他的缺点, 很明显,二进制的编码是离散的。

使用sin函数和cos函数来做位置编码(transformer)

这一部分理解起来需要一定的数学知识,我讲不明白,推荐大家直接去原博客去看Transformer学习笔记一:Positional Encoding(位置编码)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐