Conditional Positional Encodings for Vision Transformers(论文阅读笔记)

论文来源arxiv.org

本文作者:李炎,硕士研究生,目前研究方向为深度学习、计算机视觉。

摘要

不同于之前的人工设置的定长的位置编码(Position Encoding)或可学习位置编码,本文设计了一种条件位置编码 CPE(conditional positional encoding),CPE 是动态生成的,并以输入 token 的局部邻域为条件( conditioned on the local neighborhood of the input tokens),CPE 可以更好的处理比模型在训练期间见过的更长的输入序列;同时 CPE 可以在不同任务中保持网络模型的平移不变性。同时本文设计了一种 位置编码生成器 PEG (Position Encoding Generator) 用于生成 CPE ,该位置编码生成器很简单,并很容易应用在其他视觉变压器(Vision Transformer)中。

问题描述

之前的视觉转换器( Vision Transformer )中的位置编码( Position Encoding )大多采用人为设定的固定长度的 Position Encoding 或者可学习的 Position Encoding ,但是上述两种位置编码方法在网络模型训练中与其他网络参数一同训练,训练过后位置编码的长度已经固定,当输入 Vision Transformer 的序列长度变化较大的时候,表现出来的泛化能力较弱,为了更好的处理更长的输入序列并在各种视觉任务中保持网络结构的平移不变性

本文核心工作

  1. 设计了一种性能更好的条件位置编码 CPE 。
  2. 设计了一种位置编码生成器 PEG 用于生成 CPE。

模型

本文认为视觉任务的成功位置编码应满足以下要求:
(1) 使输入序列排列可变但平移不变。
(2) 具有归纳性,能够处理比训练期间更长的序列。
(3)具有提供一定程度绝对位置的能力。如 [13] 所示,这对性能很重要。
~
本文认为通过位置编码来表征局部关系足以满足上述所有条件。

在这里插入图片描述

  • 首先 PEG 对输入维度为 B ∗ N ∗ C B*N*C BNC 的 Tokens 序列进行reshape操作,将其还原为2D的shape: B ∗ H ∗ W ∗ C B* H* W* C BHWC

  • 然后来将一个 F 函数重复应用于的局部块(local patch)上,用于产生Conditional Positional Encoding 。

     B:每批的图片数
     N:Token数,即将图片分成的块(Patch)数; $N=(H*W)/d$
     d:每个 Patch 的尺寸为 d*d
     C:图片的通道数
     H、W:分别为原图的高、宽
    

PEG 通过一个 F 函数来高效实现。需要注意的是 卷积( F 函数)一定要使用zero paddings,以获取绝对位置信息。zero paddings[1]是图中 F 函数获取绝对位置信息的关键。 F 函数由内核为 k ( k ≥ 3 ) k (k ≥ 3) k(k3) ( k − 1 ) / 2 (k−1)/ 2 (k1)/2 零填充的二维卷积有效地实现。其中 F 可以是各种形式,例如可分离卷积和许多其他形式。

这里的零填充[1]非常重要!!通过零填充可以获取 patch 的绝对位置。
为什么使用二维卷积就变成了条件位置编码呢?
因为,卷积核尺寸越大(例如 3*3),则包含的周边信息越多,可以理解为,将原图像的顺序排列的特征具有了空间信息,因此信息包含更多,则能很好的提高准确率,是本文的关键理解

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)]

实验

数据集
使用具有 1K 类和 1.3M 图像的 ILSVRC-2012 ImageNet 数据集。

实验设计及结果

  1. 与其他SOTA方法进行对比:
    在这里插入图片描述
    与之前的 Transformer 相比,加入了位置编码的 CPVT 模型具有更好的性能。

  2. 对比PEG 和二维正弦编码
    在这里插入图片描述
    使用 PEG 的位置编码替换了原始的 2-D编码,获得了更好的性能。
    物体检测的性能结果也表明 PEG 可以提供绝对位置信息,因为物体检测任务需要边界框的绝对坐标

  3. CPVT 中提出的 PEG 可以直接推广到更大的图像尺寸,而无需任何微调
    224 ∗ 224 224*224 224224 图像上训练的 CPVT,应用到 384 ∗ 384 384*384 384384 上,效果相近,无需微调

总结

本文提出的 CPE (conditional positional encoding)位置编码可以实现比固定位置编码和可学习位置编码更强的性能。并且设计了一种位置编码生成器 PEG (Position Encoding Generator),加入了 PEG 的视觉变压器模型可以处理更长的输入序列并在视觉任务中保持所需的平移不变性。同时此 CPE 很容易实现并且成本可以忽略不计。

论文代码:GitHub

其他相关文章与知识

Self-attention:
在这里插入图片描述
Multi-head Self-Attention:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

参考文献

[1] HOW MUCH POSITION INFORMATION DO CONVOLUTIONAL NEURAL NETWORKS ENCODE?

  1. 【论文笔记】Conditional Positional Encodings for Vision Transformers
  2. 2021-Conditional Positional Encodings for Vision Transformers
  3. DeiT:使用Attention蒸馏Transformer
  4. Training data-efficient image transformers & distillation through attention
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
这个警告是由ESLint的规则`no-unneeded-ternary`引起的,它表示在默认赋值时使用条件表达式是不必要的。 在上面的代码示例中,可以看到在`filterItems`方法中使用了条件表达式来处理空字符串的情况。然而,根据该警告,使用条件表达式是不必要的,因为我们可以直接使用简单的赋值操作来实现相同的效果。 要解决这个警告,你可以将条件表达式改为简单的赋值操作。 下面是修改后的代码示例: ```vue <template> <div> <q-select v-model="selectedItem" :options="filteredItems" option-label="label" option-value="value" :filter="filterItems" input-debounce="300" placeholder="Search" /> </div> </template> <script> export default { data() { return { selectedItem: '', items: [ { label: 'Option 1', value: 'option1' }, { label: 'Option 2', value: 'option2' }, { label: 'Option 3', value: 'option3' }, // 其他选项... ], filteredItems: [] }; }, methods: { filterItems(val, update) { if (val === '') { update(() => { this.filteredItems = []; }); } else { const lowercaseVal = val.toLowerCase(); this.filteredItems = this.items.filter(item => item.label.toLowerCase().includes(lowercaseVal) ); } } } }; </script> ``` 在修改后的代码中,我们移除了条件表达式,并直接在`if`语句的分支中进行赋值操作。这样可以避免不必要的条件表达式。 通过这种方式,我们可以消除ESLint警告,并且代码逻辑仍然保持一致。 希望这个解决方案对你有所帮助!如果还有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值