文章目录
1. Title
2. Summary
本文主要是对Transformer中的Positional Encoding问题进行了探索,之前的PE都存在一定的问题:例如无法适应不同长度的序列、不具有平移不变性等。
基于这些问题,本文提出了Conditional Positional Encoding。主要方法是将序列化的tokens重新reshape为2D tensor,然后使用带有zero paddings的2D卷积去捕获相邻token之间的关系,然后重新生成一个PE。
这个PE就能有效缓解以上两个问题,同时即插即用,计算复杂度也很低。
3. Problem Statement
由于Transformer中的Self-Attention操作是Permutation-Invariant的,也就是说,对于同一个序列,任意顺序进行排列,Self-Attention得到的一样的结果。该性质的推导见下图简单说明:
这种Permutation-Invariance显然不是我们所期望的,为了打破这种性质,不难看出,我们需要为每个位置赋予一个独特的标志,这样当求和过程中各个item的位置发生变化后,其对应的item的值也会发生变化,从而打破了这种排列不变性。
这个独特的标志即为Positional Encodings。
目前Positional Encodings分为两种类型:
- Fixed Positional Encodings:即将各个位置的标志设定为固定值,一般是采用不同频率的Sin函数来表示。
- Learnable Positional Encoding:即训练开始时,初始化一个和输入token数目一致的tensor,这个tensor会在训练过程中逐步更新。
以上这些Positional Encodings都存在一些问题:
- 首先,Encodings的长度是提前固定的,在测试过程中,如果遇到了比训练时更长的序列,将难以处理,只能通过插值的方法去进行上采样,从而实现长度的匹配。
- 其次,Encodings不具有Translation Invariance,这不利于分类等问题的解决。
- 最后,即使是Relative Positional Encoding,一方面其需要额外的计算,另一方面其需要对原Transformer进行修改,无法即插即用,其对于分类任务的来说,由于无法提供绝对位置信息,性能也不佳。
以下实验结果证实了上述描述。
4. Method(s)
一个对于视觉任务的合理有效的Positional Encoding,应该需要满足以下需求:
- 使得网络具有Permutation-Variant,但是具有Translation-Invariant。
- 能够处理不同长度的序列。
- 可以提供一定程度的绝对位置信息。
利用局部关系的构建的Positional Encoding即可满足以上要求。为此,本文提出使用一个Positional Encoding Generators(PEG)根据input token之间的局部关系动态构建一个Positional Encoding。
4.1 Positional Encoding Generator
- 为了获取局部关系,首先PEG需要对输入的Tokens序列 X ∈ R B × N × C X \in \mathbb{R}^{B \times N \times C} X∈RB×N×C进行reshape操作,将其还原为2D的shape, X ′ ∈ R B × H × W × C X^{\prime} \in \mathbb{R}^{B \times H \times W \times C} X′∈RB×H×W×C。
- 接下来将 F F F重复应用于 X ′ X^{\prime} X′的local patch上,用于产生Conditional Positional Encoding E B × H × W × C E^{B \times H \times W \times C} EB×H×W×C。
- PEG可以通过一个2D卷积来高效实现。需要注意的是卷积需要使用zero paddings,以获取绝对位置信息。zero paddings是CNN获取绝对位置信息的关键,关于这一点可以参见论文:HOW MUCH POSITION INFORMATION DO CONVOLUTIONAL NEURAL NETWORKS ENCODE?。
PEG的实现见以下代码:
class PosCNN(nn.Module):
def __init__(self, in_chans, embed_dim=768, s=1):
super(PosCNN, self).__init__()
self.proj = nn.Sequential(nn.Conv2d(in_chans, embed_dim, 3, s, 1, bias=True, groups=embed_dim))
self.s = s
def forward(self, x, H, W):
B, N, C = x.shape
feat_token = x
cnn_feat = feat_token.transpose(1, 2).view(B, C, H, W) # reshape
if self.s == 1:
x = self.proj(cnn_feat) + cnn_feat # CNN聚合局部关系并配合残差连接
else:
x = self.proj(cnn_feat)
x = x.flatten(2).transpose(1, 2)
return x
def no_weight_decay(self):
return ['proj.%d.weight' % i for i in range(4)]
4.2 Conditional Positional Encoding Vision Transformers
基于Conditional Positional Encoding,本文进一步提出了Conditional Positional Encoding Vision Transformer(CPVT)。
考虑到cls token不是Translation Invariant,因此,本文进一步去除了cls token,在Transformer Encoder的最后使用GAP去实现完全的Translation Invariant。这种设计使得模型获得进一步的性能提升。
5. Evaluation