相较于CNN来说,Transformer由于其能高效地捕获远距离依赖的特性,近期在计算机视觉领域也引领了一波潮流。Transformer主要是依靠Self-Attention去捕获各个token之间的关系,但是这种Global Self-Attention的计算复杂度太高
O
(
N
2
)
O(N^2)
O(N2),不利于在token数目较多的密集检测任务(分割、检测)中使用。
基于以上考虑,目前主流有两种应对方法:
一种是以SwinTransformer为代表的Locally-Grouped Self-Attention。其在不重叠的窗口内计算Self-Attention,当窗口大小固定时,整体的计算复杂度将下降至
O
(
N
)
O(N)
O(N),然后再通过其他方法例如SwinTransformer中的Shift-Window的方法去实现窗口间的互动。但这种方法的缺点在于窗口的大小会不一致,不利于现代深度学习框架的优化和加速。
一种是以PVT为代表的Sub-Sampled Version Self-Attention。其在计算Self-Attention前,会先对QKT Token进行下采样,虽然计算复杂度还是
O
(
N
2
)
O(N^2)
O(N2),但是在实际过程中也已经可以接受。
首先将2D feature map划分为多个Sub-Windows,并仅在Window内部进行Self-Attention计算,计算量会大大减少,由
(
H
2
W
2
d
)
\left(H^{2} W^{2}d\right)
(H2W2d)下降至
O
(
k
1
k
2
H
W
d
)
\mathcal{O}\left(k_{1} k_{2} H W d\right)
O(k1k2HWd),其中
k
1
=
H
m
,
k
2
=
W
n
k_{1}=\frac{H}{m}, k_{2}=\frac{W}{n}
k1=mH,k2=nW,当
k
1
,
k
2
k_1,k_2
k1,k2固定时,计算复杂度将仅与
H
W
HW
HW呈线性关系。
4.2.2 Global Sub-Sampled Attention(GSA)
LSA缺乏各个Window之间的信息交互,比较简单的一个方法是,在LSA后面再接一个Global Self-Attention Layer,这种方法在实验中被证明也是有效的,但是其计算复杂度会较高:
O
(
H
2
W
2
d
)
\mathcal{O}\left(H^{2} W^{2} d\right)
O(H2W2d)。
另一个思路是,将每个Window提取一个维度较低的特征作为各个window的表征,然后基于这个表征再去与各个window进行交互,相当于Self-Attention中的Key的作用,这样一来,计算复杂度会下降至:
O
(
m
n
H
W
d
)
=
O
(
H
2
W
2
d
k
1
k
2
)
\mathcal{O}(m n H W d)=\mathcal{O}\left(\frac{H^{2} W^{2} d}{k_{1} k_{2}}\right)
O(mnHWd)=O(k1k2H2W2d)。 这种方法实际上相当于对feature map进行下采样,因此,被命名为Global Sub-Sampled Attention。 综合使用LSA和GSA,可以取得类似于Separable Convolution(Depth-wise+Point-wise)的效果,整体的计算复杂度为:
O
(
H
2
W
2
d
k
1
k
2
+
k
1
k
2
H
W
d
)
\mathcal{O}\left(\frac{H^{2} W^{2} d}{k_{1} k_{2}}+k_{1} k_{2} H W d\right)
O(k1k2H2W2d+k1k2HWd)。同时有:
H
2
W
2
d
k
1
k
2
+
k
1
k
2
H
W
d
≥
2
H
W
d
H
W
\frac{H^{2} W^{2} d}{k_{1} k_{2}}+k_{1} k_{2} H W d \geq 2 H W d \sqrt{H W}
k1k2H2W2d+k1k2HWd≥2HWdHW,当且仅当
k
1
⋅
k
2
=
H
W
k_{1} \cdot k_{2}=\sqrt{H W}
k1⋅k2=HW。 考虑到分类任务中,
H
=
W
=
224
H=W=224
H=W=224是比较常规的设置,同时,不是一般性使用方形框,则有
k
1
=
k
2
k_1=k_2
k1=k2,第一个stage的feature map大小为56,可得
k
1
=
k
2
=
56
=
7
k_1=k_2=\sqrt{56}=7
k1=k2=56=7。 当然可以针对各个Stage去设定其窗口大小,不过为了简单性,所有的
k
k
k均设置为7。
整个Transformer Block可以被表示为:
z
^
i
j
l
=
LSA
(
LayerNorm
(
z
i
j
l
−
1
)
)
+
z
i
j
l
−
1
z
i
j
l
=
FFN
(
LayerNorm
(
z
^
i
j
l
)
)
+
z
^
i
j
l
z
^
l
+
1
=
GSA
(
LayerNorm
(
z
l
)
)
+
z
l
z
l
+
1
=
FFN
(
LayerNorm
(
z
^
l
+
1
)
)
+
z
^
l
+
1
,
i
∈
{
1
,
2
,
…
,
m
}
,
j
∈
{
1
,
2
,
…
,
n
}
\begin{array}{l} \hat{\mathbf{z}}_{i j}^{l}=\text { LSA }\left(\text { LayerNorm }\left(\mathbf{z}_{i j}^{l-1}\right)\right)+\mathbf{z}_{i j}^{l-1} \\ \mathbf{z}_{i j}^{l}=\text { FFN }\left(\text { LayerNorm }\left(\hat{\mathbf{z}}_{i j}^{l}\right)\right)+\hat{\mathbf{z}}_{i j}^{l} \\ \hat{\mathbf{z}}^{l+1}=\text { GSA }\left(\text { LayerNorm }\left(\mathbf{z}^{l}\right)\right)+\mathbf{z}^{l} \\ \mathbf{z}^{l+1}=\text { FFN }\left(\text { LayerNorm }\left(\hat{\mathbf{z}}^{l+1}\right)\right)+\hat{\mathbf{z}}^{l+1}, \\ i \in\{1,2, \ldots, m\}, j \in\{1,2, \ldots, n\} \end{array}
z^ijl= LSA ( LayerNorm (zijl−1))+zijl−1zijl= FFN ( LayerNorm (z^ijl))+z^ijlz^l+1= GSA ( LayerNorm (zl))+zlzl+1= FFN ( LayerNorm (z^l+1))+z^l+1,i∈{1,2,…,m},j∈{1,2,…,n}同时在每个Stage的第一个Block中会引入CPVT中的的PEG对位置信息进行编码。