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

近年来比较牛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的表述能力。啥都不说,先上图,看图说话:
    • 这里写图片描述 图片说明:此图可以用如下流程进行表述: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 1 16 ,这样的话,会减少超参数数量,如果使用的是 116 1 16 的话,那超参数数量大概是只用一层fc的 18 1 8
    • 这就是SENet啦,现在我们将ResNet和SENet的优势进行结合,如图: 这里写图片描述 图片说明:左侧是ResNet的key Block,右侧是SE-ResNet的key Block,由此就有了SENet和ResNet的综合体
    • 接下来说一下实验。使用的ImageNet数据集,对比几种经典Classification网络和当前的SENet,效果如下:这里写图片描述 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最大限度的流向网络后层,使得网络最大限度的利用原始图像信息。还是一样,啥都不说,先上图,看图说话:这里写图片描述 图片说明: 网络第L层的输出的feature maps,是之后所有网络层的输入,假设 第L层的输入feature map个数表示为 Li L i ,我们的输入为RGB(channel=3),输入为第0层,而且每次Conv之后,会产生4个feature map,于是我们知道第I层的输入feature map个数为 Li=L0+4(L1) L i = L 0 + 4 ∗ ( L − 1 )
    • 由上图我们知道,我们不能通过这种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。
    • 现在看一下网络的整体结构:这里写图片描述 图片说明:我们的网络=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,如图所示:这里写图片描述 图片说明:左侧是ResNet的key block,网络通过identity mapping方式,得到 L(xi)=L(xi1)+x L ( x i ) = L ( x i − 1 ) + 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结构,如图:这里写图片描述 图片说明: 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的提高之处:这里写图片描述 两个模型具使用基本相同的复杂程度,可以看出,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,原创文章,转载请保留原文地址、作者等信息

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值