欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

综述 近年来比较牛X的Classification Architecture

程序员文章站 2022-04-05 15:47:10
...

近年来比较牛X的图像分类网络主要有Alexnet、Googlenet、vgg、resnet、DenseNet、SENet,以及各种他们的变种形式,这里简单介绍几个

  • Squeeze-and-Excitation Networks(SENet):这是2017年ILSVRC classification performance最佳的深度学习网络。
    • 此网络不同于其他网络主要体现在在Conv+BN+ReLU得到feature map之后,增加了对feature map的权重,旨在增强feature map的表述能力。啥都不说,先上图,看图说话:
    • 综述 近年来比较牛X的Classification Architecture 图片说明:此图可以用如下流程进行表述:Conv+BN+ReLU–>feature map(w * h * c)–>global average pooling(1 * 1 * c),–>fc(1 * 1 * c/16)–>ReLU–>fc(1 * 1 * c)–>sigmoid(1 * 1 * c),而后将此feature maps和经过sigmoid之后的结果进行相乘,得到我们想要的feature map,这就是SENet的关键block。下面有几个问题,大概阐述一下:
      • 1.为什么要使用2个fc?作者Jie Hu指出,之所以使用2个fc,完全是为了增强SENet模块的非线性表达能力。(当时做的时候,在想为什么不用3个甚至更多的fc呢?事实证明,2层的网络,只要第二层(不包含输入)使用的是非线性**但愿,则可以逼近任意连续函数)
      • 2.为什么这里第一层fc之后接的是c/16的单元个数?这个是一个非常重要的hyperparameter,paper原话’In particular, we found that setting r = 16 achieved a good tradeoff between accuracy and complexity and consequently’,意思简单明了,,,那就是试出来的,试了很多值,挑选了一个最好值,那就是channle的116,这样的话,会减少超参数数量,如果使用的是116的话,那超参数数量大概是只用一层fc的18
    • 这就是SENet啦,现在我们将ResNet和SENet的优势进行结合,如图: 综述 近年来比较牛X的Classification Architecture 图片说明:左侧是ResNet的key Block,右侧是SE-ResNet的key Block,由此就有了SENet和ResNet的综合体
    • 接下来说一下实验。使用的ImageNet数据集,对比几种经典Classification网络和当前的SENet,效果如下:综述 近年来比较牛X的Classification Architecture crop原图为224 * 224/320 * 320/229 * 229,由图知SENet达到了相对的min error,拿到了Classification的第一名。
    • 现在写一写SENet key block的code:
# Use nn.Conv2d instead of nn.Linear + 其中的c为feature map(w * h * c)经过global avergae pooling得到的1 * 1 * c的结果
self.fc1 = nn.Conv2d(c, planes//16, kernel_size=1)
self.fc2 = nn.Conv2d(c//16, planes, kernel_size=1)
--------------------------##########--------------------------
# Squeeze
w = F.avg_pool2d(out, out.size(2))
w = F.relu(self.fc1(w))
w = F.sigmoid(self.fc2(w))
# Excitation
out = out * w  # New broadcasting feature from v0.2!

  • (Densely Connected Convolutional Networks)Densenet:当初看得时候,给我一种 这就是抄的嘛 的感觉,,,完全借鉴了ResNet,不够这种思想还是很值得学习的,下面我们简单学习一下。
    • 此网络的主要贡献点在于使得origin feature map最大限度的流向网络后层,使得网络最大限度的利用原始图像信息。还是一样,啥都不说,先上图,看图说话:综述 近年来比较牛X的Classification Architecture 图片说明: 网络第L层的输出的feature maps,是之后所有网络层的输入,假设 第L层的输入feature map个数表示为Li,我们的输入为RGB(channel=3),输入为第0层,而且每次Conv之后,会产生4个feature map,于是我们知道第I层的输入feature map个数为Li=L0+4(L1)
    • 由上图我们知道,我们不能通过这种Dense Block改变feature map的大小,由此我们可以在Dense Block之间插入专门用于降低feature map size的结构,我们称之为transition。这种结构由BN+ReLU+Conv+avergae+pooling构成,我们通过pooling改变feature map的大小。
    • 论文中还提出,在Dense Block中使用1*1的Conv,模型的性能会有较大幅度的提高,论文中称为Bottleneck,结构为: BN–>ReLU–>Conv(1 to 1)–>BN–>ReLU–>Conv(3 to 3) version,这种结构会较大幅度的提高模型的performance。
    • 现在看一下网络的整体结构:综述 近年来比较牛X的Classification Architecture 图片说明:我们的网络=Dense Block+Transition Block完成。其中Dense Block用于 提取特征+组合特征;Transition Block用于减小feature map的size。
    • 现在写一写Dense key block的code:

class Bottleneck(nn.Module):
    def __init__(self, in_planes, growth_rate):
        super(Bottleneck, self).__init__()
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.conv1 = nn.Conv2d(in_planes, 4*growth_rate, kernel_size=1, bias=False)
        self.bn2 = nn.BatchNorm2d(4*growth_rate)
        self.conv2 = nn.Conv2d(4*growth_rate, growth_rate, kernel_size=3, padding=1, bias=False)

    def forward(self, x):
        out = self.conv1(F.relu(self.bn1(x)))
        out = self.conv2(F.relu(self.bn2(out)))
        out = torch.cat([out,x], 1)
        return out


class Transition(nn.Module):
    def __init__(self, in_planes, out_planes):
        super(Transition, self).__init__()
        self.bn = nn.BatchNorm2d(in_planes)
        self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=1, bias=False)

    def forward(self, x):
        out = self.conv(F.relu(self.bn(x)))
        out = F.avg_pool2d(out, 2)
        return out

  • Aggregated Residual Transformations for Deep Neural Networks(ResNeXt):凯明大神入驻Facebook AI lab之后,继续升级自己的经典ResNet,提出了ResNext,只需要较少的超参数,通过采用分支同构的网络结构,使得模型性能进一步提升。提出了一个cardinality的概念(不同于深度和宽度),可以粗浅的理解为group的意思。
    • 自2012年以来,随着任务越来越复杂,人们往往通过设计出更深、更宽的网络结构来解决遇到的挑战。但网络结构的加深、加宽无疑会使得model更难训练、开销更大,于是作者提出了一种新的结构,使得在不增加模型复杂度的情况下,提高模型的泛化能力,这种结构就是ResNext。
    • ResNext是ResNet的升级版,我们先看下两种网络的key block,如图所示:综述 近年来比较牛X的Classification Architecture 图片说明:左侧是ResNet的key block,网络通过identity mapping方式,得到L(xi)=L(xi1)+x,极大程度上在网络上保留了输入图像的信息,而后的DenseNet也借鉴了这种思想;右侧就是ResNext的key block,使用split-transform-merge的结构,假设第L层得到w * h * c的feature map,这里的c=256,而后通过32组(1 * 1的卷积[4个卷积核]+3 * 3的卷积[4个卷积核]+1 * 1的卷积核[256个卷积核])将32组进行组合,然后再和本层的输入(w * h * c的feature map)进行组合,得到最终结果。这里的cardinality=32,32组同构子拓展结构完全相同,论文中提出是为了降低设计复杂性。提出这种类似于group的概念真的可以提高网路的性能么?原文中指出:Experiments demonstrate that increasing cardinality is a more effective way of gaining accuracy than going deeper or wider.实验证明,增加cardinality比单纯deeper or wider网络更加有效,针对于acc指标。
    • 之后作者提出了3种不同ResNext的Key block结构,如图:综述 近年来比较牛X的Classification Architecture 图片说明: 3.a已经在上面说过了,不在赘述;3.b是和3.a的不同之处在于key block经过的是2层卷积,而后将32组w * h * 4的feature map进行concatenate(理解为 拼接),而后再进行卷积;3.c使用了group,得到w * h * c(128)之后,将128个feature map分为32组,每组4个feature map,这32组分别进行卷积(卷积核为3 * 3 * 4,这也是和ResNet的主要不同之处),而后进行拼接,再进行卷积操作。
    • 作者之处,3.a,3.b,3.c三种结构是等价的,而且通过是实验进行了证明,除此之外,3.c网络结构较为简练且速度较快,在之后的实验中,一直采用3.c的这种结构。接下来我们看下ResNext较ResNet的提高之处:综述 近年来比较牛X的Classification Architecture 两个模型具使用基本相同的复杂程度,可以看出,ResNext在使用较少参数的情况下,达到了更好的准确性。
    • 现在贴下ResNext key block的代码:
self.conv1 = nn.Conv2d(in_planes, group_width, kernel_size=1, bias=False)
self.bn1 = nn.BatchNorm2d(group_width)
# groups 完成group的骚操作
self.conv2 = nn.Conv2d(group_width, group_width, kernel_size=3, stride=stride, padding=1, groups=cardinality, bias=False)
self.bn2 = nn.BatchNorm2d(group_width)
self.conv3 = nn.Conv2d(group_width, self.expansion*group_width, kernel_size=1, bias=False)
self.bn3 = nn.BatchNorm2d(self.expansion*group_width)
  • OK

作者:gengmiao 时间:2018.05.20,原创文章,转载请保留原文地址、作者等信息