--- created: 2025-08-03 21:19:11 tags: - "Research" - "基础" - "Transformer" - "位置编码" - "序列建模" --- ## 0. 参考资料 \[1][一文教你彻底理解Transformer中Positional Encoding](https://zhuanlan.zhihu.com/p/338592312)--主要 \[2][Transformer Architecture: The Positional Encoding - Amirhossein Kazemnejad's Blog](https://kazemnejad.com/blog/transformer_architecture_positional_encoding)--各种关于位置编码博客的源头 \[3][[【Transformer系列】深入浅出理解Positional Encoding位置编码-CSDN博客](https://blog.csdn.net/m0_37605642/article/details/132866365)]--对\[2]的不错的中文解析 \[4][Transformer 结构详解:位置编码 | Transformer Architecture: The Positional Encoding-CSDN博客](https://blog.csdn.net/qq_36667170/article/details/124336971) ## 1. 为什么要有位置编码? 在RNN处理一个句子时, 以一个**序列的模式逐个处理句子中的词语**, 这使得词语的顺序信息在处理过程中被天然的保存下来了, 并不需要额外的处理. [[CNN-卷积层, 池化层 与 全连接层|CNN]]也一样, 卷积的存在保存了局部的特征, 虽然是局部的, 但就这一小范围内还是有位置和顺序的. 而对于[[Transformer]]来说, 由于句子中的词语都是**同时进入网络进行处理, 顺序信息在输入网络时就已丢失**. 因此, Transformer是需要额外的处理来告知每个词语的相对位置的. 解决方案就是[Attention is All You Need](http://arxiv.org/abs/1706.03762)中提到的Positional Encoding. 总而言之, **Positional Encoding就是句子中词语相对位置的编码,让Transformer保留词语的位置信息.** (位置编码实际上有很多种方式, 在Transformer的论文中使用的是Sinusoidal Positional Encoding, 也就是使用**正余弦函数**来表示绝对位置, 位置编码的分类在[这篇博客中](https://blog.csdn.net/m0_37605642/article/details/132866365)略有提到) ## 2. 位置编码的原理是什么 理想状态下,编码方式应该要满足以下几个条件, - 对于每个位置的词语,它都能提供**一个独一无二的编码** - **词语之间的间隔**对于**不同长度**的句子来说,含义应该是**一致**的 - 能够随意**延伸到任意长度的句子** ### 2.1 原文公式 在论文中给出的解决方案如下: $$\overrightarrow{p_t}^{(i)}=f(t)^{(i)}:=\left\{\begin{array}{ll}\sin(\omega_k.t),&\mathrm{if~}i=2k\\\cos(\omega_k.t),&\mathrm{if~}i=2k+1\end{array}\right.$$ $\text{where }\omega_k=\frac1{10000^{2k/d}}$ - $t$表示当前词语在句子中的 *位置* - $\overrightarrow{p_t}\in R^d$表示的是该词语的 *位置编码* - $d$表示的是 *位置编码的维度*. $$\overrightarrow{p_{t}}=\begin{bmatrix}\sin(\omega_{1}.t)\\\cos(\omega_{1}.t)\\\\\sin(\omega_{2}.t)\\\cos(\omega_{2}.t)\\....\\\cos(\omega_{d/2}.t)\\\cos(\omega_{d/2}.t)\end{bmatrix}_{d\times1}$$ 从公式可以看出, 其实 *一个词语的位置编码是由不同频率的余弦函数函数组成的* , 从低位到高位, 余弦函数对应的频率由1降低到了$\frac{1}{10000}$,按照论文中的说法, 也就是,波长从$2π$增加到了$10000·2π$。 在[这篇博客中](https://blog.csdn.net/m0_37605642/article/details/132866365)还有更深入的公式解析, ~~不过数学苦手还是直接看看直观理解是如何吧~~. ### 2.2 直观理解 一堆 $cos$ 和 $sin$ 组合在一起形成的 $\overrightarrow{p_t}$ 居然就能表示位置信息实在让人摸不着头脑, 下面让我们来句一个很简单的信息表示的例子来尝试着理解一下. 在下面的表格中, 存了0~15的二进制表示, 可以发现, *每个比特位的**变化率**是不一样* 的,**越低位的变化越快**. (最低位的0和1 *每**个**数字会变化一次*, 而最高位, *每**8**个数字才会变化一次*. | 0: 0000 | 8: 1000 | | ------- |:---------:| | 1: 0001 | 9: 1001 | | 2: 0010 | 10: 1010 | | 3: 0011 | 11: 1011 | | 4: 0100 | 12: 1100 | | 5: 0101 | 13: 1101 | | 6: 0110 | 14: 1110 | | 7: 0111 | 15: 1111 | 不同 **频率(周期)** 的 $sin$ 和 $cos$ 组合其实也是同样的道理: 通过调整三角函数的频率,我们可以实现这种低位到高位的变化,这样的话,位置信息就表示出来了。(说到底计算机中的信息不也是这样的二进制吗, 所以可以给transformer中的输入中的每一个token给出唯一的位置编码)