注意力机制无法考虑位置关系,通过在输入表示中添加位置编码(positional encoding)来注入绝对的或相对的位置信息

对于位置 $i$ 的词元 $x_i$,其位置编码为 $x_i^\prime = x_i + p_i$,其中 $p_i$ 可以是固定的也可以是可学习的

为什么可以直接加上去

TODO

正弦余弦固定位置编码

考虑输入和位置编码为 $X, P\in\mathbb{R}^{n\times d}$

$$ \begin{align*} p_{i, 2j} &= \sin\left(\frac{i}{10000^{2j/d}}\right)\\ p_{i, 2j+1} &= \cos\left(\frac{i}{10000^{2j/d}}\right) \end{align*} $$

class PositionEmbedding(nn.Module):
    def __init__(self, hidden_size, max_length=1024):
        super().__init__()
        self.P = torch.zeros((max_length, hidden_size))
        x = torch.arange(max_length).reshape(-1, 1) /\\
            torch.pow(torch.tensor(10000), torch.arange(0, hidden_size, 2) / hidden_size).reshape(1, -1)
        self.P[:, 0::2] = torch.sin(x)
        self.P[:, 1::2] = torch.cos(x)

    def forward(self, x):
        seq_length = x.shape[1]
        return x + self.P[:seq_length, :]

绝对位置信息

image.png

考虑二进制的表示,随着数量的增大,较高比特位的交替频率低于较低比特位,如最低位每次增加都会变化,第二位增加两次才会变化

于是在正弦余弦位置编码中,从词元维度的角度,随着绝对位置的增加,其位置编码都在 0-1 之间交替,在维度越低的地方,交替越快,维度越高的地方,交替越慢

TODO:那为什么要拿 sin 和 cos 交替

相对位置信息

除了捕获绝对位置信息之外,上述的位置编码还允许模型学习得到输入序列中相对位置信息。 这是因为对于任何确定的位置偏移 $\delta$,位置 $i+\delta$ 处的位置编码可以线性投影位置 $i$ 处的位置编码来表示。 这种投影的数学解释是,令 $w_j = 1/10000^{2j/d}$,对于任何确定的位置偏移 $\delta$,任何一对 $(p_{i, 2j}, p_{i, 2j+1})$ 都可以线性投影到 $(p_{i+\delta, 2j}, p_{i+\delta, 2j+1})$,且投影矩阵不依赖于任何位置 $i$

把位置编码作为可学习的参数

TODO

缺点:不能处理未见长度,无法在长度上泛化

前沿