转:

SENet详解及Keras复现代码

论文地址:https://arxiv.org/pdf/1709.01507.pdf

代码地址:https://github.com/hujie-frank/SENet

1、通道间的特征关系

近些年来,卷积神经网络在很多领域上都取得了巨大的突破。而卷积核作为卷积神经网络的核心,通常被看做是在局部感受野上,将空间上(spatial)的信息和特征维度上(channel-wise)的信息进行聚合的信息聚合体。卷积神经网络由一系列卷积层、非线性层和下采样层构成,这样它们能够从全局感受野上去捕获图像的特征来进行图像的描述。

我们可以看到,已经有很多工作在空间维度上来提升网络的性能。那么很自然想到,网络是否可以从其他层面来考虑去提升性能,比如考虑特征通道之间的关系?论文的作者就是基于这一点并且提出了Squeeze-and-Excitation Networks(简称 SENet)。作者并不希望引入一个新的维度来进行特征通道间的融合,而是采用一种全新的特征重标定策略。简单来说,就是通过增加一条分支,自动获取到每个通道的重要程度,然后依照这个重要程度去提升有用的信息,同时抑制对当前任务用处不大的特征。

上图是SE模块的示意图。给定一个输入X,其通道数维C’,经过一系列卷积等变换后得到一个通道数维C的特征。接下来的结构有点类似ResNet,但又与ResNet有很大不同。

首先是Squeeze操作,我们顺着空间维度来进行特征压缩,将每个二维特征通道变换成一个实数,这个实数某种程度上具有全局感受野,并且输出和输入的通道数是一样的。它表征着在特征通道上响应的全局分布,而且使得靠近输入的层也可以获得全局的感受野,这一点在很多任务中都是非常有用的。

其次是Excitation操作,他是类似于RNN中门的机制,通过参数W来为每个特征通道生成权重,其中参数W将被用来控制U中每个通道的重要性。

最后一个是Reweight的操作,我们将Excitation的输出权重看做是特征选择后每个特征通道的重要性,然后通过乘法逐通道加权到原来的特征U上,完成在通道维度上的特征重标定。

2、具体的网络结构

由于SE模块并不像GoogLeNet和ResNet一样,提出了全新的网络结构,所以它是可以很灵活的嵌入到已有主流网络中去。

上图左边是将SE模块嵌入到Inception结构的一个示例。

这里的Global pooling对应着Squeeze操作,它将输入特征层的维度压缩至1 x 1 x C。紧接着两个全连接层组成一个Bottleneck结构去建模通道间的相关性,并且最终输出的维度信息保持不变,为1 x 1 x C。

我们可以看到第一个全连接层使用了ReLU作为激活函数,第二个层采用了Sigmoid的作为激活函数。而我们知道Sigmoid会变量映射到0,1之间,也就是说有用的特征通过SE模块让他更偏向于1了,同时无用的特征也更接近0了,那么通过最后Scale操作,将输出权重与原始特征的每个通道逐乘也就增益了原始通道有用的特征,抑制了无用特征。

为什么采用两个全连接层而不是一个的原因在于:

  1. 通过ReLU可以获得更多的非线性
  2. 引入r参数可以减少参数量和计算量

除此之外,SE模块也可以嵌入到含有跨层连接的网络中去,上图右边就是将SE嵌入到模块中的一个例子,原理、操作基本和SE-Inception一样,只不过是在最后的Addition前对分支上Residual的特征进行重标定。

目前大多数的主流网络都是基于这两种类似的单元通过 repeat 方式叠加来构造的。由此可见,SE 模块可以嵌入到现在几乎所有的网络结构中。通过在原始网络结构的 building block 单元中嵌入 SE 模块,我们可以获得不同种类的 SENet。如 SE-BN-Inception、SE-ResNet、SE-ReNeXt、SE-Inception-ResNet-v2 等等。

3、实验结果

论文中给出了ResNet、ResNeXt等在当时比较常见的网络对比结果。深度学习经过几年的发展,在数据增强上也有了新的突破,为了公平起见,作者将网络又重新实现了一遍并且采用了同样的数据增强方式。结果如下图所示:

结合试验结果和上面的介绍来看,我们可以发现SENet的构造非常简单,不需要引入新的函数或层。对比原来的网络,仅仅只需要增加2%-10%的参数,就能将误差降低0.4-1.1左右。

4、更多的尝试

参数r的调节

我们在第一个全连接中引入了参数r,使得第一个全连接层的通道数减少,整体呈现一个瓶颈状的结构。作者的试验结果发现r=8时会有一个比较好的效果。

Pooling的方式


对于空间维度的压缩方式,作者尝试了Global Max Pooling和Global Average Pooling两种方式,无论是top-1还是top-5,结果都表明,AvgPool效果会更好。

激活函数的选择


接下来是最后一个全连接层激活函数的选择,用tanh替换sigmoid会略微恶化性能,而使用ReLU会显著恶化,实际上会导致SE-ResNet-50的性能低于ResNet-50基线。这表明,为了使SE块有效,激活函数的选择是很重要的。

SE Block添加的位置


作者还对SE模块添加的位置做了对比,在top-5上在越靠后的Stage上填加SE模块比在越靠前的Stage上添加效果要好,当然如果在所有Stage都添加效果是最好的。

SE的四种结构


最后是对SE模块的结构进行了对比:

​ (a) 普通的残差
​ (b) 标准的SE模块
​ 先进行SE再进行残差
​ (d) 先完成残差计算再进行SE模块计算
​ (e) 在跨层连接上完成SE模块计算


从结果上看,是SE-PRE的结构略胜一筹,但个人觉得只是在ResNet-50上对比了一下还不具有说服力。但是无论是什么结构都会提高ResNet的准确率,说明SE模块是有起作用的。

5、总结

SENet作为ImageNet竞赛的最后一届图像识别冠军,作者是付出了很多的时间,在网络架构上做了大量的尝试和实验,论文中还有些细节没有在本文中展开解释,读者可以下载论文详细阅读。作者开源的代码是基于caffe的,笔者自己也尝试在keras和tf2上进行复现,比较直观的效果是分类的置信度比原本ResNet要高很多。可能是因为在SE-ResNet中进行了多次sigmoid函数激活。

  • Keras-SEResNet

转:

SENet详解及Keras复现代码

最新文章

  1. [ASP.NET MVC 小牛之路]15 - Model Binding
  2. java.lang.IndexOutOfBoundsException at java.io.FileOutputStream.writeBytes(Native Method)
  3. ACM: 强化训练-Beautiful People-最长递增子序列变形-DP
  4. Java中线程的锁和数据库中的事务隔离级别
  5. 详解Android定位
  6. java_Collection 类集
  7. 转:6款Java转C#的最佳工
  8. android 工程里缺少 R.java 文件原因和解决方法
  9. Nginx中的信号量(信号控制)
  10. CTF入门指南(0基础)
  11. 轻量化卷积神经网络MobileNet论文详解(V1&V2)
  12. github在README.md中插入图片
  13. 不小心跳进安装Django-redis的坑
  14. QT_REQUIER_CONFIG
  15. 在operator =中要处理“自我赋值”
  16. Navicat操作数据库时一直显示加载中
  17. C# 16进制与字符串、字节数组之间的转换 (转载)
  18. python工具 - alert弹框输出姓名年龄、求和
  19. 解读EXPLAIN执行计划中的key_len(转)
  20. 题解——牛客网Wannafly挑战赛23 B-游戏 (SG函数)

热门文章

  1. Educational Codeforces Round 97 (Rated for Div. 2) E. Make It Increasing(最长非下降子序列)
  2. 用Python修改本机适配器信息
  3. SPOJ 227 Ordering the Soldiers
  4. VScode 相关
  5. 加密后的程序在Win8中无法运行
  6. 深入理解JavaScript垃圾回收
  7. μC/OS-III---I笔记5---多值信号量
  8. TypeScript & WebAssembly
  9. Big O Complexity Graph
  10. shit nuxt.js sensors-data