经典CNN网络结构

回顾21世纪10年代,深度学习取得了巨大的进步,产生了巨大的影响。主要驱动力是神经网络的复兴,特别是卷积神经网络(ConvNets)。十年来,视觉识别领域成功地从工程特征转变为设计(ConvNet)架构。尽管采用反向传播训练方法的卷积神经网络自上世纪八十年代已经发明了,但直到2012年我们才看到它作为视觉特征学习的真正潜力。AlexNet的引入促成了“ImageNet的时刻”,引领了计算机视觉领域的一个新时代,这个领域因此而快速演化。具有代表性的网络有VGGNet、Inceptions、Resnet、DenseNet、MobileNet、EfficientNet、RegNet等,它们分别关注精度、效率、可扩展性等方面,并且普及了很多有用的设计原则。

1、 VGGNet

VGG16相比AlexNet的一个改进是采用连续的几个3×3的卷积核代替AlexNet中的较大卷积核(11×11,7×7,5×5)。对于给定的感受野(与输出有关的输入图片的局部大小),采用堆积的小卷积核是优于采用大的卷积核,因为多层非线性层可以增加网络深度来保证学习更复杂的模式,而且代价还比较小(参数更少)。

简单来说,在VGG中,使用了3个3×3卷积核来代替7×7卷积核,使用了2个3×3卷积核来代替5*5卷积核,这样做的主要目的是在保证具有相同感知野的条件下,提升了网络的深度,在一定程度上提升了神经网络的效果。

网络结构:

2、 Inception系列网络

Inception V1

在这之前,网络大都是这样子的:

也就是卷积层和池化层的顺序连接。这样的话,要想提高精度,增加网络深度和宽度是一个有效途径,但也面临着参数量过多、过拟合等问题。(当然,改改超参数也可以提高性能)

有没有可能在同一层就可以提取不同(稀疏或不稀疏)的特征呢(使用不同尺寸的卷积核)?于是,2014年,在其他人都还在一味的增加网络深度时(比如vgg),GoogleNet就率先提出了卷积核的并行合并(也称Bottleneck Layer),如下图。

和卷积层、池化层顺序连接的结构(如VGG网络)相比,这样的结构主要有以下改进:

  1. 一层block就包含1×1卷积,3×3卷积,5×5卷积,3×3池化(使用这样的尺寸不是必需的,可以根据需要进行调整)。这样,网络中每一层都能学习到“稀疏”(3×3、5×5)或“不稀疏”(1×1)的特征,既增加了网络的宽度,也增加了网络对尺度的适应性;
  2. 通过deep concat在每个block后合成特征,获得非线性属性。

按照这样的结构来增加网络的深度,虽然可以提升性能,但是还面临计算量大(参数多)的问题。为改善这种现象,GooLeNet借鉴Network-in-Network的思想,使用1×1的卷积核实现降维操作(也间接增加了网络的深度),以此来减小网络的参数量(这里就不对两种结构的参数量进行定量比较了),如图所示。

最后实现的inception v1网络是上图结构的顺序连接,其中不同inception模块之间使用2×2的最大池化进行下采样,如表所示。

如表所示,实现的网络仍有一层全连接层,该层的设置是为了迁移学习的实现(下同)。

在之前的网络中,最后都有全连接层,经实验证明,全连接层并不是很必要的,因为可能会带来以下三点不便:

  • 网络的输入需要固定
  • 参数量多
  • 易发生过拟合

实验证明,将其替换为平均池化层(或者1×1卷积层)不仅不影响精度,还可以减少参数量。

此外,实验室的小伙伴最近做了下实验,如果是小目标检测的话,网络的最后还是需要几层全连接层的,猜想可能是用池化的话会损失太多信息,毕竟是小目标。

———————————————————————————————–

Inception V2和Inception V3的改进,主要是基于V3论文中提到的四个原则:

  1. 避免表示瓶颈,尤其是在网络的前面。一般来说,特征图从输入到输出应该缓慢减小。
  2. 高维度特征在网络局部处理更加容易。考虑到更多的耦合特征,在卷积网络中增加非线性。可以让网络训练更快。
  3. 空间聚合可以以低维度嵌入进行,这样不会影响特征的表达能力。如,在进行大尺度卷积之前,先对输入进行降维。
  4. 平衡网络的宽度和深度。增加宽度和深度都会带来性能上的提升,两者同时增加带来了并行提升,但是要考虑计算资源的合理分配。

———————————————————————————————–

Inception v2

注意,这里实现的inception v2的结构是在inception v3论文中有介绍)

2015年Google团队又提出了inception v2的结构,基于上面提到的一些原则,在V1的基础之上主要做了以下改进:

⑴ 使用BN层,将每一层的输出都规范化到一个N(0,1)的正态分布,这将有助于训练,因为下一层不必学习输入数据中的偏移,并且可以专注与如何更好地组合特征(也因为在v2里有较好的效果,BN层几乎是成了深度网络的必备);

(在Batch-normalized论文中只增加了BN层,而之后的Inception V3的论文提及到的inception v2还做了下面的优化)

⑵ 使用2个3×3的卷积代替梯度(特征图,下同)为35×35中的5×5的卷积,这样既可以获得相同的视野(经过2个3×3卷积得到的特征图大小等于1个5×5卷积得到的特征图),还具有更少的参数,还间接增加了网络的深度,如下图。(基于原则3

figure5

⑶ 3×3的卷积核表现的不错,那更小的卷积核是不是会更好呢?比如2×2。对此,v2在17×17的梯度中使用1*n和n*1这种非对称的卷积来代替n*n的对称卷积,既降低网络的参数,又增加了网络的深度(实验证明,该结构放于网络中部,取n=7,准确率更高),如下。(基于原则3

figure6

⑷ 在梯度为8×8时使用可以增加滤波器输出的模块(如下图),以此来产生高维的稀疏特征。(基于原则2

(原则2指出,在高维特征上,采用这种结构更好,因此该模块用在了8×8的梯度上)

figure7

⑸ 输入从224×224变为229×229。

最后实现的Inception v2的结构如下表。

经过网络的改进,inception v2得到更低的识别误差率,与其他网络识别误差率对比如表所示。

如表,inception v2相比inception v1在imagenet的数据集上,识别误差率由29%降为23.4%。

Inception v3

inception模块之间特征图的缩小,主要有下面两种方式:

右图是先进行inception操作,再进行池化来下采样,但是这样参数量明显多于左图(比较方式同前文的降维后inception模块),因此v2采用的是左图的方式,即在不同的inception之间(35/17/8的梯度)采用池化来进行下采样。

但是,左图这种操作会造成表达瓶颈问题,也就是说特征图的大小不应该出现急剧的衰减(只经过一层就骤降)。如果出现急剧缩减,将会丢失大量的信息,对模型的训练造成困难。(上文提到的原则1

因此,在2015年12月提出的Inception V3结构借鉴inception的结构设计了采用一种并行的降维结构,如下图:

具体来说,就是在35/17/8之间分别采用下面这两种方式来实现特征图尺寸的缩小,如下图:

figure 5′ 35/17之间的特征图尺寸减小
figure 6′ 17/8之间的特征图尺寸缩小

这样就得到Inception v3的网络结构,如表所示。

inception v3

经过优化后的inception v3网络与其他网络识别误差率对比如表所示。

如表所示,在144×144的输入上,inception v3的识别错误率由v1的7.89%降为了4.2%。

此外,文章还提到了中间辅助层,即在网络中部再增加一个输出层。实验发现,中间辅助层在训练前期影响不大,而在训练后期却可以提高精度,相当于正则项。

Inception V4

其实,做到现在,inception模块感觉已经做的差不多了,再做下去准确率应该也不会有大的改变。但是谷歌这帮人还是不放弃,非要把一个东西做到极致,改变不了inception模块,就改变其他的。

因此,作者Christian Szegedy设计了inception v4的网络,将原来卷积、池化的顺次连接(网络的前几层)替换为stem模块,来获得更深的网络结构。stem模块结构如下

stem模块

stem之后的,同v3,是inception模块和reduction模块,如下图

inception v4 中的inception模块(分别为inception A inception B inception C)
inception v4中的reduction模块(分别为reduction A reduction B)

最终得到的inception v4结构如下图。

Inception-ResNet-v2

ResNet(该网络介绍见卷积神经网络结构简述(三)残差系列网络)的结构既可以加速训练,还可以提升性能(防止梯度弥散);Inception模块可以在同一层上获得稀疏或非稀疏的特征。有没有可能将两者进行优势互补呢?

Christian Szegedy等人将两个模块的优势进行了结合,设计出了Inception-ResNet网络。

(inception-resnet有v1和v2两个版本,v2表现更好且更复杂,这里只介绍了v2)

inception-resnet的成功,主要是它的inception-resnet模块。

inception-resnet v2中的Inception-resnet模块如下图

Inception-resnet模块(分别为inception-resnet-A inception-resnet-B inception-resnet-C)

Inception-resnet模块之间特征图尺寸的减小如下图。(类似于inception v4)

inception-resnet-v2中的reduction模块(分别为reduction A reduction B)

最终得到的Inception-ResNet-v2网络结构如图(stem模块同inception v4)。

经过这两种网络的改进,使得模型对图像识别的错误率进一步得到了降低。Inception、resnet网络结果对比如表所示。

如表,Inception V4与Inception-ResNet-v2网络较之前的网络,误差率均有所下降。

3、Resnet

ResNet网络是在2015年由微软实验室提出,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名。获得COCO数据集中目标检测第一名,图像分割第一名。下图是ResNet34层模型的结构简图。

在ResNet网络中有如下几个亮点:

(1)提出residual结构(残差结构),并搭建超深的网络结构(突破1000层)

(2)使用Batch Normalization加速训练(丢弃dropout)

在ResNet网络提出之前,传统的卷积神经网络都是通过将一系列卷积层与下采样层进行堆叠得到的。但是当堆叠到一定网络深度时,就会出现两个问题。1)梯度消失或梯度爆炸。 2)退化问题(degradation problem)。在ResNet论文中说通过数据的预处理以及在网络中使用BN(Batch Normalization)层能够解决梯度消失或者梯度爆炸问题。如果不了解BN层可参考这个链接。但是对于退化问题(随着网络层数的加深,效果还会变差,如下图所示)并没有很好的解决办法。

4、DenseNet

DenseNet模型,它的基本思路与ResNet一致,但是它建立的是前面所有层与后面层的密集连接(dense connection),它的名称也是由此而来。DenseNet的另一大特色是通过特征在channel上的连接来实现特征重用(feature reuse)。这些特点让DenseNet在参数和计算成本更少的情形下实现比ResNet更优的性能,DenseNet也因此斩获CVPR 2017的最佳论文奖.

相比ResNet,DenseNet提出了一个更激进的密集连接机制:即互相连接所有的层,具体来说就是每个层都会接受其前面所有层作为其额外的输入。图1为ResNet网络的连接机制,作为对比,图2为DenseNet的密集连接机制。可以看到,ResNet是每个层与前面的某层(一般是2~3层)短路连接在一起,连接方式是通过元素级相加。而在DenseNet中,每个层都会与前面所有层在channel维度上连接(concat)在一起(这里各个层的特征图大小是相同的),并作为下一层的输入。

图1 ResNet网络的短路连接机制(其中+代表的是元素级相加操作)
图2 DenseNet网络的密集连接机制(其中c代表的是channel级连接操作)
 DenseNet的网络结构

5、MobileNet

MobileNet的基本单元是深度级可分离卷积(depthwise separable convolution),其实这种结构之前已经被使用在Inception模型中。深度级可分离卷积其实是一种可分解卷积操作(factorized convolutions),其可以分解为两个更小的操作:depthwise convolution和pointwise convolution,如图1所示。Depthwise convolution和标准卷积不同,对于标准卷积其卷积核是用在所有的输入通道上(input channels),而depthwise convolution针对每个输入通道采用不同的卷积核,就是说一个卷积核对应一个输入通道,所以说depthwise convolution是depth级别的操作。而pointwise convolution其实就是普通的卷积,只不过其采用1×1的卷积核。图2中更清晰地展示了两种操作。对于depthwise separable convolution,其首先是采用depthwise convolution对不同输入通道分别进行卷积,然后采用pointwise convolution将上面的输出再进行结合,这样其实整体效果和一个标准卷积是差不多的,但是会大大减少计算量和模型参数量。

前面讲述了depthwise separable convolution,这是MobileNet的基本组件,但是在真正应用中会加入batchnorm,并使用ReLU激活函数,所以depthwise separable convolution的基本结构如图3所示。

加入BN和ReLU的depthwise separable convolution

MobileNet的网络结构如表1所示。首先是一个3×3的标准卷积,然后后面就是堆积depthwise separable convolution,并且可以看到其中的部分depthwise convolution会通过strides=2进行down sampling。然后采用average pooling将feature变成1×1,根据预测类别大小加上全连接层,最后是一个softmax层。如果单独计算depthwise
convolution和pointwise convolution,整个网络有28层(这里Avg Pool和Softmax不计算在内)。我们还可以分析整个网络的参数和计算量分布,如表2所示。可以看到整个计算量基本集中在1×1卷积上,如果你熟悉卷积底层实现的话,你应该知道卷积一般通过一种im2col方式实现,其需要内存重组,但是当卷积核为1×1时,其实就不需要这种操作了,底层可以有更快的实现。对于参数也主要集中在1×1卷积,除此之外还有就是全连接层占了一部分参数。

MobileNetv2

MobileNetv2相比v1的两个主要改进:linear bottleneck和inverted residual。

v2的加入了1×1升维,引入Shortcut并且去掉了最后的ReLU,改为Linear。步长为1时,先进行1×1卷积升维,再进行深度卷积提取特征,再通过Linear的逐点卷积降维。将input与output相加,形成残差结构。步长为2时,因为input与output的尺寸不符,因此不添加shortcut结构,其余均一致。

preview

首先利用3×3的深度可分离卷积提取特征,然后利用1×1的卷积来扩张通道。用这样的block堆叠起来的MobileNetV1既能较少不小的参数量、计算量,提高网络运算速度,又能的得到一个接近于标准卷积的还不错的结果,看起来是很美好的。

但是!

有人在实际使用的时候, 发现深度卷积部分的卷积核比较容易训废掉:训完之后发现深度卷积训出来的卷积核有不少是空的.

这是为什么?

作者认为这是ReLU这个浓眉大眼的激活函数的锅。(没想到你个浓眉大眼的ReLU激活函数也叛变革命了???)

针对这个问题,可以这样解决:既然是ReLU导致的信息损耗,将ReLU替换成线性激活函数。我们当然不能把所有的激活层都换成线性的啊,所以我们就悄咪咪的把最后的那个ReLU6换成Linear。作者将这个部分称之为linear bottleneck。对,就是论文名中的那个linear bottleneck。

现在还有个问题是,深度卷积本身没有改变通道的能力,来的是多少通道输出就是多少通道。如果来的通道很少的话,DW深度卷积只能在低维度上工作,这样效果并不会很好,所以我们要“扩张”通道。既然我们已经知道PW逐点卷积也就是1×1卷积可以用来升维和降维,那就可以在DW深度卷积之前使用PW卷积进行升维(升维倍数为t,t=6),再在一个更高维的空间中进行卷积操作来提取特征

也就是说,不管输入通道数是多少,经过第一个PW逐点卷积升维之后,深度卷积都是在相对的更高6倍维度上进行工作。

回顾V1的网络结构,我们发现V1很像是一个直筒型的VGG网络。我们想像Resnet一样复用我们的特征,所以我们引入了shortcut结构,这样V2的block就是如下图形式:

对比一下V1和V2:

可以发现,都采用了 1×1 -> 3 ×3 -> 1 × 1 的模式,以及都使用Shortcut结构。但是不同点呢:

  • ResNet 先降维 (0.25倍)、卷积、再升维。
  • MobileNetV2 则是 先升维 (6倍)、卷积、再降维。

刚好V2的block刚好与Resnet的block相反,作者将其命名为Inverted residuals。就是论文名中的Inverted residuals

6、EfficientNet

该论文提出了一种新的模型缩放方法,它使用一个简单而高效的复合系数来以更结构化的方式放大 CNNs。 不像传统的方法那样任意缩放网络维度,如宽度,深度和分辨率,该论文的方法用一系列固定的尺度缩放系数来统一缩放网络维度。 通过使用这种新颖的缩放方法和 AutoML[5] 技术,作者将这种模型称为 EfficientNets ,它具有最高达10倍的效率(更小、更快)。

模型扩展的有效性在很大程度上依赖于baseline网络。为了进一步提高性能,作者还开发了一个新的基线网络,通过使用 AutoML MNAS 框架执行神经结构搜索,优化了准确性和效率。 最终的架构使用移动反向bottleneck卷积(MBConv) ,类似于 mobileenetv2和 MnasNet。

移动翻转瓶颈卷积(mobile inverted bottleneck convolution,MBConv),类似于 MobileNetV2 和 MnasNet,由深度可分离卷积Depthwise Convolution和SENet构成。

每个MBConv的网络结构如下:
MBConv = 1×1升维 + Depthwise Convolution + SENet + 1×1降维 + add
在这里插入图片描述

SENet

该网络为压缩与激发网络(Squeeze-and-Excitation Network,SENet),即注意力机制。该思想由Momenta公司提出,并发于2017CVPR。SENet网络的创新点在于关注channel之间的关系,希望模型可以自动学习到不同channel特征的重要程度。

其中第一个FC层降维,降维系数为r,然后ReLU激活,最后的FC层恢复原始的维度。
在这里插入图片描述
SENet添加位置示意:
在这里插入图片描述
代码实现

7、RegNet

本文的基本贡献有三方面。

  • 提出了设计空间的设计原则。
  • 根据这些原则,一个有效的设计空间被引入(RegNet)
  • 介绍了一组SoTA网络(RegNetX和RegNetY)。

我们首先设计了一个 AnyNet,它包含三个部分

  1. Stem 一个简单的网络输入头
  2. body 网络中主要的运算量都在这里
  3. head 用于预测分类的输出头
模型网络结构设计

我们将 stem 和 head 固定下来,并专注于网络 body 设计。因为 body 部分的参数量最多,运算量也多,这部分是决定网络准确性的关键

而 Body 结构,通常包含 4 个 stage,每个 stage 都会进行降采样。而 1 个 stage 是由多个 block 进行堆叠得到的

论文中,我们的 Block 采取的是带有组卷积的残差 BottleNeck Block(即 ResNext 里的结构),我们称在这样 Block 限制条件下的搜索空间为 AnyNetX ,Block 的结构如下:

带有组卷积的残差BottleNeck Block

此时 AnyNetX 中有 16 个自由度可以设计,包含了 4 个 stage,每个 stage 有 4 个 Block 参数:

  • block 的数目 di
  • block 的宽度 wi
  • Bottleneck 的通道缩放比例 bi
  • 分组数目 gi

此时我们在这样的条件下进行采样,缩小网络设计空间:

  • di ≤ 16
  • wi ≤ 1024 (其中 wi 可被 8 整除)
  • bi ∈ {1, 2, 4}
  • gi ∈ {1, 2, . . . , 32}

因此我们在 AnyNetX 衍生出其他搜索空间

  • AnyNetXa 就是原始的 AnyNetX
  • AnyNetXb 在 AnyNetX 基础上,每个 stage 使用相同的 Bottleneck 缩放比例 bi。并且实验得出缩放比例 bi <= 2 时最佳,参考下图最右边子图
对AnyNetXb和AnyNetXc的分析
  • AnyNetXc 在 AnyNetXb 的基础上共享相同的分组数目 gi。由上图的左图和中间图可得知,从 A->C 的阶段,EDF 并没有受到影响,而我们此时已经减少了
  • AnyNetXd 在 AnyNetXc 的基础上逐步增加 Block 的宽度 wi。此时网络性能有明显提升!

AnyNetXd

  • AnyNetXe 在 AnyNetXd 的基础上在除了最后一个 stage 上,逐步增加 Block 的数量(深度)di。网络性能略微有提升
AnyNetXe

Swin Transformer v2

paper:https://arxiv.org/pdf/2111.09883.pdf

Swin Transformer V2: Scaling Up Capacity and Resolution扩展容量和分辨率

Transformer 是 Google 的团队在 2017 年提出的一种 NLP 经典模型,现在比较火热的 Bert 也是基于 Transformer。Transformer 模型使用了 Self-Attention 机制,不采用 RNN 的顺序结构,使得模型可以并行化训练,而且能够拥有全局信息。

本文介绍这篇文章是 Swin Transformer 系列的升级版 Swin Transformer v2。Swin Transformer 是屠榜各大CV任务的通用视觉Transformer模型,它在图像分类、目标检测、分割上全面超越 SOTA,在语义分割任务中在 ADE20K 上刷到 53.5 mIoU,超过之前 SOTA 大概 4.5 mIoU!可能是CNN的完美替代方案。除此之外,本文一并介绍 Swin MLP 的代码实现,Swin Transformer 作者们在已有模型的基础上实现了 Swin MLP 模型,证明了 Window-based attention 对于 MLP 模型的有效性。

Swin Transformer Block 有两种,大致结构和 Transformer Block 一致,只是内部 attention 模块分别是 Window-based MSA 和 Shifted Window-based MSA。Window-based MSA 不同于普通的 MSA,它在一个个 window 里面去计算 self-attention,计算量与序列长度 N=hw 成线性关系。Window-based MSA 虽然大幅节约了计算量,但是牺牲了 windows 之间关系的建模,不重合的 Window 之间缺乏信息交流影响了模型的表征能力。Shifted Window-based MSA 就是为了解决这个问题。将下一层 Swin Transformer Block 的 Window 位置进行移动,得到不重合的 patch。

在 Swin Transformer 的基础上,研究人员进一步开发出了用于底层复原任务的 SwinIR

Swin Transformer v2 原理分析:

Swin Transformer 提出了一种针对视觉任务的通用的 Transformer 架构,MSRA 进一步打造了一个包含3 billion 个参数,且允许输入分辨率达到1560×1560的大型 Swin Transformer,称之为 SwinV2。它在多个基准数据集 (包含 ImageNet 分类、COCO 检测、ADE20K 语义分割以及Kinetics-400 动作分类) 上取得新记录,分别是 ImageNet 图像分类84.0% Top-1 accuracy,COCO 目标检测63.1/54.4 box / mask mAP,ADE20K 语义分割59.9mIoU,Kinetics-400视频动作识别86.8% Top-1 accuracy。

Swin Transformer v2 的核心目的是把 Swin Transformer 模型做大,做成类似 BERT large 那样包含 340M 参数的预训练大模型。在 NLP 中,有的预训练的大模型,比如 Megatron-Turing-530B 或者 Switch-Transformer-1.6T,参数量分别达到了530 billion 或者1.6 trillion。

另一方面,视觉大模型的发展却滞后了。 Vision Transformer 的大模型目前也只是达到了1-2 billion 的参数量,且只支持图像识别任务。部分原因是因为在训练和部署方面存在以下困难:

  • 问题1:训练中的不稳定性问题。在大型模型中,跨层激活函数输出的幅值的差异变得更大。激活值是逐层累积的,因此深层的幅值明显大于浅层的幅值。如下图1所示是扩大模型容量时的不稳定问题。 当我们将原来的 Swin Transformer 模型从小模型放大到大模型时,深层的 activation 值急剧增加。最高和最低幅值之间的差异达到了104。当我们进一步扩展到一个巨大的规模 (658M 参数) 时,它不能完成训练,如图2所示。
图1:扩大模型容量时的不稳定问题
图2:使用 Pre-Norm,当进一步扩展到一个巨大的规模 (658M 参数) 时不能完成训练。
  • 问题2:许多下游视觉任务需要高分辨率的图像或窗口,预训练模型时是在低分辨率下进行的,而 fine-tuning 是在高分辨率下进行的。针对分辨率不同的问题传统的做法是把位置编码进行双线性插值 (bi-cubic interpolation),这种做法是次优的。如下图3所示是不同位置编码方式性能的比较,当我们直接在较大的图像分辨率和窗口大小测试预训练的 Imagenet-1k 模型 (分辨率256×256,window siez=8×8) 时,发现精度显着下降。
图3:不同位置编码方式性能的比较
  • 问题3:当图像分辨率较高时,GPU 内存消耗也是一个问题。

为了解决以上几点问题,作者提出了:

方法1:post normalization 技术:解决训练中的不稳定性问题

把 Layer Normalization 层放在 Attention 或者 MLP 的后面。这样每个残差块的输出变化不至于太大,因为主分支和残差分支都是 LN 层的输出,有 LN 归一化作用的限制。如上图1所示,这种做法使得每一层的输出值基本上相差不大。在最大的模型训练中,作者每经过6个 Transformer Block,就在主支路上增加了一层 LN,以进一步稳定训练和输出幅值。

图4:Swin v2 相对于 Swin Transformer 的改进 (红色部分)

方法2:scaled cosine attention 技术:解决训练中的不稳定性问题

原来的 self-attention 计算中,query 和 key 之间的相似性通过 dot-product 来衡量,作者发现这样学习到的 attention map 往往被少数像素对所支配。所以把 dot-product 改成了 cosine 函数,通过它来衡量 query 和 key 之间的相似性。

\[\operatorname{Sim}\left(\mathbf{q}i, \mathbf{k}_j\right)=\cos \left(\mathbf{q}_i, \mathbf{k}_j\right) / \tau+B{i j}\]
式中, \(B_{i j}\) 是下面讲得相对位置编码, \(\tau\) 是可学习参数。余弦函数是 naturally normalized,因 此可以有较温和的注意力值。

方法3:对数连续位置编码技术:解决分辨率变化导致的位置编码维度不一致问题。

  • 该方法可以 更平滑地传递在低分辨率下预先训练好的模型权值,以处理高分辨率的模型权值。
    我们首先复习下 Swin Transformer 的相对位置编码技术。
    \[\operatorname{Attention}(Q, K, V)=\operatorname{SoftMax}\left(Q K^T / \sqrt{d}+B\right) V\]
    式中, \(B \in \mathbb{R}^{M^2 \times M^2}\) 是每个 head 的相对位置偏差项 (relative position bias),\(Q, K, V \in \mathbb{R}^{M^2 \times d}\) 是 window-based attention 的 query, key 和 value。 window 的大小。

作者引入对数空间连续位置偏差 (log-spaced continuous position bias),使相对位置偏差在不同的 window 分辨率之下可以较为平滑地过渡。

方法4:节省 GPU memory 的方法:

1 Zero-Redundancy Optimizer (ZeRO) 技术:

来自论文:Zero: Memory optimizations toward training trillion parameter models

传统的数据并行训练方法 (如 DDP) 会把模型 broadcast 到每个 GPU 里面,这对于大型模型来讲非常不友好,比如参数量为 3,000M=3B 的大模型来讲,若使用 AdamW optimizer,32为的浮点数,就会占用 48G 的 GPU memory。通过使用 ZeRO optimizer, 将模型参数和相应的优化状态划分并分布到多个 GPU 中,从而大大降低了内存消耗。训练时使用 DeepSpeed framework,ZeRO stage-1 option。

2 Activation check-pointing 技术:

来自论文:Training deep nets with sublinear memory cost

Transformer 层中的特征映射也消耗了大量的 GPU 内存,在 image 和 window 分辨率较高的情况下会成为一个瓶颈。这个优化最多可以减少30%的训练速度。

3 Sequential self-attention computation 技术:

在非常大的分辨率下训练大模型时,如分辨率为1535×1536,window size=32×32时,在使用了上述两种优化策略之后,对于常规的 GPU (40GB 的内存)来说,仍然是无法承受的。作者发现在这种情况下,self-attention 模块构成了瓶颈。为了解决这个问题,作者实现了一个 sequential 的 self-attention 计算,而不是使用以前的批处理计算方法。这种优化在前两个阶段应用于各层,并且对整体的训练速度有一定的提升。

在这项工作中,作者还一方面适度放大 ImageNet-22k 数据集5倍,达到7000万张带有噪声标签的图像。 还采用了一种自监督学习的方法来更好地利用这些数据。通过结合这两种策略,作者训练了一个30亿参数的强大的 Swin Transformer 模型刷新了多个基准数据集的指标,并能够将输入分辨率提升至1536×1536 (Nvidia A100-40G GPUs)。此外,作者还分享了一些 SwinV2 的关键实现细节,这些细节导致了 GPU 内存消耗的显着节省,从而使得使用常规 GPU 来训练大型视觉模型成为可能。 作者的目标是在视觉预训练大模型这个方向上激发更多的研究,从而最终缩小视觉模型和语言模型之间的容量差距。

不同 Swin V2 的模型配置:

  • SwinV2-T: C= 96, layer numbers ={2,2,6,2}
  • SwinV2-S: C= 96, layer numbers ={2,2,18,2}
  • SwinV2-B: C= 128, layer numbers ={2,2,18,2}
  • SwinV2-L: C= 192, layer numbers ={2,2,18,2}
  • SwinV2-H: C= 352, layer numbers ={2,2,18,2}
  • SwinV2-G: C= 512, layer numbers ={2,2,42,2}

对于 SwinV2-H 和 SwinV2-G 的模型训练,作者每经过6个 Transformer Block,就在主支路上增加了一层 LN,以进一步稳定训练和输出幅值。

Experiments

模型:SwinV2-G,3B parameters

Image classification

Dataset for Evaluation:ImageNet-1k,ImageNet-1k V2

Dataset for Pre-Training:ImageNet-22K-ext (70M images, 22k classes)

训练策略:分辨率使用192×192,为了节约参数量。2-step 的预训练策略。首先以自监督学习的方式在 ImageNet-22K-ext 数据集上训练 20 epochs,再以有监督学习的方式在这个数据集上训练 30 epochs,SwinV2-G 模型在 ImageNet-1k 上面达到了惊人的90.17%的 Top-1 Accuracy,在 ImageNet-1k V2 上面也达到了惊人的84.00%的 Top-1 Accuracy,超过了历史最佳的83.33%。

图5:Image classification 实验结果

同时,使用 Swin V2 的训练策略以后,Base 模型和 Large 模型的性能也可以进一步提升。比如 SwinV2-B 和 SwinV2-L 在 SwinV1-B 和 SwinV1-L 的基础上分别涨点0.8%和0.4%,原因来自更多的 labelled data (ImageNet-22k-ext, 70M images), 更强的 Regularization,或是自监督学习策略。

Object detection,Instance Segmentation

Dataset for Evaluation:COCO

Dataset for Pre-Training:Object 365 v2

如下图6所示 SwinV2-G 模型与之前在 COCO 目标检测和实例分割任务上取得最佳性能模型进行了比较。SwinV2-G 在 COCO test-dev 上实现了 63.1/54.4 box/max AP,相比于 SoftTeacher (61.3/53.0) 提高了 + 1.8/1.4。

图6:COCO 目标检测和实例分割任务

Semantic segmentation

Dataset for Evaluation:ADE20K

如下图7所示 SwinV2-G 模型与之前在 ADE20K 语义分割基准上的 SOTA 结果进行了比较。Swin-V2-G 在 ADE20K val 集上实现了 59.9 mIoU,相比于 BEiT 的 58.4 高了 1.5。

图7:ADE20k语义分割任务

Video action classification

Dataset for Evaluation:Kinetics-400 (K400)

如下图8所示 SwinV2-G 模型与之前在 Kinetics-400 动作分类基准上的 SOTA 结果进行了比较。可以看到,Video-SwinV2-G 实现了 86.8% 的 top-1 准确率,比之前的 TokenLearner 方法的 85.4% 高出 +1.4%。

图8:K400视频动作分类任务

对比实验:post-norm 和 scaled cosine attention 的作用

如下图9所示,这两种技术均能提高 Swin-T,Swin-S 和 Swin-B 的性能,总体提高分别为 0.2%,0.4% 和 0.5%。说明该技术对大模型更有利。更重要的是,它们能让训练更稳定。对于 Swin-H 和 Swin-G 模型而言,自监督预训练使用原来的 Swin V1 无法收敛,而 Swin V2 模型训练得很好。

图9:post-norm 和 scaled cosine attention 对比实验结果

PointRend –图像细颗粒分割

title
https://arxiv.org/abs/1912.08193

论文地址: https://arxiv.org/abs/1912.08193

gitlab: https://github.com/zsef123/PointRend-PyTorch

存在的问题

在目前的语义分割网络中存在的问题主要有过采样和现采样。

1.过采样( oversample ):对于图片中低频区域( 属于同一个物体 ),没必要使用 太多的采样点,却使用太多采样点造成过采样;

2.欠采样( undersample ) :对于图片中高频区域( 靠近物体边界 ),如果这些区域的采样过于稀疏,导致分割出的边界过于平滑,不大真实

文章要解决的问题是在实例分割任务中边缘不够精细的问题。以MaskRCNN举例,由于计算量和显存的原因,对于每一个ROIAlign之后的proposal我们一般只会upsample到28*28的分辨率输出mask。这对于绝大多数物体显然是不够的。如果想得到像素级别的精度,我们不得不付出更大的计算和存储代价。那有什么办法可以在低代价下仍然得到精细的分割结果呢?其实很重要的一点是往往这些不准确的部分是在物体的边缘,这些边缘其实只占了整个物体中非常小的一部分。所以基于这样的一个想法,作者提出可以每次在预测出来的mask中只选择Top N最不确定的位置进行细分预测。每个细分点的特征可以通过Bilinear插值得到,每个位置上的classifier通过一个简单的MLP来实现。这其实是等价于用一个1*1的conv来预测,但是对于中心很确定的点并不计算。整体的示意图如下:

PointRend 解决了什么问题?

这篇论文讲了一个很好听的故事,即:把语义分割以及实例分割问题(统称图像分割问题)当做一个渲染问题来解决。故事虽然这么讲,但本质上这篇论文其实是一个新型上采样方法,针对物体边缘的图像分割进行优化,使其在难以分割的物体边缘部分有更好的表现

作为一个小白,那么问题来了:

1、什么是渲染?

2、为什么要把图像分割问题当做渲染问题呢?

要想知道什么是渲染,可以参考:

计算机中所说的「渲染」是什么意思?

简单来说,渲染就是“绘制”,把3D的物体在2D平面上绘制出来。

为什么要把图像分割问题和渲染问题扯在一起呢?因为讲故事好听啊,论文好写嘛….咳咳…不不,是因为二者有类似的问题要解决:即物体边缘难以处理。

具体来说,在图像渲染中,对于多个3D物体,在边缘要判断对于镜头而言谁先谁后,而且还得抗锯齿;而对于图像分割问题,边缘恢复也一直是个麻烦事儿,因为在典型的语义分割网络中(如FCN、DeepLab),在CNN内部一般都会相对输入图像降采样16倍,然后再想办法上采样回去。更细致地说,对于 DeepLabV3+,模型最后直接是一个4倍的双线性插值上采样,这显然对物体边缘的预测十分不利。虽然 DeepLabV3+当时在2017年就达到了秒天秒地的 89%mIoU on VOC2012 test (使用了300M JFT 数据集预训练),至今无人超越(因为JFT 数据集 Google没有公开 \手动滑稽),但显然这个上采样过程仍然存在较大的提升空间。

参考链接:Uno Whoiam:DeepLab 语义分割模型 v1、v2、v3、v3+ 概要(附 Pytorch 实现)

而在实例分割网络中,Mask R-CNN 这货生成的 Mask 才 28×28,要是把这样的 mask 拉伸到 不说多了比如 256×256,还指望它可以很好地预测边缘?我只能说这是在想Peach。

事实上,在图像分割任务上边缘预测不理想这个情况其实在许多前人的工作中都有提及,比如 Not All Pixels Are Equal: Difficulty-Aware Semantic Segmentation via Deep Layer Cascade 中就详细统计了语义分割中,模型最容易误判的 pixel基本上都在物体边缘(如下图右上红色部分标记) 。

而关于上采样其实也有一些前人的工作,如 Decoders Matter for Semantic Segmentation: Data-Dependent Decoding Enables Flexible Feature Aggregation,在实现上有点像超分辨率网络 ESPCN 里使用的 sub-pixel convolutional layer 的操作,不过多加了一个二阶范数约束:

总的来说,图像分割边缘预测是一个未被很好解决的问题,而何恺明团队的 PointRend 是对此问题的一个新的思路和解法,接下来将介绍 PointRend 是如何 work 的。

文主要贡献

1.提出可嵌入主流网络的PointRend模块,提高了图像分割精度。

2.把图像分割问题看作渲染问题,本质上是一个新型上采样方法,为图像分割提供独特视角。

3.降低了训练所需的算力。输出224×224分辨率图像,PointRend只需0.9B FLOPs。

二、总体思路

PointRend 方法要点总结来说是一个迭代上采样的过程:

while 输出的分辨率 < 图片分辨率:

  1. 对输出结果进行2倍双线性插值上采样得到 coarse prediction_i。(粗分辨率预测)
  2. 挑选出 N 个“难点”,即结果很有可能和周围点不一样的点(例如物体边缘)。
  3. 对于每个难点,获取其“表征向量”,“表征向量”由两个部分组成,其一是低层特征(fine-grained features),通过使用点的坐标,在低层的特征图上进行双线性插值获得(类似 RoI Align),其二是高层特征(coarse prediction),由步骤 1 获得。
  4. 使用 MLP 对“表征向量”计算得到新的预测,更新 coarse prediction_i 得到 coarse prediction_i+1。这个 MLP 其实可以看做一个只对“难点”的“表征向量”进行运算的由多个 conv1x1 组成的小网络。

整个过程可以这么理解:

小明同学做题,现在有已知条件(coarse prediction_0,fine-grained features),想求解答案(coarse prediction_k),发现直接求(双线性插值or其它方法)不够准确,那就一步一步来吧(从coarse prediction_1,coarse prediction_2….求到coarse prediction_k)。好的,现在求coarse prediction_1,诶,发现有好多东西不知道,不能从 coarse prediction_0 直接得到怎么办?那就找出不知道的(“难点”),在 fine-grained features 里面找出对应的线索(ROIAlign-like 双线性插值),然后在结合 coarse prediction_0 得到整体线索(“特征向量”)求解(使用MLP计算),嗯,终于得到 coarse prediction_1了。再用同样的思路反复求解,直到 coarse prediction_k。

示意图如下:

对于一个coarse prediction(4×4大小),将其上采样两倍(8×8大小,这里可以理解为检测头的输出)后,取了一些难分割的点(大多是边缘部分),取这些点的特征向量输入到MLP网络中,进行point prediction,得到每一个点的新类别,最后结果输出(8×8大小,边缘更加精确的结果)。

另外,其PointRend 训练为了节省时间,没有使用上述的迭代过程,而是使用多种组合的采样方法,不赘述,详见paper。

  1. 从PointRend的应用思路中可以看到,这里包含了两个阶段的特征处理,分别是fine-grained features和coarse prediction部分,如果主干网络是ResNet,那么fine-grained features就是ResNet的stage2输出,也就是4倍下采样时的精细分割结果,而coarse prediction就是检测头的预测结果(还未上采样还原成原图的结果)。
  2. 从coarse prediction中挑选N个“难点”,也就是结果很有可能和周围点不一样的点(比如物体边缘的点)。对于每一个难点,获取他的“特征向量”,对于点特征向量(point features),主要由两部分组成,分别是fine-grained features的对应点和coarse prediction的对应点的特征向量,将这个两个特征向量拼接成一个向量。
  3. 接着,通过一个MLP网络对这个“特征向量”进行预测,更新coarse prediction。也就相当于对这个难点进行新的预测,对他进行分类。

看完这个,我们就可以这么理解,将预测难的点(边缘点)提取出来,再提取其特征向量,经过MLP网络,将这个点的归属进行分类,然后提升这些点的分类准确率。这就是PointRend的思想。

一个PointRend模块包括三部分

1.point selection strategy:用于inference和traing的点选择

对于点采样过程,需要对模型的Train过程和Inference过程做区分

该方法的核心思想是灵活自适应地选择图像平面上的点来预测分割标签。直观地说,这些点应该更密集地位于高频区域附近,例如物体边界,类似于射线追踪中的反混叠问题。我们产生了推理训练的想法。

  • inference推理

通过仅在与其邻域有显着不同的位置进行计算,该方法可用于有效地渲染高分辨率图像(例如,通过光线跟踪)。对于所有其他位置,通过对已经计算的输出值(从粗网格开始)进行插值来获得值。

对于每个区域,我们以粗到精的方式迭代地“渲染”输出蒙版。在规则网格上的点上进行最粗糙级别的预测(例如,通过使用标准的粗糙分段预测头)。在每次迭代中,PointRend使用双线性插值对其先前预测的分段进行上采样,然后在此较密集的网格上选择N个最不确定的点(例如,对于二进制掩码,概率最接近0.5的那些)。然后,PointRend为这N个点中的每一个点计算特征,并预测它们的标签。重复该过程,直到将分段上采样到所需的分辨率为止。

  • training

对于Train过程的点采样操作,同样可以遵循Inference中的操作。但是作者发现,这样子采样对于梯度的传播不太友好,于是只能被迫选择其他的点采样策略——干脆就用随机采样的方式来进行采样。

在训练过程中,PointRend还需要选择一些点,以在这些点上构建用于训练point head的逐点(point-wise)特征。原则上,点选择策略可以类似于推理inference中使用的细分策略。但是,细分引入了一系列步骤,这些步骤对于通过反向传播训练神经网络不太友好。取而代之的是,为了训练,我们使用基于随机采样的非迭代策略

采样策略在特征图上选择N个点进行训练。它旨在使用三个原理将选择偏向不确定区域,同时还保留一定程度的均匀覆盖。对于训练和推理选择,N的值可以不同。

(i)过度生成:我们通过从均匀分布中随机采样kN个点(k> 1)来过度生成候选点。(ii)重要抽样:通过对所有kN个点的粗略预测值进行插值并计算任务特定的不确定性估计,我们将重点放在具有粗略预测的点上。从kN个候选中选择最不确定的βN个点(β∈[0,1])。(iii)覆盖范围:从均匀分布中采样剩余的(1-β)N点。我们用不同的设置来说明此过程,并将其与常规的网格选择进行比较,如下图所示。

在训练时,预测和损失函数仅在N个采样点上计算(除粗略分割外),这比通过细分步骤进行反向传播更简单,更有效。这种设计类似于在Faster R-CNN系统中对RPN + Fast R-CNN的并行训练,其推理是顺序的。

2. Point-wise Representation:逐点表示

PointRend通过组合(例如,级联)两种特征类型(细粒度和粗略预测特征)在选定点上构造逐点特征,如下所述。

  • 细粒度特征

为了允许PointRend呈现精细的分割细节,我们从CNN特征图中提取每个采样点的特征向量。 因为一个点是“实值2D坐标”,所以我们按照标准做法对特征图执行双线性插值,以计算特征向量。 可以从单个特征图中提取特征(例如,ResNet中的res2);也可以按照Hypercolumn方法,从多个特征图(例如res2到res5)中提取并连接它们。

  • 粗预测特征

细粒度的特征可以解析细节,但在两个方面也有不足:

首先,它们不包含特定区域的信息,因此,两个实例的边界框重叠的相同点将具有相同的细粒度特征。但是,该点只能位于一个实例之中。 因此,对于实例分割的任务,其中不同的区域可能针对同一点预测不同的标签,因此需要其他区域特定的信息。

其次,取决于用于细粒度特征的特征图,这些特征可能只包含相对较低级别的信息(例如,我们将对res2使用DeepLabV3)。 因此,需要有更多具有上下文和语义信息的特征。

基于这两点考虑,第二种特征类型是来自网络的粗分割预测,例如表示k类预测的区域(box)中每个点的k维向量。通过设计,粗分辨率能够提了更加全局的上下文信息,而通道则传递语义类别。这些粗略的预测与现有架构的输出相似,并且在训练过程中以与现有模型相同的方式进行监督。例如,在mask R-CNN中,粗预测可以是一个轻量级的7×7分辨率Mask头的输出。

点特征向量(point features),主要由两部分组成,分别是fine-grained features的对应点和coarse prediction的对应点的特征向量,将这个两个特征向量拼接成一个向量

3. point head

给定每个选定点的逐点特征表示,PointRend使用简单的多层感知器(MLP)进行逐点分割预测。这个MLP在所有点(和所有区域)上共享权重,类似于图卷积或PointNet。由于MLP会预测每个点的分割标签,因此可以通过特定任务的分割loss进行训练。

三、效果如何?

实验结果

  • 网络设计

实验使用ResNet-50+ FPN 的Mask-Rcnn作backbone。 Mask-RCNN中的默认head是region-wise FCN,用“ 4×conv”表示,作为用来与本文网络进行比较的基准网络。

为了计算粗略预测,我们用重量更轻的设计替换4×conv Mask头,该设计类似于Mask R-CNN的box head产生7×7Mask预测。具体来说,对于每个边界框,我们使用双线性插值从FPN的P2层提取14×14特征图。这些特征是在边界框内的规则网格上计算的(此操作可以看作是RoIAlign的简单版本)。接下来,我们使用具有256个输出通道步幅为2的 2×2卷积层,后跟ReLU, 将空间大小减小到7×7。最后,类似于Mask R-CNN的box head,用两个带1024宽的隐藏层的MLP为K类分别产生7×7的Mask预测。ReLU用于MLP的隐藏层,并且Sigmoid激活函数应用于输出。

PointRend:在每个选定点上,使用双线性插值从粗预测头的输出中提取K维特征向量,PointRend还从FPN的P2级别插值256维特征向量,步长为4。这些粗预测和细粒度特征向量是串联在一起的,我们使用具有256个通道的3个隐藏层的MLP在选定点进行K类别预测。在MLP的每个层中,我们用K个粗预测特征补充到256个输出通道中,作为下一层输入向量。在MLP中使用ReLU,并将Sigmoid激活函数应用于输出。

不得不说这个针对物体边缘进行优化的上采样方法的确在感官上和数据上都有很不错的效果:

语义分割结果:

实例分割结果(基于MaskR-CNN):

PointRend的一些代码和实现

摘自: https://chowdera.com/2022/194/202207120607167479.html

代码详解: https://www.361shipin.com/blog/1536592971120508928

  • 作者提出可以在预测出来的mask中只选择Top N最不确定的位置进行细分预测。

具体为先根据粗糙预测出来的mask,将mask按类别预测分数排序,选出分数高的前2 类别的mask,计算出在2个类别mask上均有较高得分的Top K个像素点作为K 个不确定点【1个像素点只能对应1个类别,如果它对应2个类别的分数都很高,说明它很可能是边界点,也是不确定的】

def sampling_points(mask, N, k=3, beta=0.75, training=True):
    """
    主要思想:根据粗糙的预测结果,找出不确定的像素点
    :param mask: 粗糙的预测结果(out)   eg.[2, 19, 48, 48]
    :param N: 不确定点个数(train:N = 图片的尺寸/16, test: N = 8096)    eg. N=48
    :param k: 超参
    :param beta: 超参
    :param training:
    :return: 不确定点的位置坐标  eg.[2, 48, 2]
    """
    assert mask.dim() == 4, "Dim must be N(Batch)CHW"   #this mask is out(coarse)
    device = mask.device
    B, _, H, W = mask.shape   #first: mask[1, 19, 48, 48]
    mask, _ = mask.sort(1, descending=True) #_ : [1, 19, 48, 48],按照每一类的总体得分排序
    if not training:
        H_step, W_step = 1 / H, 1 / W
        N = min(H * W, N)
        uncertainty_map = -1 * (mask[:, 0] - mask[:, 1])
        #mask[:, 0]表示每个像素最有可能的分类,mask[:, 1]表示每个像素次有可能的分类,当一个像素
        #即是最有可能的又是次有可能的,则证明它不好预测,对应的uncertainty_map就相对较大
        _, idx = uncertainty_map.view(B, -1).topk(N, dim=1) #id选出最不好预测的N个点
        points = torch.zeros(B, N, 2, dtype=torch.float, device=device)
        points[:, :, 0] = W_step / 2.0 + (idx  % W).to(torch.float) * W_step    #点的横坐标
        points[:, :, 1] = H_step / 2.0 + (idx // W).to(torch.float) * H_step    #点的纵坐标
        return idx, points  #idx:48 || points:[1, 48, 2]
  • 得到不确定点的位置以后,可以通过Bilinear插值得到对应的特征,对每个不确定点的使用一个MLP来进行单独进行细分预测【训练与预测有所区别】。

具体为:通过刚刚得到的不确定点所在图片的相对位置坐标来找到对应的特征点,将此点对应的特征向量与此点的粗糙预测结果合并,然后通过一个MLP进行细分预测。

##训练阶段
def forward(self, x, res2, out):
        """
        主要思路:
        通过 out(粗糙预测)计算出top N 个不稳定的像素点,针对每个不稳定像素点得到在res2(fine)
        和out(coarse)中对应的特征,组合N个不稳定像素点对应的fine和coarse得到rend,
        再通过mlp得到更准确的预测
        :param x: 表示输入图片的特征     eg.[2, 3, 768, 768]
        :param res2: 表示xception的第一层特征输出     eg.[2, 256, 192, 192]
        :param out: 表示经过级联空洞卷积提取的特征的粗糙预测    eg.[2, 19, 48, 48]
        :return: rend:更准确的预测,points:不确定像素点的位置
        """
        """
        1. Fine-grained features are interpolated from res2 for DeeplabV3
        2. During training we sample as many points as there are on a stride 16 feature map of the input
        3. To measure prediction uncertainty
           we use the same strategy during training and inference: the difference between the most
           confident and second most confident class probabilities.
        """
        if not self.training:
            return self.inference(x, res2, out)
		#获得不确定点的坐标
        points = sampling_points(out, x.shape[-1] // 16, self.k, self.beta) #out:[2, 19, 48, 48] || x:[2, 3, 768, 768] || points:[2, 48, 2]
		#根据不确定点的坐标,得到对应的粗糙预测
        coarse = point_sample(out, points, align_corners=False) #[2, 19, 48]
        #根据不确定点的坐标,得到对应的特征向量
        fine = point_sample(res2, points, align_corners=False)  #[2, 256, 48]
		#将粗糙预测与对应的特征向量合并
        feature_representation = torch.cat([coarse, fine], dim=1)   #[2, 275, 48]
		#使用MLP进行细分预测
        rend = self.mlp(feature_representation) #[2, 19, 48]
        return {"rend": rend, "points": points}
##推理阶段
@torch.no_grad()
    def inference(self, x, res2, out):
        """
        输入:
        x:[1, 3, 768, 768],表示输入图片的特征
        res2:[1, 256, 192, 192],表示xception的第一层特征输出
        out:[1, 19, 48, 48],表示经过级联空洞卷积提取的特征的粗糙预测
        输出:
        out:[1,19,768,768],表示最终图片的预测
        主要思路:
        通过 out计算出top N = 8096 个不稳定的像素点,针对每个不稳定像素点得到在res2(fine)
        和out(coarse)中对应的特征,组合8096个不稳定像素点对应的fine和coarse得到rend,
        再通过mlp得到更准确的预测,迭代至rend的尺寸大小等于输入图片的尺寸大小
        """
        """
        During inference, subdivision uses N=8096
        (i.e., the number of points in the stride 16 map of a 1024×2048 image)
        """
        num_points = 8096
                while out.shape[-1] != x.shape[-1]: #out:[1, 19, 48, 48], x:[1, 3, 768, 768]
        	#每一次预测均会扩大2倍像素,直至与原图像素大小一致
            out = F.interpolate(out, scale_factor=2, mode="bilinear", align_corners=True)   #out[1, 19, 48, 48]
            points_idx, points = sampling_points(out, num_points, training=self.training)   #points_idx:8096 || points:[1, 8096, 2]
            coarse = point_sample(out, points, align_corners=False) #coarse:[1, 19, 8096]   表示8096个不稳定像素点根据高级特征得出的对应的类别
            fine = point_sample(res2, points, align_corners=False)  #fine:[1, 256, 8096]    表示8096个不稳定像素点根据低级特征得出的对应类别
            feature_representation = torch.cat([coarse, fine], dim=1)   #[1, 275, 8096] 表示8096个不稳定像素点合并fine和coarse的特征
            rend = self.mlp(feature_representation) #[1, 19, 8096]
            B, C, H, W = out.shape  #first:[1, 19, 128, 256]
            points_idx = points_idx.unsqueeze(1).expand(-1, C, -1)  #[1, 19, 8096]
            out = (out.reshape(B, C, -1)

A ConvNet for the 2020s

paper:https://arxiv.org/abs/2201.03545 CVPR 2022.Facebook AI Research

github:https://github.com/facebookresearch/ConvNeXt

作者提出了ConvNeXt,一个完全由标准 ConvNet 模块构建的纯 ConvNet 模型。ConvNeXt 准确、高效、可扩展且设计非常简单。

2020年以来,ViT一直是研究热点。ViT在图片分类上的性能超过卷积网络的性能,后续发展而来的各种变体将ViT发扬光大(如Swin-T,CSwin-T等),值得一提的是Swin-T中的滑窗操作类似于卷积操作,降低了运算复杂度,使得ViT可以被用做其他视觉任务的骨干网络,ViT变得更火了。本文探究卷积网络到底输在了哪里,卷积网络的极限在哪里。在本文中,作者逐渐向ResNet中增加结构(或使用trick)来提升卷积模型性能,最终将ImageNet top-1刷到了87.8%。作者认为本文所提出的网络结构是新一代(2020年代)的卷积网络(ConvNeXt),因此将文章命名为“2020年代的卷积网络”。

作者的出发点时Resnet-50模型。首先使用用于训练视觉变压器的类似训练技术训练它,与原始Resnet-50相比,获得了较大的改进效果。这将是我们的基线。然后,我们研究了一系列设计决策,总结为1)宏观设计,2)Resnext,3)inverted bottleneck,4)使用大的核,以及5)各种层的微型设计。

1、训练技巧:

作者认为,除了网络结构,训练技巧也会影响最终的效果,除了vision Transformers的结构 ,vision Transformers的一些训练技巧也给作者带来 一些启发。作者使用swin transformer的训练技巧,应用在基线模型中:

1、增加 epoch到300

2、使用AdamW优化器

3、数据增强技术(cutmix、mixup等等)

结果分类准确率由76.1%上升到78.8%。具体训练config如下:

2、宏观设计

作者借鉴了Swin-T的两个设计:

  1. 每阶段的计算量(调整每个阶段block数量)
  2. 对输入图片下采样方法

对于第一点类似Swin-T四个阶段1:1:9:1的计算量,作者将ResNet-50每个阶段block数调整为3,3,9,3(原来为3,4,6,3),增加第三阶段计算量,准确率由78.8%提升至79.4%。

这个每阶段计算量的设计:感觉很多模型都是在中间部分的计算量最多 ,两头的计算量最小,这种设计的效果最好。

对于第二点Swin-T融合压缩2×2的区域,作者则使用4×4步长为4的卷积对输入图片进行下采样,这样每次卷积操作的感受野不重叠,准确率由79.4%提升至79.5%。

3、类ResNeXt设计

depthwise conv中的逐channel卷积操作和self-attention中的加权求和很类似,因此作者采用depthwise conv替换普通卷积。参照ResNeXt,作者将通道数增加到96,准确率提升至80.5%,FLOPs相应增大到了5.3G。相比之下原始的ResNet-50 FLOPs为4G,运算量增大很多。

4、Inverted Bottleneck

在depthwise conv的基础上借鉴MobileNet的inverted bottleneck设计(维度先扩增4倍在缩减),将block由下图(a)变为(b)。因为depthwise不会使channel之间的信息交互,因此一般depthwise conv之后都会接1 × 1 × C的pointwise conv。这一顿操作下来准确率只涨了0.1%到80.6%。在后文说明的大模型上涨点多一点。

Moving up depthwise conv layer

首先,考虑到卷积核太大会导致计算复杂度上升,不方便作者去寻找大卷积核。因此作者借鉴transformer里面MSA block 放在了1*1卷积之前,把7*7的 depthwise conv layer 放在1*1卷积之前,这样, depthwise conv layer 的通道数下降,相应计算量也下降,但性能下降到了79.9%

增大卷积kernel

作者认为更大的感受野是ViT性能更好的可能原因之一,作者尝试增大卷积的kernel,使模型获得更大的感受野。首先在pointwise conv的使用上,作者为了获得更大的感受野,将depthwise conv提前到1 × 1 conv之前,之后用384个1 × 1 × 96的conv将模型宽度提升4倍,在用96个1 × 1 × 96的conv恢复模型宽度。反映在上图中就是由(b)变为(c)。由于3×3的conv数量减少,模型FLOPs由5.3G减少到4G,相应地性能暂时下降到79.9%。

然后作者尝试增大depthwise conv的卷积核大小,证明7×7大小的卷积核效果达到最佳

其他乱七八糟的尝试

借鉴最初的Transformer设计,作者将ReLU替换为GELU;ViT的K/Q/V计算中都没有用到激活函数和归一化层,于是作者也删除了大量的激活函数和归一化层,仅在1 × 1卷积之间使用激活函数,仅在7 × 7卷积和1 × 1 卷积之间使用归一化层,同时将BN升级为LN。最终block结构确定如下:

顺便复习一下各种归一化方法:

最后仿照Swin-T,作者将下采样层单独分离出来,单独使用2 × 2卷积层进行下采样。为保证收敛,在下采样后加上Layer Norm归一化。最终加强版ResNet-50准确率82.0%(FLOPs 4.5G)。

总的来说ResNet-50、本文模型和Swin-T结构差别如下:

实验结果

作者在ResNet-50加强版的基础上又提出了多个变体(ConvNeXt-T/B/L/XL),从实验结果上看ResNet-50加强版性能收益较为突出,越是大模型性能收益越低。

在检测、分割下游任务中ConvNeXt也获得了与Swin-T相似或更好的结果。结果就不细说了。

消融实验

每一部分具体涨点效果如下:

总的来说本文实验做的比较充分,总结一下,卷积网络涨点可以尝试:

  1. 对输入下采样时尝试无重叠小一点的卷积层,例如4 × 4,stride=4的卷积;
  2. block中采用大卷积核,例如7 × 7;
  3. depthwise conv + inverted bottleneck + moving up depthwise layer的block结构;
  4. 减少激活/归一化层,ReLU换成GELU,BN换成LN;
  5. 使用2×2 conv + LN下采样。

Vision MLP –Pay Attention to MLPs

MLP-Mixer的增强版,带gating的MLP。有两个版本,分别是gMLP和aMLP。Pay-Attention-to-MLPs是gMLP版本,同时也提出了gMLP的增强版aMLP。

paper: https://arxiv.org/abs/2105.08050

github: https://github.com/antonyvigouret/Pay-Attention-to-MLPs

此文和最近刊出MLP文章相同,旨在探究self-attention对于Transformer来说是否至关重要。并在CV和NLP上的相关任务进行实验。

Transformer结构具有可并行化汇聚所有token间的空间信息的优点。众所周知self-attention是通过计算输入间的空间关系动态的引入归纳偏置,同时被静态参数化的MLP能表达任意的函数,所以self-attention对于Transformer在CV和NLP等领域的成功是否是至关重要的呢?

  • 此文提出了一个基于MLP的没有self-attention结构名为gMLP,仅仅存在静态参数化的通道映射(channel projections)和空间映射(spatial projections)。同时作者通过实验发现当对空间映射的线性结果进行门机制乘法得到的效果最好
  • 此文使用gMLP做图片分类并在ImageNet上取得了与DeiT、ViT等Transformer模型相当的效果。与先前的MLP模型MLP-Mixer相比,gMLP做到了参数更少(参数减少66%)效果更强(效果提升3%)。
  • 此文使用gMLP做masked language modeling,gMLP采用和Bert一样的设置最小化perplexity取得了和Transformer模型预训练一样好的效果。通过pretraining和finetuning实验发现随着模型容量的增加,gMLP比Transformer提升更大,表明模型相较于self-attention可能对于模型容量的大小更为敏感。
  • 对于需要跨句对齐的微调任务MNLI,gMLP与Transformer相比逊色一筹。对此作者发现加上一个128特征大小的单头注意力足以使得gMLP在任何NLP任务上取得比Transformer更好的效果。

gMLP由L个如下图所示的模块堆叠而成

设每个模块的输入 \(X \in \mathbb{R}^{n \times d}\), n为序列长度, d为特征维度。每个模块表达如下:
\(Z=\sigma(X U), \quad \tilde{Z}=s(Z), \quad Y=\tilde{Z} V\)
\(\sigma\) 是GELU等激活函数, U 和 V 和Transformer中的FFN类似都是线性映射。为了简洁表达上式中 省略了shortcuts, normalizations 和 biases。
上式中最重要的是能捕捉空间交互的 \(s(\cdot)\) 。如果上式去掉 \(s(\cdot)\) 那么将不再能进行空间交互和FFN 并无区别。文中作者选择名为 Spatial Gating Unit (SGU) 的模块作为 \(s(\cdot)\) 捕捉空间依赖。另外,gMLP在NLP、CV任务中遵循与BERT、ViT一样的输入输出规则。

Spatial Gating Unit:

为了能有跨token的交互, \(s(\cdot)\) 操作须在空间维度。可以简单的使用线性映射表示:
\(f_{W, b}(Z)=W Z+b\)
其中 \(W \in \mathbb{R}^{n \times n}\) 表示空间交互的映射参数。在self-attention中 W 是通过 Z 动态计算得到的。 此文对上式使用gating操作以便更好的训练,如下所示:
\(s(Z)=Z \odot f_{W, b}(Z)\)
为了训练更稳定,作者将 W 和 b 分别初始化为接近 0 与 1 来保证在开始训练时 \(f_{W, b} \approx 1\) 、 \(s(Z z) \approx Z\) 使得在开始阶段gMLP近似于FFN并在训练中逐渐学习到跨token的空间信息。
作者进一步发现将 Z 从通道维度分割成两部分 \(\left(Z_1, Z_2\right)\) 进行gating操作更有用,如下所示:
\(
s(Z)=Z_1 \odot f_{W, b}\left(Z_2\right)
\)
另外函数 \(f_{W, b}\)的输入通常需要normalizel以此提升模型的稳定性。

一些思考:这里的SpatialGatingUnit里面用到了一个通道split,然后再将分割后的两部分做乘法,让我想到了NAFnet中的simplegate,这个的作用一是减少计算量(相比于GELU)、另外引入门控机制,在通道维度进行通道交织,对于模型的效果表现很好。

作者进一步分析了SGU与现有的一些操作的相似之处:首先是Gated Linear Units (GLU) 与 SGU的区别在于SGU对spatial dimension而GLU对channel dimension; 其次SGU和
Squeeze-and-Excite (SE) 一样使用hadamard-product,只是SGU并没有跨通道的映射来保 证排列不变性;SGU的空间映射可以看作depthwise convolution不过SGU只学习跨通道只是, 并没有跨通道过滤器;SGU学习的是二阶空间交互 \(z_i z_j\) , self-attention学习的是三阶交互 \(q_i k_j v_k\) , SGU的复杂度为 \(n^2 e / 2\) 而self-attention的复杂度为 \(2 n^2 d_{\text {。 }}\)

实验:

1、Image Classification

此文首先将gMLP应用于图片分类,使用ImageNet数据集而且不使用额外数据。下表首先展示了gMLP用于图片分类的参数,gMLP和ViT/B16一样使用 16×16 个patch,同时采用和DeiT相似的正则化方法防止过拟合。

下表中gMLP与baselines在ImageNet上的结果表示gMLP取得了与视觉Transformer相当的结果,同时与其它MLP视觉模型相比,gMLP取得了准确率、速度权衡下最好的结果。

Masked Language Modeling with BERT:

此文同时将gMLP应用于masked language modeling(MLM)任务,对于预训练和微调任务,模型的输入输出规则都保持与BERT一致。

作者观察到在MLM任务最后学习到的空间映射矩阵总是Toeplitz-like matrics,如下图所示。所以作者认为gMLP是能从数据中学习到平移不变性的概念的,这使得gMLP实质起到了卷积核是整个序列长度的1-d卷积的作用。在接下来的MLM实验中,作者初始 W 为Toeplitz matrix。

Ablation: The Importance of Gating in gMLP for BERT’s Pretraining:下表展示了gMLP的各种变体与Transoformer模型、MLP-Mixer的比较,可以看到gMLP在与Transformer相同模型大小的情况下能达到与Transformer相当的效果。同时gating操作对于空间映射十分有用。同时下图还可视化了模型学习到的空间映射参数。

Case Study: The Behavior of gMLP as Model Size Increases:下表与下图展示了gMLP随着模型增大逐渐能有与Transformer相当的效果,可见Transformer的效果应该主要是依赖于模型尺寸而非self-attention。

  • Ablation: The Usefulness of Tiny Attention in BERT’s Finetuning:从上面的Case Study可以发现gMLP对于需要跨句子连接的finetuing任务可能不及Transformer,所以作者提出了gMLP的增强版aMLP。aMLP相较于gMLP仅增加了一个单头64的self-attention如下图所示:

从下图结果可以发现aMLP相较于gMLP极大提升了效果并在所有task超过了Transformer。

Vision MLP –ResMLP

Feedforward networks for image classification with data-efficient training

我们提出了ResMLP,一种完全基于多层感知机(MLP)进行图像分类的体系结构。 它是一个简单的残差网络,它交替(i)线性层,其中图像 patches在通道之间独立且相同地交互;以及(ii)两层前馈网络,其中通道中的每个 patch独立地相互作用。

CODE:

import torch
import numpy as np
from resmlp import ResMLP

img = torch.ones([1, 3, 224, 224])

model = ResMLP(in_channels=3, image_size=224, patch_size=16, num_classes=1000,
                 dim=384, depth=12, mlp_dim=384*4)

parameters = filter(lambda p: p.requires_grad, model.parameters())
parameters = sum([np.prod(p.size()) for p in parameters]) / 1_000_000
print('Trainable Parameters: %.3fM' % parameters)

out_img = model(img)

print("Shape of out :", out_img.shape)  # [B, in_channels, image_size, image_size]

本文作者提出了一种基于全连接层的图像分类网络。网络结构与MLP-Mixer相似,即先将输入图像拆分成若干patch,对每个patch通过全连接层转换为特征嵌入矩阵,该矩阵的两个维度分别表示channel维度(每个局部位置的特征维度)和patch维度(表示局部位置的维度)。首先将该矩阵转置后沿patch维度进行全连接层运算,实现不同patch之间的交互;再沿channel维度进行全连接运算,实现不同channel之间的交互。最后使用池化层和输出层获得分类结果。本文与MLP-Mixer的不同之处在于采用了更强的数据增强方法和蒸馏策略。

当采用现代的训练策略进行训练时,使用大量的数据增广和可选的蒸馏方法,可以在ImageNet上获得令人惊讶的良好精度/复杂度折衷。

Affine仿射变换:

函数名称:diag(x)
函数功能:构建一个n维的方阵,它的主对角线元素值取自向量x,其余元素都为0

Vision MLP系列–RepMLP

RepMLPNet: Hierarchical Vision MLP with Re-parameterized Locality (https://arxiv.org/abs/2112.11081)

CVPR 2022

RepMLP Block

Github source: https://github.com/DingXiaoH/RepMLP

最近公开了一系列视觉MLP论文,包括RepMLP、MLP-Mixer、ResMLP、gMLP等。在这个时间点出现关于MLP的一系列讨论是很合理的:

1) Transformer大火,很多研究者在拆解Transformer的过程中多多少少地对self-attention的必要性产生了疑问。去掉了self-attention,自然就剩MLP了。

2) 科学总是螺旋式上升的,“复兴”老方法(比如说另一篇“复兴”VGG的工作,RepVGG)总是喜闻乐见的。

这些论文引发了热烈的讨论,比如:

1) 这些模型到底是不是MLP?

2) 卷积和全连接(FC)的区别和联系是什么?FC是不是卷积,卷积是不是FC?

3) 真正的纯MLP为什么不行?

4) 所以MLP is all you need?

《RepMLP: Re-parameterizing Convolutions into Fully-connected Layers for Image Recognition》。这篇文章讲了一个全连接层找到一份陌生的工作(直接进行feature map的变换),为了与那些已经为这份工作所特化的同胞(卷积层)们竞争,开始“内卷”的故事。

关键贡献在于,RepMLP用卷积去增强FC,既利用其全局性又赋予其局部性,并通过结构重参数化,将卷积融合到FC中去,从而在推理时去除卷积。

论文:RepMLP: Re-parameterizing Convolutions into Fully-connected Layers for Image Recognition

代码:DingXiaoH/RepMLP

1. 为什么真正的纯MLP不太行?

我们一般认为多层感知机(MLP)是至少两层全连接层(FC)堆叠得到的模型,而且一般把同时含有卷积和MLP的模型(或模型中的一个模块)称为CNN。尽管目前大家对什么叫MLP的问题尚有争议(下图),我们不妨先定义一个任何人都会称之为MLP的100%纯MLP:

这个MLP在ImageNet上的输入是(3, 112, 112),第一层将其变为(32, 56, 56),第二层将其变为(64, 28, 28),然后global average pool,然后经过FC映射为1000类。这样总共只有三个FC,毫无疑问是MLP。这三层的参数为:

第一层:3x112x112x32x56x56 = 3.77G 参数

第二层:32x56x56x64x28x28 = 5.03G 参数

第三层:64×1000 = 64k 参数,忽略不计

看起来有点吓人,但这确实是一个处于A1位置的纯MLP应有的体量,虽然它只有两层,而且通道数只有32和64。除了减小通道数量,任何试图减小参数量的改动都将使其不再属于A1位置。比如说:

1) 先切块。把112×112的输入切成56×56的四块,每一块经过第一层变成28×28,再拼起来,这样第一层的参数量变成了3x56x56x32x28x28=236M,看起来好多了。但是,这破坏了全局性,因为分属于两块中的两点之间不再有联系了!换句话说,我们引入了一种局部性:一张图切成四块之后,每块中的任一像素只跟同块中的其他像素有联系。ViT,RepMLP和其他几篇MLP都用了这种操作或某种类似的操作。

2) 分组FC。正如卷积有分组卷积一样,FC也可以分组。由于torch里没有现成的算子,分组FC可以用分组1×1卷积实现。组数为g,参数量和计算量就会变成1/g。可惜,这也引入了局部性。RepMLP用了这种操作。

3) 把一个FC拆分成两次操作,第一次操作对channel维度线性重组,spatial共享参数(等价于1×1卷积);第二次操作对spatial维度线性重组,channel共享参数(等价于先转置后1×1卷积)。这思想可以类比于depthwise conv + 1×1 conv。MLP-Mixer使用这种操作,用两个各自都不具有全局性的操作实现了整体的全局性(而RepMLP使用另一种不同的机制,对不同的分块做pooling再连接,实现了这种全局性)。

所以,真正的100%纯MLP不太行,大家都在用各种花式操作做“伪MLP”的原因之一,就是体量太大。

这篇文章介绍的RepMLP属于B2的位置,不追求纯MLP。称其为“MLP”的原因是想强调卷积和FC的区别:RepMLP将卷积看成一种特殊的FC,显式地用卷积去强化FC(把FC变得具有局部性又不失全局性),指出了这样的FC强在哪里(如ResNet-50中,用一半通道数量的RepMLP替换3×3卷积就可以实现同等精度和55%加速),并用这种强化过的FC(及一些其他技巧)构造一种通用的CNN基本组件,提升多重任务性能。论文中说明了这里MLP的意思是推理时结构“不包含大于1×1的卷积”。

2. RepMLP:FC“内卷”,卷出性能

真正的100%纯MLP不太行的原因之二,是不具有局部先验。

在一张图片中,一个像素点跟它周围的像素点的关系往往比远在天边的另一个像素点更密切,这称为局部性。人类在识别图片的时候潜意识地利用这一点,称为局部先验。卷积网络符合局部先验,因为卷积核通过滑动窗口在图片上“一块一块地”寻找某种特征。

那么FC层呢?FC能自动学到这一点吗?在有限的数据量(ImageNet)和有限的计算资源前提(GPU)下,很难。

实验验证:下面我们假设FC层的输入是64x10x10的feature map直接 “展平”成的6400维向量。输出也是6400维向量,然后reshape成64x10x10的feature map。下图展示了FC学得的kernel中的一个切片的权值大小。简单地讲(详见论文),展示的这一部分表示在输出的第0个channel中随便找的一个采样点(6,6)(也就是图中黄框标出来的点)作用于第0个输入channel上的10×10个像素点的权值。颜色越深,表示权值越大。比如说,如果图中的(5,5)点颜色深,就表示这个FC层认为输出中的(0,6,6)点与输入中的(0,5,5)点关系紧密。

结果很明显,(6,6)周围的权值并没有颜色更深,也就是说FC并不认为这个点和周围点的联系更紧密。相反,似乎这个FC层认为(6,6)点与右上和右下部分关系更密切。实验也证明,不具有局部性的FC效果较差。

既然图像的局部性很强,FC把握不住,那怎么办呢?RepMLP提出,用卷积去增强FC(如下图所示,输入既被展平成向量并输入FC,又用不同大小的卷积核进行卷积,各自过BN后相加),并通过结构重参数化,将卷积融合到FC中去,从而在推理时去除卷积。

我们将卷积和FC之间建立联系,是因为卷积可以看成一个稀疏且存在重复参数的FC。如下图代码所示,给定输入X和卷积核conv_K,其卷积的结果等于X(直接展平成向量)和fc_K的矩阵乘,fc_K称为conv_K的等效FC核。尽管我们都相信这样的fc_K一定存在,但根据conv_K的值直接构造出fc_K的方法(下图中的convert_K函数)似乎不太简单。

本文提出了一种简洁优美的做法(见后文)。我们用这种方法构造出fc_K并打印出来,可以看出它是一个稀疏且有很多元素相同的矩阵(Toeplitz矩阵)。如下图的代码和结果所示。

RepMLP把卷积的输出和FC的输出相加,这样做的好处是:

1) 降低FLOPs,提高速度。用我们提出的方法把卷积全都转换为等效FC kernel后,由于矩阵乘法的可加性(AX + BX = (A+B)X),一个稀疏且共享参数的FC(Toeplitz矩阵)加一个不稀疏不共享参数的FC(全自由度的矩阵),可以等价转换为一个FC(其参数是这两个矩阵之和)。这样我们就可以将这些卷积等效地去掉。这一思路也属于结构重参数化(通过参数的等价转换实现结构的等价转换,如RepVGG)。

2) 在同等参数量的情况下,FC的FLOPs远低于卷积。

3) 相比于纯FC,这样做产生了局部性。注意这种局部性是我们“赋予”FC的,而不是让FC学到的。

4) 相比于卷积层,这样做使得相距遥远的两个点直接相连,具备了全局性。

这样做看起来像是让FC的“内部”含有卷积,所以也可以称为“内卷”。事实证明,跟人类相似,FC的“内卷”也可以提高性能。

只剩下一个问题了:我们相信存在一个FC kernel等价于卷积的卷积核,但是给定一个训练好的卷积核,怎么构造出FC kernel(Toeplitz矩阵)呢?

其实也很简单:FC kernel等于在单位矩阵reshape成的feature map上用卷积核做卷积的结果。这一做法是高效、可微、与具体的卷积算法和平台无关的。推导过程也很简洁(详见论文)。

现在,整个流程就很清晰了:

1) 训练时,既有FC又有卷积,输出相加。

2) 训练完成后,先把BN的参数“吸”到卷积核或FC中去(跟RepVGG一样),然后把每一个卷积转换成FC,把所有FC加到一起。从此以后,不再有卷积,只有FC。

3) 保存并部署转换后的模型。

现在我们再看一下用卷积增强后转换得到的FC kernel,可以看出采样点周围的权值变大了,现在(6,6)点更关注它旁边的输入点了。有趣的是,这里用到的最大卷积是7×7,但是7×7的范围(蓝色框)外还有一些值(红色框)比蓝框内的值大,这说明全局性也没有被局部性“淹没”。

一些其他设计

RepMLP中也用了一些其他设计,包括:

1) 用groupwise conv实现groupwise FC,减少参数和计算量。

2) 将输入分块(最近大家都会用的常见操作),进一步减少参数和计算量。如下图所示,H和W是feature map的分辨率,h和w是每一块的分辨率。

3) 用两个FC在不同分块之间建立联系,确保全局性。如下图所示。

实验结果

用RepMLP替换Res50中的部分结构,在ImageNet上有性能提升。将ImageNet pretrained模型迁移到语义分割和人脸上,也都有性能提升。

在ImageNet上的实验是在Res50中做的。考虑到Res50的主干通道较多(256、512、1024、2048),为了将RepMLP用到Res50中取得合理的trade-off,我们做了以下设计:

1)RepMLP Bottleneck Block:在RepMLP之前用1×1和3×3降维,RepMLP之后用3×3和1×1升维。这一结构类似于旷视在工程中探索并申请的专利GLFP(202010422194.X, Visual task processing method and device and electronic system,下图)。

2)RepMLP Light Block:在RepMLP之前用1×1大幅降维,之后用1×1大幅升维。降维/升维的幅度(8x)比Res50(4x)更大。

一些有趣的发现:

1) RepMLP中具有局部先验的成分(融合进FC的卷积),所以对于具有平移不变性的任务(ImageNet,Cityscapes语义分割)有效。

2) RepMLP中也具有不具有平移不变性的成分(大FC kernel),所以对于具有某种位置模式(例如人脸图像中,眼睛总是在鼻子上面)的任务也有效。

3) 由于FC和卷积的差别,RepMLP可以大幅增加参数而不降低速度(参数增加47%,ImageNet精度提升0.31%,速度仅降低2.2%)。

一些常见问题

RepMLP和ResMLP是什么关系?

相当于旺旺碎冰冰和王冰冰的关系。只是名字有点像。RepMLP中用卷积增强FC的思路也可以用在其他MLP架构中,应该也会有提升。另外,ResMLP、RepMLP和ResRep(去年做的一篇用重参数化做剪枝的论文)也没有关系。

把卷积融合进FC里,那FC不就是卷积了吗?

卷了,但不是完全卷,而且比卷积更强。上面可视化的图显示,转换后的kernel可以关注到卷积核的感受野以外的信息,因而表征能力更强。论文中报告的实验表明,这样的操作可以以一半的channel量达到与纯CNN相当的性能,速度更快,FLOPs更低。本文的关键也在于把卷积看成一种特殊的FC,然后考虑如何利用这种特殊性

所以MLP is all you need?

目前看来,还差得远。目前的方法多多少少都用到了切块等操作,都需要用某种方式降低参数量和引入局部性。真正的纯MLP(A1位置)依然还没有希望。真正纯MLP的一个大麻烦是总的参数量和输入分辨率耦合,因而改变输入分辨率会很困难。MLP-Mixer的一个缺点是不方便改变输入分辨率,所以它在ImageNet分类上的性能不容易迁移到其他任务上去。

PyTorch医学图像分割开源库

github: https://github.com/MontaEllis/Pytorch-Medical-Segmentation

基于PyTorch的专注于医学图像分割的开源库,其支持模型丰富,方便易用。其可算为torchio的一个实例,作者将其综合起来,包含众多经典算法,实用性比较强。

该库特点:

  1. 支持2D和3D医学图像分割,可以修改hparam.py文件来确定是2D分割还是3D分割以及是否可以进行多分类。
  2. 支持绝大数主流分割模型,几乎提供了所有的2D和3D分割的算法。
  3. 兼容几乎所有的医学数据格式(例如 nii.gz, nii, mhd, nrrd, …),修改hparam.py的fold\_arch即可。

作者提供了训练和测试推断的代码,简单配置后训练和推断都仅需要一行命令。

已包含的分割模型:

超越YOLOv7 | YOLOv6论文

各种Tricks大放异彩!!

论文: https://arxiv.org/abs/2209.02976

github:https://github.com/meituan/YOLOv6

多年来,YOLO 系列一直是高效目标检测的行业标准。YOLO 社区蓬勃发展,丰富了其在众多硬件平台和丰富场景中的使用。在这份技术报告力求将其极限推向新的高度,以坚定不移的行业应用心态向前迈进。

考虑到真实环境中对速度和准确性的不同要求,作者广泛研究了来自工业界或学术界的最新目标检测进展。具体来说,从最近的网络设计、训练策略、测试技术、量化和优化方法中大量吸收了一些想法。最重要的是,整合思想和实践,构建了一套不同规模的部署网络,以适应多样化的用例。

在 YOLO 作者的慷慨许可下,作者将其命名为 YOLOv6。作者也热烈欢迎用户和贡献者进一步增强。YOLOv6-N 在 NVIDIA Tesla T4 GPU 上以 1234 FPS 的吞吐量在 COCO 数据集上达到 35.9% 的 AP。YOLOv6-S 以 495 FPS 的速度达到 43.5% 的 AP,优于同规模的其他主流检测器(YOLOv5-SYOLOX-S 和 PPYOLOE-S)。

YOLOv6-S 量化版本甚至带来了 869 FPS 的最新 43.3% AP。此外,与具有相似推理速度的其他检测器相比,YOLOv6-M/L 还实现了更好的准确度性能(即 49.5%/52.3%)。

1、简介

YOLO 系列因其在速度和准确性之间的出色平衡而成为工业应用中最流行的检测框架。YOLO 系列的开创性作品是YOLOv1-3,随着后期的实质性改进,开创了单阶段检测器的新路。YOLOv4 将检测框架重组为几个独立的部分(backboneneck 和 head),并验证了当时的 bag-of-freebies 和 bag-of-specials,设计了一个适合在单 GPU 上训练的框架。目前,YOLOv5YOLOXPPYOLOE 和 YOLOv7 都是高效检测器部署的竞争候选者。不同大小的模型通常通过缩放技术获得。

在本报告中,作者凭经验观察了几个促使更新 YOLO 框架的重要因素:

  1. RepVGG 的重参化是一种高级技术,尚未在检测中得到很好的利用。作者还注意到 RepVGG Block 的简单模型缩放变得不切实际,为此作者认为小型和大型网络之间的网络设计的优雅一致性是不必要的。普通的单路径架构对于小型网络是更好的选择,但对于较大的模型,参数的指数增长和单路径架构的计算成本使其不可行;
  2. 基于重参化的检测器的量化也需要细致处理,否则由于其在训练和推理过程中的异构配置,将难以处理性能下降。
  3. 以前的工作往往不太关注部署,其延迟通常在 V100 等高成本机器上进行比较。在实际服务环境方面存在硬件差距。通常,像 Tesla T4 这样的低功耗 GPU 成本更低,并且提供相当好的推理性能。
  4. 考虑到架构差异,标签分配和损失函数设计等高级特定领域策略需要进一步验证;
  5. 对于部署,可以容忍训练策略的调整,提高准确度性能但不增加推理成本,例如知识蒸馏。

考虑到上述观察,带来了 YOLOv6 的诞生,它在准确性和速度方面实现了迄今为止最好的权衡。在图 1 中展示了 YOLOv6 与其他类似规模的同行的比较。为了在不大幅降低性能的情况下提高推理速度,研究了包括训练后量化 (PTQ) 和量化感知训练 (QAT) 在内的尖端量化方法,并将它们纳入 YOLOv6 以实现部署就绪网络的目标。

将 YOLOv6 的主要方面总结如下:

  • 针对不同场景中的工业应用重新设计了一系列不同规模的网络。不同规模的架构各不相同,以实现最佳的速度和准确性权衡,其中小型模型具有简单的单路径主干,大型模型建立在高效的多分支块上。
  • 为 YOLOv6 注入了一种self-distillation策略,在分类任务和回归任务上都执行。同时,动态调整来自教师和标签的知识,以帮助学生模型在所有训练阶段更有效地学习知识。
  • 广泛验证标签分配、损失函数和数据增强技术的先进检测技术,并有选择地采用它们以进一步提高性能。
  • 在 RepOptimizer 和通道蒸馏的帮助下改进了检测的量化方案,这带来了具有 43.3% 的 COCO AP 和 869 FPS 的吞吐量的快速准确的检测器,批量大小为 32。

2、YOLOv6方法全解

YOLOv6 的改造设计包括以下组件,网络设计、标签分配、损失函数、数据增强、行业便利改进以及量化和部署:

网络设计:

  • Backbone:与其他主流架构相比, RepVGG 主干在相似的推理速度下在小型网络中具有更强的特征表示能力,但由于参数和计算成本的爆炸式增长,它很难扩展以获得更大的模型。在这方面,将 RepBlock 作为小型网络的构建块。对于大型模型,修改了一个更高效的 CSP Block,名为 CSPStackRep 块。
  • Neck:YOLOv6 的 Neck 采用 YOLOv4 和 YOLOv5 之后的 PAN。使用 RepBlocks 或 CSPStackRep Blocks 增强 Neck 以获得 Rep-PAN
  • Head:简化了 Decoupled Head,使其更高效,称为Efficient Decoupled Head

标签分配:

通过大量实验评估了 YOLOv6 上标签分配策略的最新进展,结果表明 TAL 更有效且对训练更友好。

损失函数:

主流的Anchor-Free检测器的损失函数包括分类损失、框回归损失和目标损失。对于每个损失,用所有可用的技术系统地对其进行试验,最后选择 VariFocal Loss 分类损失,SIoU/GIoU 损失作为回归损失。

行业便利的改进:

引入了额外的常见实践和技巧来提高性能,包括self-distillation和更多的训练时期。对于self-distillation,分类和框回归分别由教师模型监督。多亏了 DFL使得框回归的蒸馏成为可能。此外,来自Soft Label和Hard Label的信息比例通过余弦衰减动态下降,这有助于学生在训练过程中的不同阶段选择性地获取知识。此外,作者遇到了性能受损的问题,而在评估时没有添加额外的灰色边框,为此提供了一些补救措施。

量化和部署:

为了解决量化基于重参化模型的性能下降问题,使用 RepOptimizer 训练 YOLOv6 以获得对 PTQ 友好的权重。进一步采用 QAT 和通道蒸馏和图优化来追求极致性能。量化 YOLOv6-S 达到了最新的技术水平,AP 为 42.3%,吞吐量为 869 FPS(batch size=32)。

2.1、网络设计

单阶段目标检测器一般由以下部分组成:BackboneNeckHeadBackbone主要决定特征表示能力,同时,它的设计对推理效率有至关重要的影响,因为它承载了很大一部分计算成本。Neck用于将低层次的物理特征与高层次的语义特征进行聚合,然后构建各个层次的金字塔特征图。Head由几个卷积层组成,它根据Neck融合的多级特征预测最终检测结果。从结构的角度来看,它可以分为Anchor-BaseAnchor-Free,或者更确切地说是参数耦合Head和参数解耦Head

在 YOLOv6 中,基于硬件友好的网络设计原则,提出了两个可缩放的可重参数BackboneNeck以适应不同大小的模型,以及一个具有混合通道策略的高效解耦HeadYOLOv6 的整体架构如图 2 所示。

1、Backbone

如上所述,Backbone网络的设计对检测模型的有效性和效率有很大的影响。以前,已经表明多分支网络通常可以比单路径网络实现更好的分类性能,但它通常伴随着并行度的降低并导致推理延迟的增加。相反,像 VGG 这样的普通单路径网络具有高并行性和更少内存占用的优势,从而带来更高的推理效率。最近在 RepVGG 中,提出了一种结构重参化方法,将训练时多分支拓扑与推理时普通架构解耦,以实现更好的速度-准确度权衡。

受上述工作的启发,设计了一个高效的可重参化Backbone,表示为 EfficientRep。对于小型模型,Backbone的主要组成部分是训练阶段的 RepBlock,如图 3(a)所示。并且每个 RepBlock 在推理阶段被转换为具有 ReLU 激活函数的 3×3 卷积层(表示为 RepConv)的堆栈,如图 3(b)所示。通常,3×3 卷积在主流 GPU 和 CPU 上进行了高度优化,并且具有更高的计算密度。因此,EfficientRep Backbone 充分利用了硬件的计算能力,在显着降低推理延迟的同时增强了表示能力。

然而,作者注意到随着模型容量的进一步扩大,单路径普通网络中的计算成本和参数数量呈指数增长。为了在计算负担和准确性之间取得更好的平衡,修改了一个 CSPStackRep Block 来构建中型和大型网络的Backbone。如图 3(c) 所示,CSPStackRep Block 由3个 1×1 卷积层和一堆子块组成,该子块由两个 RepVGG Block 或 RepConv(分别在训练或推理时)和一个残差连接组成。此外,采用跨级部分(CSP)连接来提高性能,而不会产生过多的计算成本。与 CSPRepResStage 相比,它的外观更加简洁,并考虑了准确性和速度之间的平衡。

2、Neck

在实践中,多尺度的特征集成已被证明是目标检测的关键和有效部分。采用来自 YOLOv4 和 YOLOv5 的修改后的 PAN 拓扑作为检测Neck的基础。此外,将 YOLOv5 中使用的 CSPBlock 替换为 RepBlock(适用于小型模型)或 CSPStackRep Block(适用于大型模型),并相应调整宽度和深度。YOLOv6 的Neck表示为 Rep-PAN

3、Head

Efficient decoupled head

YOLOv5 的检测头是一个耦合Head,在分类和定位分支之间共享参数,而 FCOS 和 YOLOX 中的检测头将两个分支解耦,并且在每个分支中引入了额外的两个 3×3 卷积层以提高性能。

在 YOLOv6 中采用混合通道策略来构建更高效的解耦Head。具体来说,将中间 3×3 卷积层的数量减少到只有一个。头部的宽度由BackboneNeck的宽度乘数共同缩放。这些修改进一步降低了计算成本,以实现更低的推理延迟。

Anchor-free

Anchor-free检测器因其更好的泛化能力和解码预测结果的简单性而脱颖而出。其后处理的时间成本大大降低。有两种类型的Anchor-free检测器:基于Anchor和基于关键点。在 YOLOv6 中,我们采用了基于Anchor点的范式,其框回归分支实际上预测了Anchor点到边界框4个边的距离。

2.2、Label Assignment

标签分配负责在训练阶段为预定义的Anchor分配标签。以前的工作已经提出了各种标签分配策略,从简单的基于 IoU 的策略和内部真实方法到其他更复杂的方案。

SimOTA OTA 将目标检测中的标签分配视为最佳传输问题。它从全局角度为每个真实对象定义了正/负训练样本。SimOTA 是 OTA 的简化版本,它减少了额外的超参数并保持了性能。在 YOLOv6 的早期版本中使用 SimOTA 作为标签分配方法。然而,在实践中,作者发现引入 SimOTA 会减慢训练过程。而且陷入不稳定训练的情况并不少见。因此,希望更换 SimOTA

任务对齐学习任务对齐学习(Task Alignment Learning,TAL)最早是在TOOD中提出的,其中设计了一个分类分数和预测框质量的统一度量。IoU 被这个指标替换以分配对象标签。在一定程度上缓解了任务错位(分类和框回归)的问题。TOOD 的另一个主要贡献是关于任务对齐的头部(T-head)。T-head 堆叠卷积层以构建交互式特征,在其之上使用任务对齐预测器 (TAP)。PP-YOLOE 改进了 T-head,将 T-head 中的 layer attention 替换为轻量级的 ESE attention,形成 ET-head。然而,我们发现 ET-head 会降低模型中的推理速度,并且没有准确度增益。因此,保留了高效解耦头的设计。

此外,作者观察到 TAL 可以带来比 SimOTA 更多的性能提升并稳定训练。因此,采用 TAL 作为 YOLOv6 中的默认标签分配策略。

2.3、损失函数

1、Classification Loss

提高分类器的性能是优化检测器的关键部分。Focal Loss 修改了传统的交叉熵损失,以解决正负样本之间或难易样本之间的类别不平衡问题。为了解决训练和推理之间质量估计和分类的不一致使用,Quality Focal LossQFL)进一步扩展了Focal Loss,联合表示分类分数和分类监督的定位质量。而 VariFocal Loss (VFL) 源于 Focal Loss,但它不对称地对待正样本和负样本。通过考虑不同重要性的正负样本,它平衡了来自两个样本的学习信号。Poly Loss 将常用的分类损失分解为一系列加权多项式基。它在不同的任务和数据集上调整多项式系数,通过实验证明比交叉熵损失和Focal Loss损失更好。

在 YOLOv6 上评估所有这些高级分类损失,最终采用 VFL

2、Box Regression Loss

框回归损失提供了精确定位边界框的重要学习信号。L1 Loss 是早期作品中的原始框回归损失。逐渐地,各种精心设计的框回归损失如雨后春笋般涌现,例如 IoU-series 损失和概率损失。

IoU-series Loss IoU loss 将预测框的四个边界作为一个整体进行回归。它已被证明是有效的,因为它与评估指标的一致性。IoU的变种有很多,如GIoUDIoUCIoUα-IoUSIoU等,形成了相关的损失函数。我们在这项工作中对 GIoUCIoU 和 SIoU 进行了实验。并且SIoU应用于YOLOv6-NYOLOv6-T,而其他的则使用GIoU

Probability Loss Distribution Focal Loss (DFL) 将框位置的基本连续分布简化为离散化的概率分布。它在不引入任何其他强先验的情况下考虑了数据中的模糊性和不确定性,这有助于提高框定位精度,尤其是在ground-truth框的边界模糊时。在 DFL 上,DFLv2 开发了一个轻量级的子网络,以利用分布统计数据与真实定位质量之间的密切相关性,进一步提高了检测性能。然而,DFL 输出的回归值通常比一般框回归多 17 倍,从而导致大量开销。额外的计算成本阻碍了小型模型的训练。而 DFLv2 由于额外的子网络,进一步增加了计算负担。在实验中,DFLv2 在模型上为 DFL 带来了类似的性能提升。因此,只在 YOLOv6-M/L 中采用 DFL

3、Object Loss

Object loss 最早是在 FCOS 中提出的,用于降低低质量边界框的得分,以便在后处理中将其过滤掉。它还被用于 YOLOX 以加速收敛并提高网络精度。作为像 FCOS 和 YOLOX 这样的Anchor-free框架,在 YOLOv6 中尝试过 object loss。不幸的是,它并没有带来很多积极的影响。

2.4、行业便利的改进

1、More training epochs

经验结果表明,检测器的性能随着训练时间的增加而不断进步。作者将训练持续时间从 300 个 epoch 延长到 400 个 epoch,以达到更好的收敛性。

2、Self-distillation

为了在不引入太多额外计算成本的情况下进一步提高模型精度,应用了经典的知识蒸馏技术,最小化了教师和学生预测之间的 KL-divergence。将老师限制为学生本身,但经过预训练,因此称之为自我蒸馏。

请注意,KL-divergence通常用于衡量数据分布之间的差异。然而,目标检测中有两个子任务,其中只有分类任务可以直接利用基于 KL-divergence的知识蒸馏。由于 DFL 损失,也可以在框回归上执行它。知识蒸馏损失可以表示为:

其中Ldet  是使用预测和标签计算的检测损失。引入超参数α来平衡两个损失。在训练的早期阶段,来自老师的软标签更容易学习。随着训练的继续,学生的表现将与老师相匹配,因此硬标签将更多地帮助学生。在此基础上,将余弦权重衰减应用于 α,以动态调整来自硬标签和来自教师的软标签的信息。

3、Gray border of images

作者注意到在 YOLOv5 和 YOLOv7 的实现中评估模型性能时,每个图像周围都有一个半步长的灰色边框。虽然没有添加有用的信息,但它有助于检测图像边缘附近的对象。这个技巧也适用于 YOLOv6

然而,额外的灰色像素明显降低了推理速度。没有灰色边框,YOLOv6 的性能会变差。假设该问题与马赛克增强中的灰色边框填充有关。进行了在最后一个时期关闭马赛克增强的实验(也称为淡入淡出策略)以进行验证。对此,改变了灰色边框的区域,将带有灰色边框的图像直接调整为目标图像大小。结合这两种策略,模型可以在不降低推理速度的情况下保持甚至提高性能。

2.5、量化与部署

对于工业部署,通常的做法是采用量化来进一步加快运行时间而不会对性能造成太大影响。训练后量化(PTQ)直接量化模型,只需要一个小的校准集。而量化感知训练(QAT)通过访问训练集进一步提高了性能,这通常与蒸馏结合使用。然而,由于在 YOLOv6 中大量使用了重参化块,以前的 PTQ 技术无法产生高性能,而在训练和推理期间在匹配假量化器时很难结合 QAT

1、Reparameterizing Optimizer

RepOptimizer 在每个优化步骤提出梯度重参化。该技术也很好地解决了基于重参化模型的量化问题。因此,以这种方式重建 YOLOv6 的重参化块,并使用 RepOptimizer 对其进行训练以获得对 PTQ 友好的权重。特征图的分布在很大程度上变窄了,这极大地有利于量化过程。

2、Sensitivity Analysis

通过将量化敏感操作部分转换为浮点计算来进一步提高 PTQ 性能。为了获得灵敏度分布,通常使用几个指标,均方误差 (MSE)、信噪比 (SNR) 和余弦相似度。通常为了比较,可以选择输出特征图(在激活某个层之后)来计算这些带有和不带量化的指标。作为替代方案,通过打开和关闭特定层的量化来计算验证 AP 也是可行的。

在使用 RepOptimizer 训练的 YOLOv6-S 模型上计算所有这些指标,并选择前 6 个敏感层以浮动运行。

3、使用 Channel-wise Distillation 进行量化感知训练

如果 PTQ 不足,建议使用量化感知训练 (QAT) 来提高量化性能。为了解决训练和推理过程中假量化器不一致的问题,有必要在 RepOptimizer 上构建 QAT。此外,通道蒸馏(后来称为 CW Distill)适用于 YOLOv6 框架,如图 5 所示。这也是一种自我蒸馏方法,其中教师网络是 FP32 精度的学生本身。

实验

消融实验

1、label assignment

2、损失函数

3、自蒸馏

4、Gray border of images

5、PTQ

6、QAT

SOTA对比

TensorRT部署实践对比

T4 GPU

V100 GPU

Diffusion Model 综述

Diffusion Models: A Comprehensive Survey of Methods and Applications来自加州大学&Google Research的Ming-Hsuan Yang、北京大学崔斌实验室以及CMU、UCLA、蒙特利尔Mila研究院等众研究团队,首次对现有的扩散生成模型(diffusion model)进行了全面的总结分析,从diffusion model算法细化分类、和其他五大生成模型的关联以及在七大领域中的应用等方面展开,最后提出了diffusion model的现有limitation和未来的发展方向

论文:https://arxiv.org/abs/2209.00796

摘自:AI科技评论

github链接:https://github.com/YangLing0818/Diffusion-Models-Papers-Survey-Taxonomy(扩散模型论文汇总)

介绍

扩散模型(diffusion models)是深度生成模型中新的SOTA。扩散模型在图片生成任务中超越了原SOTA:GAN,并且在诸多应用领域都有出色的表现,如计算机视觉,NLP、波形信号处理、多模态建模、分子图建模、时间序列建模、对抗性净化等。此外,扩散模型与其他研究领域有着密切的联系,如稳健学习、表示学习、强化学习。然而,原始的扩散模型也有缺点,它的采样速度慢,通常需要数千个评估步骤才能抽取一个样本;它的最大似然估计无法和基于似然的模型相比;它泛化到各种数据类型的能力较差。如今很多研究已经从实际应用的角度解决上述限制做出了许多努力,或从理论角度对模型能力进行了分析。然而,现在缺乏对扩散模型从算法到应用的最新进展的系统回顾。为了反映这一快速发展领域的进展,我们对扩散模型进行了首个全面综述。我们设想我们的工作将阐明扩散模型的设计考虑和先进方法,展示其在不同领域的应用,并指出未来的研究方向。此综述的概要如下图所示:

尽管diffusion model在各类任务中都有着优秀的表现,它仍还有自己的缺点,并有诸多研究对diffusion model进行了改善。为了系统地阐明diffusion model的研究进展,我们总结了原始扩散模型的三个主要缺点,采样速度慢,最大化似然差、数据泛化能力弱,并提出将的diffusion models改进研究分为对应的三类:采样速度提升、最大似然增强和数据泛化增强。我们首先说明改善的动机,再根据方法的特性将每个改进方向的研究进一步细化分类,从而清楚的展现方法之间的联系与区别。在此我们仅选取部分重要方法为例, 我们的工作中对每类方法都做了详细的介绍,内容如图所示:

在分析完三类扩散模型后,我们将介绍其他的五种生成模型GAN,VAE,Autoregressive model, Normalizing flow, Energy-based model。考虑到扩散模型的优良性质,研究者们已经根据其特性将diffusion model与其他生成模型结合,所以为了进一步展现diffusion model 的特点和改进工作,我们详细地介绍了diffusion model和其他生成模型的结合的工作并阐明了在原始生成模型上的改进之处。Diffusion model在诸多领域都有着优异的表现,并且考虑到不同领域的应用中diffusion model产生了不同的变形,我们系统地介绍了diffusion model的应用研究,其中包含如下领域:计算机视觉,NLP、波形信号处理、多模态建模、分子图建模、时间序列建模、对抗性净化。对于每个任务,我们定义了该任务并介绍利用扩散模型处理任务的工作,我们将本项工作的主要贡献总结如下:

  • 新的分类方法:我们对扩散模型和其应用提出了一种新的、系统的分类法。具体的我们将模型分为三类:采样速度增强、最大似然估计增强、数据泛化增强。进一步地,我们将扩散模型的应用分为七类:计算机视觉,NLP、波形信号处理、多模态建模、分子图建模、时间序列建模、对抗性净化。
  • 全面的回顾:我们首次全面地概述了现代扩散模型及其应用。我们展示了每种扩散模型的主要改进,和原始模型进行了必要的比较,并总结了相应的论文。对于扩散模型的每种类型的应用,我们展示了扩散模型要解决的主要问题,并说明它们如何解决这些问题。
  • 未来研究方向:我们对未来研究提出了开放型问题,并对扩散模型在算法和应用方面的未来发展提供了一些建议。

扩散模型基础

生成式建模的一个核心问题是模型的灵活性和可计算性之间的权衡。扩散模型的基本思想是正向扩散过程来系统地扰动数据中的分布,然后通过学习反向扩散过程恢复数据的分布,这样就了产生一个高度灵活且易于计算的生成模型。

1.Denoising Diffusion Probabilistic Models(DDPM)

一个DDPM由两个参数化马尔可夫链组成,并使用变分推断以在有限时间后生成与原始数据分布一致的样本。前向链的作用是扰动数据,它根据预先设计的噪声进度向数据逐渐加入高斯噪声,直到数据的分布趋于先验分布,即标准高斯分布。反向链从给定的先验开始并使用参数化的高斯转换核,学习逐步恢复原数据分布。用表示原始数据及其分布,则前向链的分布是可由下式表达:

这说明前向链是马尔可夫过程,是加入t步噪音后的样本,是事先给定的控制噪声进度的参数。当 趋于1时,可以近似认为服从标准高斯分布。当很小时,逆向过程的转移核可以近似认为也是高斯的:

我们可以将变分下界作为损失函数进行学习:

2.Score-Based Generative Models(SGM)

上述DDPM可以视作SGM的离散形式。SGM构造一个随机微分方程(SDE)来平滑的扰乱数据分布,将原始数据分布转化到已知的先验分布:

和一个相应的逆向SDE,来将先验分布变换回原始数据分布:

因此,要逆转扩散过程并生成数据,我们需要的唯一信息就是在每个时间点的分数函数。利用score-matching的技巧我们可以通过如下损失函数来学习分数函数:

对两种方法的进一步介绍和两者关系的介绍请参见我们的文章。原始扩散模型的三个主要缺点,采样速度慢,最大化似然差、数据泛化能力弱。最近许多研究都在解决这些缺点,因此我们将改进的扩散模型分为三类:采样速度提升、最大似然增强和数据泛化增强。在接下来的三、四、五节我们将对这三类模型进行详细的介绍。

采样加速方法

在应用时,为了让新样本的质量达到最佳,扩散模型往往需要进行成千上万步计算来获取一个新样本。这限制了diffusion model的实际应用价值,因为在实际应用时,我们往往需要产生大量的新样本,来为下一步处理提供材料。研究者们在提高diffusion model采样速度上进行了大量的研究。我们对这些研究进行了详细的阐述。我们将其细化分类为三种方法:Discretization Optimization,Non-Markovian Process,Partial Sampling。

1.Discretization Optimization

方法优化求解diffusion SDE的方法。因为现实中求解复杂SDE只能使用离散解来逼近真正的解,所以该类方法试图优化SDE的离散化方法,在保证样本质量的同时减少离散步数。SGM 提出了一个通用的方法来求解逆向过程,即对前向和后向过程采取相同的离散方法。如果给定了前向SDE的离散方式:

那么我们就可以以相同的方式离散化逆向SDE:

这种方法比朴素DDPM效果略好一点。进一步,SGM向SDE求解器中加入了一个矫正器,从而让每一步生成的样本都有正确的分布。在求解的每一步,求解器给出一个样本后,矫正器都使用马尔可夫链蒙特卡罗方法来矫正刚生成的样本的分布。实验表明向求解器中加入矫正器比直接增加求解器的步数效率更高。

2.Non-Markovian Process方法突破了原有Markovian Process的限制,其逆过程的每一步可以依赖更多以往的样本来进行预测新样本,所以在步长较大时也能做出较好的预测,从而加速采样过程。其中主要的工作DDIM,不再假设前向过程是马尔可夫过程,而是服从如下分布:

DDIM的采样过程可以视为离散化的神经常微分方程,其采样过程更高效,并且支持样本的内插。进一步的研究发现DDIM可以视作流形上扩散模型PNDM的特例。3.Partial Sampling方法通过在generation process中忽略一部分的时间节点,而只使用剩下的时间节点来生成样本,直接减少了采样时间。例如,Progressive Distillation从训练好的扩散模型中蒸馏出效率更高的扩散模型。对于训练好的一个扩散模型,Progressive Distillation会从新训练一个扩散模型,使新的扩散模型的一步对应于训练好的扩散模型的两步,这样新模型就可以省去老模型一半的采样过程。具体算法如下:

不断循环这个蒸馏过程就能让采样步骤指数级下降。

最大似然估计加强

扩散模型在最大似然估计的表现差于基于似然函数的生成模型,但最大化似然估计在诸多应用场景都有重要意义,比如图片压缩, 半监督学习, 对抗性净化。由于对数似然难以直接计算,研究主要集中在优化和分析变分下界(VLB)。我们对提高扩散模型最大似然估计的模型进行了详细的阐述。我们将其细化分类为三类方法:Objectives Designing,Noise Schedule Optimization,Learnable Reverse Variance。

1.Objectives Designing方法利用扩散 SDE推倒出生成数据的对数似然与分数函数匹配的损失函数的关系。这样通过适当设计损失函数,就可以最大化 VLB 和对数似然。Song et al. 证明了可以设计损失函数的权重函数,使得plug-in reverse SDE 生成样本的似然函数值小于等于损失函数值,即损失函数是似然函数的上界。分数函数拟合的损失函数如下:

我们只需将权重函数设为扩散系数g(t)即可让损失函数成为似然函数的VLB,即:

2.Noise Schedule Optimization通过设计或学习前向过程的噪声进度来增大VLB。VDM证明了当离散步数接近无穷时,损失函数完全由信噪比函数SNR(t)的端点决定:

那么在离散步数接近无穷时,可以通过学习信噪比函数SNR(t)的端点最优化VLB,而通过学习信噪比函数中间部分的函数值来实现模型其他方面的改进。

3.Learnable Reverse Variance方法学习反向过程的方差,从而较少拟合误差,可以有效地最大化VLB。Analytic-DPM证明,在DDPM和DDIM中存在反向过程中的最优期望和方差:

使用上述公式和训练好的分数函数,在给定前向过程的条件下,最优的VLB可以近似达到。

数据泛化增强

扩散模型假设数据存在于欧几里得空间,即具有平面几何形状的流形,并添加高斯噪声将不可避免地将数据转换为连续状态空间,所以扩散模型最初只能处理图片等连续性数据,直接应用离散数据或其他数据类型的效果较差。这限制了扩散模型的应用场景。数个研究工作将扩散模型推广到适用于其他数据类型的模型,我们对这些方法进行了详细地阐释。我们将其细化分类为两类方法:Feature Space Unification,Data-Dependent Transition Kernels。1.Feature Space Unification方法将数据转化到统一形式的latent space,然后再latent space上进行扩散。LSGM提出将数据通过VAE框架先转换到连续的latent space 上后再在其上进行扩散。这个方法的难点在于如何同时训练VAE和扩散模型。LSGM表明由于潜在先验是intractable的,分数匹配损失不再适用。LSGM直接使用VAE中传统的损失函数ELBO作为损失函数,并导出了ELBO和分数匹配的关系:

该式在忽略常数的意义下成立。通过参数化扩散过程中样本的分数函数,LSGM可以高效的学习和优化ELBO。

2.Data-Dependent Transition Kernels方法根据数据类型的特点设计diffusion process 中的transition kernels,使扩散模型可以直接应用于特定的数据类型。D3PM为离散型数据设计了transition kernel,可以设为lazy random-walk,absorbing state等。GEODIFF为3D分子图数据设计了平移-旋转不变的图神经网络,并且证明了具有不变性的初分布和transition kernel可以导出具有不变性的边缘分布。假设是一个平移-旋转变换,如:

那么生成的样本分布也有平移-旋转不变性:

和其他生成模型的联系

在下面的每个小节中,我们首先介绍其他五类重要的生成模型,并分析它们的优势和局限性。然后我们介绍了扩散模型是如何与它们联系起来的,并说明通过结合扩散模型来改进这些生成模型。VAE,GAN,Autoregressive model, Normalizing flow, Energy-based model和扩散模型的联系如下图所示:

  1. DDPM可以视作层次马尔可夫VAE(hierarchical Markovian VAE)。但DDPM和一般的VAE也有区别。DDPM作为VAE,它的encoder和decoder都服从高斯分布、有马尔科夫行;其隐变量的维数和数据维数相同;decoder的所有层都共用一个神经网络。
  2. DDPM可以帮助GAN解决训练不稳定的问题。因为数据是在高维空间中的低维流形中,所以GAN生成数据的分布和真实数据的分布重合度低,导致训练不稳定。扩散模型提供了一个系统地增加噪音的过程,通过扩散模型向生成的数据和真实数据添加噪音,然后将加入噪音的数据送入判别器,这样可以高效地解决GAN无法训练、训练不稳定的问题。
  3. Normalizing flow通过双射函数将数据转换到先验分布,这样的作法限制了Normalizing flow的表达能力,导致应用效果较差。类比扩散模型向encoder中加入噪声,可以增加Normalizing flow的表达能力,而从另一个视角看,这样的做法是将扩散模型推广到前向过程也可学习的模型。
  4. Autoregressive model在需要保证数据有一定的结构,这导致设计和参数化自回归模型非常困难。扩散模型的训练启发了自回归模型的训练,通过特定的训练方式避免了设计的困难。
  5. Energy-based model直接对原始数据的分布建模,但直接建模导致学习和采样都比较困难。通过使用扩散恢复似然,模型可以先对样本加入微小的噪声,再从有略微噪声的样本分布来推断原始样本的分布,使的学习和采样过程更简单和稳定。

扩散模型的应用

在本节中,我们分别介绍了扩散模型在计算机视觉、自然语言处理、波形信号处理、多模态学习、分子图生成、时间序列以及对抗学习等七大应用方向中的应用,并对每类应用中的方法进行了细分并解析。例如在计算机视觉中可以用diffusion model进行图像补全修复(RePaint):

在多模态任务中可以用diffusion model进行文本到图像的生成(GLIDE):

还可以在分子图生成中用diffusion model进行药物分子和蛋白质分子的生成(GeoDiff):

应用分类汇总见表:

未来研究方向

  1. 应用假设再检验。我们需要检查我们在应用中普遍接受的假设。例如,实践中普遍认为扩散模型的前向过程会将数据转换为标准高斯分布,但事实并非如此,更多的前向扩散步骤会使最终的样本分布与标准高斯分布更接近,与采样过程一致;但更多的前向扩散步骤也会使估计分数函数更加困难。理论的条件很难获得,因此在实践中操作中会导致理论和实践的不匹配。我们应该意识到这种情况并设计适当的扩散模型。
  2. 从离散时间到连续时间。由于扩散模型的灵活性,许多经验方法可以通过进一步分析得到加强。通过将离散时间的模型转化到对应的连续时间模型,然后再设计更多、更好的离散方法,这样的研究思路有前景。
  3. 新的生成过程。扩散模型通过两种主要方法生成样本:一是离散化反向扩散 SDE,然后通过离散的反向 SDE 生成样本;另一个是使用逆过程中马尔可夫性质对样本逐步去噪。然而,对于一些任务,在实践中很难应用这些方法来生成样本。因此,需要进一步研究新的生成过程和视角。
  4. 泛化到更复杂的场景和更多的研究领域。虽然目前diffusion model已经应用到多个场景中,但是大多数局限于单输入单输出的场景,将来可以考虑将其应用到更复杂的场景,比如text-to-audiovisual speech synthesis。也可以考虑和更多的研究领域相结合。

part2:【扩散模型笔记整理】从DDPM到Imagen

扩散模型(Diffusion Model)

1. 概述

  • 如图所示,扩散模型分两个过程:扩散(diffusion, 从x0到xT的过程逐步加入噪声)和去噪(denoise, 从xT到x0逐步去噪)。训练的时候,需要利用扩散加噪来生成训练样本;推理的时候,输入一个噪音,逐步去噪输出原始信号(比如图像、语音)。

参考文献:Denoising Diffusion Probabilistic Models

2. 扩散和去噪(Diffusion&Denoise)

  • 首先介绍一下高斯分布的表达,记作X∽N(μ,σ2):

扩散过程每一步都加入一个方差为βt∈(0,1)的高斯噪声可以用马尔科夫链来表示:

  • 这里的βt是一个0到1的等比序列(β0=0),此时表示原始图像;第T步的时候,βt=1,表示标准高斯噪声N∽(0,I)。因而实际上扩散过程是一个从原始图像变为标准高斯分布的过程。加噪和高斯采样等价,无非就是改变了一下高斯采样的均值中心点。
  • 实际训练的时候,我们可以直接用下面的公式一次性算出某一步的加噪图片作为训练素材,无需逐步迭代。
  • 去噪过程和扩散过程反过来:从一张随机采样的高斯噪声图片逐步去噪得到我们想要生成的图像。表达式:
  • 去噪过程,需要用模型预测加入的高斯噪声,得到原始的无噪声的图像。上式表示,利用模型算出原始第n步的未加噪图像,实质上只要算出均值和方差,再做一个采样得到原始图像。而为了算出μ,我们需要预测出噪声ϵ,反推出原始图像的均值中心,方差项可以由网络预测也可以取常数(前者效果好)。下节将介绍模型的训练和推理过程。

3. 训练和采样(Training&Sampling)

  • 训练其实就是扩散过程,而采样其实就是去噪过程。
  • 算法如上图所示,训练training的过程实际上是随机采第t步的加噪图像,输入带噪图片以及步数t,模型预测噪声ϵ,模型训练目标:预测噪声与实际加入噪声的误差越小越好。
  • 采样sampling的过程(生成过程)为:将有噪声的图像(第一张图像为随机采样的高斯分布噪声)减去模型预测的噪声(噪声前面的其它参数可以由上面加噪的过程反向推导出来)不断把噪声去掉以恢复出原始的图像。
  • 方差项σ也可以由模型来预测。

参考文献: Improved Denoising Diffusion Probabilistic Models

引导扩散模型(Guided Diffusion)

前文已经讲述扩散模型的原理,然而我们随机输入一张高斯噪声显然不能按照人的意愿生成我们想要的内容,因而需要额外的引导guidance以得到我们需要的图像。一种想法是使用外部模型(分类器or广义的判别器)的输出作为引导条件来指导扩散模型的去噪过程,从而得到我们想要的输出;还有一种则比较直观一些:我们直接把我们想要的引导条件condition也作为模型输入的一部分,从而让扩散模型见到这个条件后就可以直接生成我们想要的内容。

下文将讲解classifier guidance和semantic guidance diffusion model(后者包括前者,前者是比较简单的一个应用),除此之外,由于额外的判别器会拖慢推理速度,因此后来有人提出了 classifier-free guidance diffusion model来替代前面的那种方案,也即把条件作为模型的输入,直接生成我们需要的图像。

1. Classifier Guidance Diffusion Model

  • 这种方法不用额外训练扩散模型,直接在原有训练好的扩散模型上,通过外部的分类器来引导生成期望的图像。唯一需要改动的地方其实只有sampling过程中的高斯采样的均值,也即采样过程中,期望噪声图像的采样中心越靠近判别器引导的条件越好。
  • 上图总结了采样算法。Algorithm 1和 Algorithm 2其实是等价的(1是直接预测均值和方差,2是预测噪声的误差)。直接看Algorithm 1可知,实质上改变的只有高斯分布的均值中心,将扩散方向“引导”成我们想要的内容。具体而言,用分类模型pϕ对生成的图片进行分类,得到预测分数与目标类别的交叉熵,将其对带噪图像求梯度用梯度引导下一步的生成采样。(实际使用的时候,需要把这个分类器也在带噪数据额外训练一下)
  • 因为我们实际使用的模型预测的是噪音,实际计算为Algorithm 2,可以由1推导而来。(具体推导过程可以参考文献)

参考文献:Diffusion Models Beat GANs on Image Synthesis

2. Semantic Guidance Diffusion

  • 介绍完前面的 classifier guidance后,显然我们可以把分类器替换成其它任意的判别器,也即更换引导条件,从而实现利用不同的语义信息来指导扩散模型的去噪过程。比如说,我们可以实现text-guidance和image-guidance等。
  • 实质上就是把classifier guidance的条件推广,表达为:
  • Fϕ表示就是新的引导条件,这里展示的是分类的,其实也可以换成相似度之类的分数指标。具体可以有以下的例子:图像引导、文本引导、图像+文本引导。


参考文献:More Control for Free! Image Synthesis with Semantic Diffusion Guidance

3. Classifier-Free Guidance Diffusion

  • 正如前文提到的,额外引入一个网络来指导,推理的时候比较复杂(扩散模型需要反复迭代,每次迭代都需要额外算一个分数)。然而,直接将引导条件作为模型的输入,直到Classifier-Free Diffusion Guidance被提出前似乎效果也一般般。Classifier-Free Diffusion Guidance这篇文章的贡献就是提出了一个等价的结构替换掉了外部的判别器,从而可以直接用一个扩散模型来做条件生成任务。
  • 实际做法只是改变了模型输入的内容,有conditional(除了随机高斯噪声输入外,把引导信息的embedding也加进来)和unconditional 的 sample输入。两种输入都会被送到同一个diffusion model从而让其能够具有无条件和有条件生成的能力。得到这两种输入的输出后,就可以用来引导扩散模型进行训练。
  • 回忆一下前面的 classifier guidance的噪音更新方式:
  • 实质上,这个classifier-free用另一个近似的等价结构替换掉了后面那一项:
  • 其中,ϵθ(xt,y) 表示conditional的输入,而ϵθ(xt)则表示unconditional输入,用这两项之差乘以一个系数来替换掉原来的那项。至于为什么可以这么直接替换,其实可以用贝叶斯公式推导而来:
  • 因而,实际上这个过程就训练了一个 implicit classifier,从而移除外部的分类器。

参考文献:Classifier-Free Diffusion Guidance

GLIDE

  • 这篇文章主要就是用到了前面所说的classifier-free扩散模型,只不过把输入的condition换成了文本信息,从而实现文本生成图像,此外还利用diffusion model实现了超分辨率。一些效果展示如下,可以看到,其实已经可以生成一些比较逼真的图片了。
  • 具体可以表达为:
  • 这里无非就是把原来的label y换成了 caption,实际上就是运用了足够量的image-text pair从而可以把caption当作是某种程度上的label。(随机替换为空序列以实现unconditional的训练方式)
动图封面
  • 由于此时的生成图像质量一般般,文章也提供了图像编辑的方式(具体操作为:将选中区域mask掉,将图像也作为一个condition连同文本输入到模型中去):

DALL·E 2

概况

  • 第一版DALL·E用的是GAN+CLIP重排序的结构。
  • DALL·E 2可以把diffusion model和CLIP结合在一起,生成效果十分惊艳,可以直接去官网浏览一下。DALL·E 2 (openai.com)
  • 包括prior网络用于将caption转换为CLIP image embedding,一个decoder把image embedding作为condition来生成图像。prior有两种:一种是autoregressive model、一种是diffusion model(后者效果更好一些);decoder就是diffusion model。总之,这里相比前面的变化主要在于加入了prior,以及把condition换成了CLIP的embedding。

Decoder

  • 具体而言,把CLIP image embedding作为condition输入到diffusion model中,同时把CLIP image embedding映射成4个额外的tokens接到GLIDE text encoder的输出。
  • 除了用于生成图像的diffusion model,这部分还有2个额外用于超分辨率的diffusion model,生成高清图像。

Prior

这部分的内容是为了将caption y转换为 CLIP image embedding,以用于后面decoder的图像生成。

  • 一种是auto-regressive model,将image embedding转换为一串离散的编码,并且基于condition caption y自回归地预测。(这里不一定要condition on caption(GLIDE的方法——额外用一个Transformer处理caption),也可以condition on CLIP text embedding)。此外,这里还用到了PCA来降维,降低运算复杂度。
  • 一种是diffusion model。这是一个decoder-only Transformer,输入是encoded text+CLIP text embedding+noised CLIP image embedding+额外token(类似class embedding)输入,其输出一个unnoised CLIP image embedding(取那个额外的embedding)。

Variations

  • 这部分是为了给一张图,生成相似的图像。做法很简单:用CLIP把图像编码,把这个CLIP image embedding作为condition引导decoder生成图像。除此之外,还可以对2张图像的CLIP embedding进行插值,以实现风格迁移。( spherical interpolation 几何球面线性插值)。这里证明了CLIP语义空间的可解释性

量化结果

  • 本文方法又称unCLIP(其实本质上就是把CLIP生成的embedding进行decode),相比GLIDE有小幅的提高。

Paper List

  1. (DDPM) Denoising Diffusion Probabilistic Models. NIPS 20. (Diffusion and deep-learning-based 图像生成开山之作)
  2. More Control for Free! Image Synthesis with Semantic Diffusion Guidance. arXiv 21. (对DDIM进行了推广,引入了一般形式的判别器引导)
  3. Denoising Diffusion Implicit Models. ICLR 21. (提出了一种新的sampling的方法,可以通过改变eta来skip一些step,进而达到加速sampling的目的)
  4. Improved denoising diffusion probabilistic models. ICML 21.
  5. Classifier-Free Diffusion Guidance. NIPSW 21. (引入了等价结构替代了分类器引导)
  6. GLIDE: Towards Photorealistic Image Generation and Editing with Text-Guided Diffusion Models. ICML 22.
  7. Hierarchical Text-Conditional Image Generation with CLIP Latents. NIPS 22 在投. (DALL-E 2)
  8. Photorealistic Text-to-Image Diffusion Models with Deep Language Understanding. NIPS 22 在投. (Imagen, SOTA)
  9. High-Resolution Image Synthesis with Latent Diffusion Models. CVPR 22. (隐空间LDM)