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

ni65a41a  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(142)

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

def __init__(self):
    super()
    positional_encoding = nn.Parameter()
def forward(self, x):
    x += positional_encoding

↑可能是这种感觉,然后执行可学习的位置编码。不管是不是这么简单,我不确定我理解的对不对,我想问有经验的人。
此外,我注意到一个经典的bert结构,它的位置实际上只在初始输入时编码一次。这是否意味着后续的bert层,对于彼此来说,失去了捕获位置信息的能力?

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

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

aoyhnmkz

aoyhnmkz1#

位置嵌入的目的是什么?

在transformers(包括BERT)中,不同token之间的唯一交互是通过自我注意层完成的。如果你仔细观察这些层实现的数学运算,你会注意到这些层是排列equivariant:也就是说,

  • 我喜欢编程 *

  • 我喜欢编程吗 *

是一样的,因为两个句子中的单词(=tokens)是一样的,只是它们的顺序不同。
正如你所看到的,这种“置换等变性”在很多情况下并不是一个理想的属性。
为了打破这种对称/等变性,可以简单地“编码”每个单词/标记在句子中的实际位置。举例来说:

  • “I_1 do_2 like_3 coding_4”*

不再等同于

  • “Do_1 I_2 like_3 coding_4”*

这就是位置编码/嵌入的目的--使自我注意层对标记的顺序敏感。
现在回答你们的问题:
1.可学习的位置编码实际上用简单的单个nn.Parameter来实现。位置编码只是添加到每个标记的“代码”,标记其在序列中的位置。因此,它只需要一个与输入序列大小相同的Tensor,每个位置具有不同的值。
1.* 在Transformer架构中引入一次位置编码就足够了吗?* 是的!由于transformers堆叠了多个自我注意层,因此在处理开始时添加一次位置嵌入就足够了。位置信息被“融合”到每个标记学习的语义表示中。
视觉变形器(ViT)中这种效果的一个很好的可视化可以在下面的工作中找到:

在第3.1节和图3它们显示了位置信息如何在早期层中主导令牌的表示,但当您深入Transformer时,语义信息将接管。

lyr7nygr

lyr7nygr2#

@Shai的回答相当精彩。我也有同样的疑问,这个答案对我帮助很大。我想在这个主题上添加另一篇很好的论文,它提供了对位置编码的深入了解:Conditional Positional Encodings for Vision Transformers(arXiv 2021)。
在第4.2节表2中,CPVT-Ti plus显示了比CPVT-Ti更好的性能。CPVT-Ti plus为前五个编码器插入pos嵌入(而不是仅为CPVT-Ti的第一个编码器)。因此,它表明,你的猜测,“我会得到更好的结果,如果前一层的结果是重新定位编码之前,下一个BERT层?“可能是对的。

相关问题