可学习位置嵌入的本质是什么?嵌入可以更好地改善结果吗?

Ada*_*mer 7 transformer-model deep-learning pytorch bert-language-model

我最近正在阅读huggingface项目的bert源代码。我注意到所谓的“可学习位置编码”在实现时似乎指的是特定的 nn.Parameter 层。

\n
def __init__(self):\n    super()\n    positional_encoding = nn.Parameter()\ndef forward(self, x):\n    x += positional_encoding\n
Run Code Online (Sandbox Code Playgroud)\n

\xe2\x86\x91 可能是这种感觉,然后进行了可学习的位置编码。不管是不是这么简单,我不确定我理解是否正确,我想请教有经验的人。

\n

此外,我注意到一个经典的 bert 结构,其位置实际上仅在初始输入时编码一次。这是否意味着后续的bert层,对于彼此来说,失去了捕获位置信息的能力?

\n
BertModel(\n  (embeddings): BertEmbeddings(\n    (word_embeddings): Embedding(30522, 768, padding_idx=0)\n    (position_embeddings): Embedding(512, 768)\n    (token_type_embeddings): Embedding(2, 768)\n    (LayerNorm): LayerNorm((768,), eps=1e-12, elementwise_affine=True)\n    (dropout): Dropout(p=0.1, inplace=False)\n  )\n  (encoder): BertEncoder(\n    (layer): ModuleList(\n      (0): BertLayer(...)\n      ...\n  (pooler): BertPooler(...)\n
Run Code Online (Sandbox Code Playgroud)\n

如果在下一个 BERT 层之前对上一层的结果进行重新位置编码,我会得到更好的结果吗?

\n

Sha*_*hai 10

位置嵌入的目的是什么?

在 Transformer 中(包括 BERT),不同 token 之间的唯一交互是通过自注意力层完成的。如果仔细观察这些层实现的数学运算,您会发现这些层是排列等变的:也就是说,
“我喜欢编码”

“我喜欢编码吗”
的表示 是相同的,因为单词 (= tokens)在两个句子中是相同的,只是它们的顺序不同。
正如您所看到的,这种“排列等方差”在许多情况下并不是所需的属性。
为了打破这种对称性/等变性,我们可以简单地“编码”句子中每个单词/标记的实际位置。例如:
“I_1 do_2 like_3coding_4”
不再与
“Do_1 I_2 like_3coding_4”相同

这就是位置编码/嵌入的目的——使自注意力层对标记的顺序敏感。

现在回答你的问题:

  1. 可学习的位置编码确实是用一个简单的单个nn.Parameter. 位置编码只是添加到每个标记的“代码”,标记其在序列中的位置。因此,它所需要的只是一个与输入序列大小相同、每个位置具有不同值的张量。
  2. 在 Transformer 架构中引入一次位置编码就足够了吗? 是的!由于 Transformer 堆叠了多个自注意力层,因此在处理开始时添加一次位置嵌入就足够了。位置信息被“融合”到每个标记学习的语义表示中。
    视觉变换器 (ViT) 中这种效果的良好可视化可以在这项工作中找到:
    Shir Amir、Yossi Gandelsman、Shai Bagon 和 Tali Dekel Deep ViT Features as Dense Visual Descriptors (arXiv 2021)。
    秒后。3.1 和图 在图 3 中,它们展示了位置信息如何在早期层中主导标记的表示,但是当您深入到转换器中时,语义信息就会占据主导地位。