SETR发表于2021年CVRP,原论文名为《Rethinking Semantic Segmentation from a Sequence-to-Sequence Perspective with Transformers》,是第一篇基于Transfomer做语义分割的模型。
1.1 网络结构及特点
SETR的网络结构如下:
其中图(a)是整体的网路结构,图(b)和图(c)是两种不同的Decoder方式。
我们首先来看下整体的网络结构,SERT从输入部分到Encoder和ViT是接近的,先将
H
×
W
H\times W
H×W图像按照
16
×
16
16\times16
16×16的大小划分为图像块,然后通过
1024
1024
1024个
16
×
16
16\times16
16×16的卷积和转化为
H
×
W
/
256
H \times W/256
H×W/256个长度为
1024
1024
1024的Patch Embedding,再加上Positional Embedding后就融入有Multi Head Attention叠加起来的Encoder部分。详细的结构分析读者可以参考计算机视觉算法——Vision Transformer / Swin Transformer,这里我们来重点介绍下Decoder部分。
1.1.1 Decoder
SETR的论文中一共对比了三种Decoder模式:
第一种是Naive Upsampling,具体做法
H
×
W
/
256
H \times W/256
H×W/256个
1024
1024
1024维的输出结果Reshape成
H
/
16
×
W
/
16
×
1024
H/16 \times W/16 \times 1024
H/16×W/16×1024,然后通过两个
1
×
1
1\times1
1×1的卷积将特征变成
H
/
16
×
W
/
16
×
C
H/16 \times W/16 \times C
H/16×W/16×C,其中
C
C
C就是分类的大小,然后再将
H
/
16
×
W
/
16
×
C
H/16 \times W/16 \times C
H/16×W/16×C通过双线性插值直接Upsample到原分辨率的大小且Cross Entropy损失。
Segmenter的Encoder输出的为Patch Embedding
z
L
∈
R
N
×
D
\mathbf{z}_{\mathbf{L}} \in \mathbb{R}^{N \times D}
zL∈RN×D,其中
N
N
N为Patch数量,
D
D
D为Embedding的长度。而在Decoder中,输入中加入了Class Embedding
c
l
s
=
z
lin
∈
R
N
×
K
\bold{cls}=\mathbf{z}_{\operatorname{lin}} \in \mathbb{R}^{N \times K}
cls=zlin∈RN×K,其中
K
K
K为输出类别数量。在Decoder中,Patch Embedding和Class Embedding会经过若干个Attention Layer,最后通过点乘输出一个维度为
K
×
N
K\times N
K×N的Feature:
Masks
(
z
M
′
,
c
)
=
z
M
′
c
T
\operatorname{Masks}\left(\mathbf{z}_{\mathbf{M}}^{\prime}, \mathbf{c}\right)=\mathbf{z}_{\mathbf{M}}^{\prime} \mathbf{c}^T
Masks(zM′,c)=zM′cT该Feature最后经过bilinearly upsample以及最后Softmax得到最后的输出特征图,下面这个图说明了Class Embedding和最后输出的Segmentation map的关系:
Efficient Self Attention的想法来自于《 Pyramid vision transformer: A versatile backbone for dense prediction without convolutions》,主要的目的是为了减小Self Attention的计算量,而Self Attention模块也正是整个Encoder中计算量占据比重最大的一块。
原始的Self Attention的公式为:
Attention
(
Q
,
K
,
V
)
=
Softmax
(
Q
K
⊤
d
h
e
a
d
)
V
\operatorname{Attention}(Q, K, V)=\operatorname{Softmax}\left(\frac{Q K^{\top}}{\sqrt{d_{h e a d}}}\right) V
Attention(Q,K,V)=Softmax(dheadQK⊤)V其中
Q
,
K
,
V
Q, K, V
Q,K,V的维度均为
N
×
C
N \times C
N×C,而
N
=
H
×
W
N=H \times W
N=H×W为整个输入序列的长度,该过程的计算量是
O
(
N
2
)
O\left(N^2\right)
O(N2),当输入是一张大图片时,计算量也会变得非常大,Transformer的具体计算量可以参考计算机视觉算法——Vision Transformer / Swin Transformer,Efficient Self Attention公式如下:
K
^
=
Reshape
(
N
R
,
C
⋅
R
)
(
K
)
\hat{K}=\operatorname{Reshape}\left(\frac{N}{R}, C \cdot R\right)(K)
K^=Reshape(RN,C⋅R)(K)
K
=
Linear
(
C
⋅
R
,
C
)
(
K
^
)
K=\operatorname{Linear}(C \cdot R, C)(\hat{K})
K=Linear(C⋅R,C)(K^)假定输入序列的维度为
N
×
C
{N} \times C
N×C,第一个公式的意思时将输入序列
K
K
K变成
N
R
×
(
C
⋅
R
)
\frac{N}{R} \times(C \cdot R)
RN×(C⋅R)大小,而
Linear
(
C
in
,
C
out
)
(
⋅
)
\operatorname{Linear}\left(C_{\text {in }}, C_{\text {out }}\right)(\cdot)
Linear(Cin ,Cout )(⋅)意味着通过一个线性层将
C
i
n
C_{i n}
Cin-dimensional的输入变成
C
out
C_{\text {out }}
Cout -dimensional,通过上面两个公式,将输入序列
K
K
K的维度变为了
N
R
×
C
\frac{N}{R} \times C
RN×C,因此计算量从
O
(
N
2
)
O\left(N^2\right)
O(N2)降为了
O
(
N
2
R
)
O\left(\frac{N^2}{R}\right)
O(RN2)。在Segformer中从第一层到第四层设置的
R
R
R分别为
[
64
,
16
,
4
,
1
]
[64,16,4,1]
[64,16,4,1],我个人理解这一步相当于是增大了Patch,降低了分辨率,但是不是在原始输入上操作,而是在输入的Feature上操作,这样应该是可以减少分辨率降低带来的损失,到底损失了多少,在论文中我暂时还没有找到这一部分的Ablation Study对比结果。
3.1.3 Mix-FFN
解释Mix FFN就需要先提到Conditional Position Embeddingh,这个模块首次提出于2021年CVPR的论文《Conditional Positional Encodings for Vision Transformers》,解决的主要问题也就是Segformer中提到的,当测试和训练的图像分辨率不同时,绝对Position Embedding会面临插值而导致性能下降的问题,而Conditional Position Embedding就是通过卷积对不同Token进行位置关联。这里我们展开讲下:
在《Conditional Positional Encodings for Vision Transformers》论文中对不同Ecoding方式进行了对比,首先不加Positional Embedding肯定时不行的,Self -Attention的性质决定了对于同一个序列,任意排序,得到的结果将会时一样的,从实验结果看也是性能也是最差的,而Learnable和Sin-Cos会面临上面提到输入序列不可变长的问题,而Relative需要额外的计算且性能会下降。
但是平移不变性是好理解,当一个物体在图像中发生平移时,应该只时物体对应的token发生了变化,但是token embeding的值应该是相同的,对于空间不等价性应该就是物体在图中发生平移后最后的self attention的结果应该是不同的。那么作者任务卷积正好就满足了上述这些特性,于是就设计了如下的Conditional Position Embedding模块:
对应代码如下:
classPEG(nn.Module):def__init__(self, dim=256, k=3):
self.proj = nn.Conv2d(dim, dim, k,1, k//2, groups=dim)# Only for demo use, more complicated functions are effective too.defforward(self, x, H, W):
B, N, C = x.shape
cls_token, feat_token = x[:,0], x[:,1:]# cls token不参与PEG
cnn_feat = feat_token.transpose(1,2).view(B, C, H, W)
x = self.proj(cnn_feat)+ cnn_feat # 产生PE加上自身
x = x.flatten(2).transpose(1,2)
x = torch.cat((cls_token.unsqueeze(1), x), dim=1)return x
回到本篇文章,本论文认为语义分割中不需要Positional Encoding,因此作者设计了Mix-FNN,公式如下:
x
out
=
MLP
(
GELU
(
Conv
3
×
3
(
MLP
(
x
i
n
)
)
)
)
+
x
i
n
,
\mathbf{x}_{\text {out }}=\operatorname{MLP}\left(\operatorname{GELU}\left(\operatorname{Conv}_{3 \times 3}\left(\operatorname{MLP}\left(\mathbf{x}_{i n}\right)\right)\right)\right)+\mathbf{x}_{i n},
xout =MLP(GELU(Conv3×3(MLP(xin))))+xin,从上面网络大图中我们可以看到,该模块是替换原本的Feed Forward Layer,区别其实也就是在MLP的过程中假如了一个
3
×
3
3\ \times3
3×3的卷积,我觉得该卷积的作用和PEG的作用应该是类似的。作者在Ablation Study中有对比到,使用普通的Positional Encoding和Mix-FFN对于精度影响如下:
3.1.5 Lightweight All-MLP Decoder
Segmenter中的Decoder相对很多语义分割的模型的Decoder来说要简单很多,具体步骤如下:
F
^
i
=
Linear
(
C
i
,
C
)
(
F
i
)
,
∀
i
\hat{F}_i=\operatorname{Linear}\left(C_i, C\right)\left(F_i\right), \forall i
F^i=Linear(Ci,C)(Fi),∀i
F
^
i
=
Upsample
(
W
4
×
W
4
)
(
F
^
i
)
,
∀
i
\hat{F}_i=\text { Upsample }\left(\frac{W}{4} \times \frac{W}{4}\right)\left(\hat{F}_i\right), \forall i
F^i= Upsample (4W×4W)(F^i),∀i
F
=
Linear
(
4
C
,
C
)
(
Concat
(
F
^
i
)
)
,
∀
i
F=\operatorname{Linear}(4 C, C)\left(\text { Concat }\left(\hat{F}_i\right)\right), \forall i
F=Linear(4C,C)( Concat (F^i)),∀i
M
=
Linear
(
C
,
N
c
l
s
)
(
F
)
,
M=\operatorname{Linear}\left(C, N_{c l s}\right)(F),
M=Linear(C,Ncls)(F),其中第一步是将通过MLP调整Encoder输出特征
F
i
F_i
Fi的通道数,第二步是将分辨率分别为
1
32
\frac{1}{32}
321,
1
16
\frac{1}{16}
161,
1
8
\frac{1}{8}
81的通道数上采样到
1
4
\frac{1}{4}
41,第三步将四种分辨率的上采样后的特征Concat到一起,然后再通过一个MLP将通道数调整到
C
C
C,第四步就是通过一个MLP将通道数调整到最后出的类别。作者在论文中强调,如果简单的Decoder能取得比较好的效果得益于强大的Encoder,在论文中作者可视化了DeepLabv3+和Segformer的Encoder感受野: