美文网首页
『Going deeper with convolutions』

『Going deeper with convolutions』

作者: ktulu7 | 来源:发表于2018-12-21 22:58 被阅读0次

    一 为什么读这篇

    大名鼎鼎的Inception-v1原文,开创了CV领域的Inception派系,本来想先读完ResNet系列的,不过考虑到后续ResNet都有借鉴Inception的地方,加上这篇出现的时间又比较早(2014年9月)所以先读这篇,把Inception相关概念都搞清楚了。

    二 截止阅读时这篇论文的引用次数

    2018.12.16 10673次。可以媲美后出的ResNet了。

    三 相关背景介绍

    2014年9月刊发于arXiv。本文的一作Christian Szegedy就比较传奇了,原本是数学家,从事逻辑电路的设计,后来转行从事深度学习,凭借在数学上的深厚功底,成为GoogleLeNet架构设计者。三作贾扬清也是传奇大神,caffe的作者,先后在Google Brain和FAIR混。

    四 关键词

    Inception v1

    GoogLeNet 22层

    五 论文的主要贡献

    1 开创了Inception派系。

    2 提出用密集块来近似局部最优稀疏结构

    六 详细解读

    1 介绍

    Inception架构的主要特点是提升了网络内计算资源的利用率。通过精心设计实现了网络宽度和深度的增加,同时保持其计算量不变。架构设计基于赫布理论多尺度处理

    GoogLeNet比AlexNet少12倍的参数量,准确率却更高。另外本文不仅考虑准确率,还注重功耗和内存使用。在预测时只有15亿次的乘法加法操作,所以不仅可以用于学术,现实世界也可以用。

    Inception的名字来源于盗梦空间中『we need to go deeper』的梗,而架构是受『Network in network』的启发而来。

    2 相关工作

    从LeNet-5开始,CNN的发展倾向于堆叠更多的层,增加层的大小,同时使用dropout来避免过拟合。Inception model受『primate visual cortex』的启发,使用一系列固定的尺寸不一的盖波滤波器来处理多尺度,所不同的是,滤波器的参数是通过学习得到的。通过重复多个Inception层,得到一个22层深度的GoogLeNet。

    GoogLeNet架构重度使用了『Network-in-Network』提出的1x1卷积层,主要用于降维以消除计算瓶颈(bottleneck),因为计算瓶颈会限制网络的规模。这样做不仅可以增加深度,还可以增加宽度,同时性能还不会显著下降。

    当前R-CNN是最好的目标检测方法,它把整个目标检测问题分解为两个问题,第一阶段得到与类别无关的候选区域,第二阶段对这些候选区域进行分类。

    3 动机和高层次的考虑

    本节主要介绍一些比较『远』的理论机制,涉及生物神经学,硬件资源的限制,稀疏,稠密等。。

    提升深度学习网络最直接的方式就是增加其尺寸,包括增加深度和宽度。但是有两个缺陷,第一个缺陷是更大的尺寸意味着更多的参数,在训练集有限时会更容易过拟合。第二个缺陷是均匀增加网络尺寸将急剧增加计算资源的使用。如果增加的容量是无效的将导致大量的计算被浪费(例如,大多数权重最终接近于零)。因为实际中计算资源是有限的,所以更有效的计算资源分布倾向于有区分的增加尺寸。

    解决这两个问题的根本方法是最终从完全连接迁移到稀疏连接的架构,甚至是在卷积内部。

    这里提出了赫布理论,表示没看懂。。

    4 架构细节

    Inception架构的主要思想是如何通过容易获得的密集组件进行近似和覆盖来找出卷积视觉网络中的最佳局部稀疏结构。为了避免『patch-alignment』问题,Inception架构将滤波器尺寸限制为1x1,3x3,5x5,然而这更多基于传统而非必须。另外,当前pooling运算在SOTA的网络中都成功运用,所以加它也没错。。。见图2-a。

    inception_v1-fig2.png

    naive版本的Inception模块主要的问题是,有太多的滤波器了。将导致计算爆炸。

    第二个核心理念是明智地使用降维和投影,否则所需的计算会增加的太多。这也是基于embeddings的成功:用低维度的embeddings包含大量的信息。也就是在使用昂贵的3x3和5x5卷积前用1x1卷积来减少计算。见图2-b。

    该架构的优势之一在于它可以在每个阶段显著地增加单元的数量,而不会出现不可控的计算复杂度的爆炸。另一个优势在于它与直觉相一致,即视觉信息应该以各种尺度处理然后再聚合,以便下一阶段可以同时从不同尺度抽取特征。

    5 GoogLeNet

    GoogLeNet是ILSVRC14的队名,也是对LeNet5的致敬。

    inception_v1-table1.png

    所有的卷积,包括Inception里的,都用ReLU。输入图像为224x224。"#3x3","#5x5"表示用于降维的1x1滤波器的个数。

    如果只算参数层的话是22层(算pooling则为27层)。

    中间层生成的特征非常有区分性。所以给中间层(这里是Inception4a和4d后)也接了个分类器,并将损失乘上0.3的权重加到总损失里,不过在预测时把这些辅助网络给砍掉(这也可以。。)。以上是为了解决梯度消失问题Inception想出的办法。

    [站外图片上传中...(image-4b9e07-1545449123533)]

    6 训练方法

    用DistBelief框架实现。在CPU上跑的。。。用momentum为0.9的SGD训练,学习率每8个epoch减少4%。

    作者采用了一堆策略,也很实诚的表示到底哪个真正有用他们也不知道。。。

    不过提到一点,说是效果非常好。『对图像的各种尺寸进行采样,其尺寸均匀地分布在8%和100%之间,并且纵横比在3/4和4/3之间随机选择』。

    7 ILSVRC2014分类挑战赛设置和结果

    测试时的技巧

    1 独立训练了7个版本的GoogLeNet(包括一个更宽的版本),之后ensemble。这些模型用相同的初始化值,同样的学习率衰减策略,仅仅在样本采样时增加了随机性。

    2 更激进的crop策略。把图像缩放到短边为256,288,320,352总共4个尺度的大小。从上中下(或左中右)中采样正方形。对每个正方形,取4个角点和中央大小为224的crop,同时其镜像版本。这样一个图像就能得到4x3x6x2=144个crop。

    3 平均多个crop的softmax概率

    总结下来,也就是用ensemble加tta。

    inception_v1-table2.png inception_v1-table3.png

    从原来的单模没tta的10.07%硬是干到了6.67%,你能说tricks不重要?

    8 ILSVRC2014检测挑战赛设置和结果

    200个类,IOU>0.5算对,用mAP衡量。

    9 总结

    本文证明了通过易于获得的密集块来近似预期最优稀疏结构是可行的。与较浅和较窄的网络相比,这种方法的主要优点在于适度增加计算量的同时效果获得了明显的提升。

    七 读后感

    扫了一眼,全文没一个公式,仔细看完,也是全文没公式,你敢信。。

    分类网络架构为了证明其优越性,都会拿目标检测来证明。

    看整个结构,感觉本文很简单啊。。

    感觉没有ResNet读着舒服。难道是因为何恺明是国人写英语的缘故。。

    八 补充

    https://medium.com/coinmonks/paper-review-of-googlenet-inception-v1-winner-of-ilsvlc-2014-image-classification-c2b3565a64e7

    https://towardsdatascience.com/history-of-convolutional-blocks-in-simple-code-96a7ddceac0c

    def conv(x, f, k=3, s=1, p='same', d=1, a='relu'):
        return Conv2D(filters=f, kernel_size=k, strides=s, 
                      padding=p, dilation_rate=d, activation=a)(x)
    def dense(x, f, a='relu'):
        return Dense(f, activation=a)(x)
    def maxpool(x, k=2, s=2, p='same'):
        return MaxPooling2D(pool_size=k, strides=s, padding=p)(x)
    def avgpool(x, k=2, s=2, p='same'):
        return AveragePooling2D(pool_size=k, strides=s, padding=p)(x)
    def gavgpool(x):
        return GlobalAveragePooling2D()(x)
    def sepconv(x, f, k=3, s=1, p='same', d=1, a='relu'):
        return SeparableConv2D(filters=f, kernel_size=k, strides=s, 
                               padding=p, dilation_rate=d, activation=a)(x)
    
    def bottleneck(x, f=32, r=4):
        x = conv(x, f // r, k=1)
        x = conv(x, f // r, k=3)
        return conv(x, f, k=1)
    
    def naive_inception_module(x, f=32):
        a = conv(x, f, k=1)
        b = conv(x, f, k=3)
        c = conv(x, f, k=5)
        d = maxpool(x, k=3, s=1)
        return concatenate([a, b, c, d])
    
    def incepiton_module(x, f=32, r=4):
        a = conv(x, f, k=1)
        b = conv(x, f // r, k=1)
        b = conv(b, f, k=3)
        c = conv(x, f // r, k=1)
        c = conv(c, f, k=5)
        d = maxpool(x, k=3, s=1)
        d = conv(d, f, k=1)
        return concatenate([a, b, c, d])
    

    相关文章

      网友评论

          本文标题:『Going deeper with convolutions』

          本文链接:https://www.haomeiwen.com/subject/nydbkqtx.html