SegFormer

1.网络结构

1

编码器:通过在不同阶段进行下采样,生成多尺度特征。

Efficient Self-Attention:

原始的自注意力计算:

2

计算复杂度为O($N^2$),其中N为w*h

高效的自关注机制:通过一个压缩比R对K进行处理,改进的计算过程如下.0

3

复杂度从O($N^2$)将至O($N^2 \over R$),降低了计算复杂度

注:论文中的R分别取64, 16, 4, 1

通过将K进行reshape将空间维度N的信息转移到通道维度C上,可以得到$\widehat K$;然后通过线性变换层将通道为降到原始维度C上,得到K’,实现空间下采样。

Mix-FFN:为了解决使用位置编码引入位置信息,但由于在测试时的分辨率发生变化时,会引起精度下降的问题

注:训练时生成的位置编码长度小于预测时的需要时,一种处理方法是使用插值将训练时的位置编码扩展到预测时所需的长度。

位置信息在语义分割中不是必需的

Mix-FFN:直接使用3*3卷积捕获一定程度上的位置信息

计算过程如下:

4

注:$x_{in}$为自注意力模块的输出

8

Overlapped Patch Merging:保持patch周围的局部连续性

patch尺寸K、步长S、填充尺寸P,在网络中设置参了2套参数:K = 7, S = 4, P = 3 ;K = 3, S = 2, P = 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class OverlapPatchEmbed(nn.Layer):
def __init__(self,
img_size=224,
patch_size=7, # 卷积核大小
stride=4, # 下采样倍数
in_chans=3, # 输入通道数
embed_dim=768): # 输出通道数
super().__init__()
img_size = to_2tuple(img_size)
patch_size = to_2tuple(patch_size)

self.img_size = img_size
self.patch_size = patch_size
self.H, self.W = img_size[0] // patch_size[0], img_size[
1] // patch_size[1]
self.num_patches = self.H * self.W
# 定义投影变换所用的卷积
self.proj = nn.Conv2D(
in_chans,
embed_dim,
kernel_size=patch_size,
stride=stride,
padding=(patch_size[0] // 2, patch_size[1] // 2))
# 定义layer norm层
self.norm = nn.LayerNorm(embed_dim)

def forward(self, x):
x = self.proj(x) # 通过卷积进行特征重投影,实现下采样、通道变换
x_shape = paddle.shape(x)
H, W = x_shape[2], x_shape[3]
x = x.flatten(2).transpose([0, 2, 1]) # 将H*W维度压缩成1个维度
x = self.norm(x) # 标准化

return x, H, W

解码器

Lightweight All-MLP Decoder:在解码器部分,SegFormer采用了简单的结构,仅由MLP组成

6

5

有效感受野分析

7

如图3的放大图所示,MLP头部(蓝框)的ERF与阶段4(红框)不同,除了非局部注意外,局部注意明显更强。

在上采样阶段,Head的感受野除了具有非局部关注外,还有较强的局部关注。

作者认为之所以这种简单的Decoder能够很好地工作,关键在于分层的Transformer Encoder比传统的基于CNN的Encoder具有更大的感受野。

9

2.实验结果

10