论文解读 | network in network

借鉴了很多别的东西 找不到出处了

引用

Lin M, Chen Q, Yan S. Network In Network[J]. Computer Science, 2013.

目录

前言

创新点一:mlpconv

mlpconv 的细节:

创新点二:global average pooling

网络的整体结构:

网络结构

效果分析

结论

参考资料


 


Network in Network 是2013提出的一种在网络结构上非常具有创造性的文章,文中作者做了大量的对比实验,说明各种结构对精度的影响。

前言

以前的深度学习结构,往往是CNN+POOLing+FC之类的组合,接一个分类器。这样在CNN与FC进行结合的过程中,则把两部分过程独立来开,POOLing负责将维度,CNN负责提取特征,FC负责特征分类。

那么,由于卷积网络参数较少,因此深度卷积网络的参数其实大部分集中在了全连接层,那么这个时候,到底是卷积层对结果贡献大还是全连接层贡献大?本文提出的模型尝试赋予卷积层更强大的表征能力,同时去掉了全连接层,使用了平均池化层来代替全连接层进行分类,这样做的好处就是一方面减少了参数,另一方面避免了由全连接层导致的过拟合的问题,因为池化层本身就充当了避免过拟合的功能,从而也就不需要采用dropout了。


卷积层是一个线性层(激活函数的目的就使数据非线性),如果遇到特征是高度非线性的,那么此线性卷积就不足以表达了,传统的做法是通过多个特征图来增强卷积层的表达能力,但是这样做又会对下一个卷积层造成较大的压力,因为下一层要考虑如何组合这些特征图得到更高级的特征抽象。


 

而NIN则利用mlpconv和global average pooling将CNN和FC两部分有机的结合在一起,使得其可解释性更强。从而文章的创新点:

  •  提出了mlpconv代替普通的卷积操作,从而来提升抽象能力
  •  提出了global average pooling,从而将CNN与FC有机的结合在一起,使得整个网络结构的可解释性更加强,效果也更佳
     

创新点一:mlpconv (multilayer perceptron conv)

首先,普通的卷积操作都是通过一个线性变换,然后后面跟着一个非线性激励函数 


其中,w∗x+bw∗x+b为线性变换,函数ff为非线性激励函数,例如sigmoid,tanh,ReLUsigmoid,tanh,ReLU等,但是这种抽象能力比较弱,指出这种表达能力只能正线性行可分的情况比较适应,换句话说,该结构的非线性表达能力较弱。

作者比较了传统的conv和mlpconv之间的区别:

  • mlpconv在普通的卷积后面接了一个多层感知机MLP
  • 在conv与MLP之间的连接采用的是global average pooling的方法:使得conv后的每一层特征通过全局平均产生一个元素,形成一个向量,然后在进行MLP,从而这样形成的特征层可以表示为分类目标的置信层(confidence map)

多层感知机(MLP,Multilayer Perceptron)也叫人工神经网络(ANN,Artificial Neural Network),除了输入输出层,它中间可以有多个隐层,最简单的MLP只含一个隐层,即三层的结构,如下图:


conventional 的卷积层 可以认为是linear model , 为什么呢,因为 局部接收域上的每每一个tile 与 卷积核进行加权求和,然后接一个激活函数;它的 abstraction 的能力不够, 对处理线性可分的的 concept 也许是可以的,但是更复杂的 concepts 它有能力有点不够了,所以呢,需要引入 more potent 的非线性函数;

基于此,提出了 mlpcon 结构,它用多层的感知器(其实就是多层的全连接层)来替代单纯的卷积神经网络中的 加 权求和; mlpcon 指的是: multilayer perceptron + convolution;

 

两者的结构如下所示:其中下图的 Mlpconv 的有两层的隐含层;

   image

说明:在mlpconv中的每一层的后面都跟着一个 ReLU激活函数;用于加入更多的nonlinearity;

mlpconv 的细节:

输入为一个feature map, 输出为一个feature map 时:

image

输入为多个feature map, 输出为一个feature map 时:

image

输入为多个feature map, 输出为多个feature map 时:

image[49]

 

发现了什么 ?

在 卷积神经网络中,无论是输入还是输出,不同的 feature map 之间的卷积核是不相同的;

在mlpconv中,不同的 feature map 之间的开头与能结尾之间的权值不一样,而在 隐含层之间的权值是共享的;

 

另外:

全连接层之间可以看作一特殊的卷积层,其中卷积核的大小为 1*1, feature maps的 个数即为全连接层中的每一层的units的数目;

所以呢,假设上面的第三个图中的输入为2*(4 *4), 输出为2 * (3*3)时:

    第一层的卷积核大小为2*2, 步长为1, 输入为2*(4 *4), 输出为 4*(3*3);

    第二层的卷积核大小为1*1, 步长为1, 输入为4*(3 *3), 输出为 3*(3*3);

    第三层的卷积核大小为1*1, 步长为1, 输入为3*(3 *3), 输出为 2*(3*3);

创新点二:global average pooling

一般的卷积神经网络,又CNN+FC构成,FC负责分类,最终的分类目标有多少类,则最后的输出多少维的向量,对应类别信息。但是,在CNN最后的特征层到FC是一个全联接,导致这部分的参数占据了整个网络参数的大部分,而且全联接很容易导致过拟合(overfitting)。

作者提供了一种全新的从特征层到最终的分类目标–global average pooling。该方法使得最终的特征层的深度等于最终的分类目标的种类数,然后后面紧跟一个全局平均池化,从而可以将特征层转化为一个分类向量,和最终的分类结果产生了直接的联系。

  •  该方法大大的减少了模型的参数,由于该连接方式没有参数,从而没有计算,大大减少了计算量,提高了计算速度
  •  该方法有效避免过拟合
  •  可解释性非常强,可以讲最终的feature map看作最终分类目标的confidence map

这里写图片描述

 
从上图中,可以看出最终的特征层与分类目标之间具有很强的相关性。


卷积神经网络最后的全连接层可以说作为了一个分类器,或者作为了一个 feature  clustering.   它把卷积层学习到的特征进行最后的分类;   intuitively, 根本不了解它是怎么工作的, 它就像一个黑盒子一样,并且它也引入了很多的参数,会出现 overfitting 现象;   (我认为其实最后的 全接层就是一个分类器)

本文,remove掉了 全连接层, 使用 global average pooling 来代替; 举个例子更容易说明白: 假设分类的任务有100 classes,  所以设置网络的最后的 feature maps 的个数为 100, 把每一个feature map 看作成 对应每一类的 概率的相关值 ,然后对每一个 feature map 求平均值(即 global average pooling), 得到了 100维的向量, 把它直接给 softmax层,进行分类;(其实100个数中最大值对应的类别即为预测值, 之所以再送给 softmax层是为了求 loss,用于训练时求梯度)

 

网络的整体结构:

image

(原 paper 中的图)

image

(该图来自:http://blog.csdn.net/hjimce/article/details/50458190 ,加入了相关的参数。我怎么找到这个图呢???? 难道 楼主自己 根据 caffe 中的 .prototxt 文件的加上的??)

网络结构

这里写图片描述

 
论文中给出的结构如上图,作者将mlpconv作为一个最小单元,然后多个mlpconv叠加在一起,然后生成一个n(分类目标数量)层的特征层,最后通过global average pooling生成一个输出向量(n维,每一特征层生成一维)。

详细的结构可以参考下图: 
 
【来源】

这里写图片描述

效果分析

首先作者在不同的数据集上进行了对比,发现该方法具有很好的效果

这里写图片描述

 在cifar10数据集上,可以达到state-of-the-art的效果,而在cifar100,SVHN, MINST上面也达到了很好的效果
这里写图片描述

 这里写图片描述

这里写图片描述
作者最后也进一步试验,强调了global average pooling和fc相似,都具有扮演着线性变换的作用,将特征图转化为特征向量,但前者相比较fc的方法效果更好 

这里写图片描述

结论

文中的观点:通过实验说明了 global average pooling 也可以起到很好的 regular的作用。

另外,一个比较有趣地地方就是:在 可视化最后一层 feature maps时,它的激活区域与原始图片中目标所在的区域竟然相似;amazing!

文中大量用到了文献:Maxout networks.  (引用:Goodfellow I J, Warde-Farley D, Mirza M, et al. Maxout networks[J]. arXiv preprint arXiv:1302.4389, 2013.)

文中也说明了 NIN比 maxout networks 更 non-linearity;

后续很有必要看一下 文献 maxout networks 这个paper, 它具有很好的价值;

import tensorflow as tf

def cnn_plus_relu(conv1_filter_name,conv1_filter_shape):
    assert type(conv1_filter_name) == 'str',"%s need the type of str,not %s"\
                                            %(conv1_filter_name,type(conv1_filter_name))
    assert len(conv1_filter_shape) == 4, "shape contrained w,h,channel,batch_size "
    conv_filter = tf.get_variable(conv1_filter_name,shape=conv1_filter_shape)   # [w,h,channel,batch_size]



def nin_cell(input):
    conv1_filter = tf.get_variable('conv1_filter', shape=[5, 5, 3, 192])
    conv1 = tf.nn.relu(tf.nn.conv2d(input, conv1_filter))

    mlpconv1_filter = tf.get_variable('mlpconv1_filter', shape=[1, 1, 192, 160])
    mlpconv1 = tf.nn.relu(tf.nn.conv2d(conv1, mlpconv1_filter))

    mlpconv2_filter = tf.get_variable('mlpconv2_filter', shape=[1, 1, 160, 96])
    mlpconv2 = tf.nn.relu(tf.nn.conv2d(mlpconv1, mlpconv2_filter))

    max_pool1 = tf.nn.max_pool(mlpconv2, ksize = [1,3,3,1], strides=[1,2,2,1])

    conv2_filter = tf.get_variable('conv2_filter', shape=[5, 5, 96, 192])
    conv2 = tf.nn.relu(tf.nn.conv2d(max_pool1, conv2_filter))

    mlpconv3_filter = tf.get_variable('mlpconv3_filter', shape=[1, 1, 192, 192])
    mlpconv3 = tf.nn.relu(tf.nn.conv2d(conv2, mlpconv3_filter))

    mlpconv4_filter = tf.get_variable('mlpconv4_filter', shape=[1, 1, 192, 192])
    mlpconv4 = tf.nn.relu(tf.nn.conv2d(mlpconv3, mlpconv4_filter))

    max_pool2 = tf.nn.max_pool(mlpconv4, ksize = [1,3,3,1], strides=[1,2,2,1])

    conv3_filter = tf.get_variable('conv3_filter', shape=[3, 3, 192, 192])
    conv3 = tf.nn.relu(tf.nn.conv2d(max_pool2, conv3_filter))

    mlpconv4_filter = tf.get_variable('mlpconv4_filter', shape=[1, 1, 192, 192])
    mlpconv4 = tf.nn.relu(tf.nn.conv2d(conv3, mlpconv4_filter))

    mlpconv5_filter = tf.get_variable('mlpconv5_filter', shape=[1, 1, 192, 10])
    mlpconv5 = tf.nn.relu(tf.nn.conv2d(mlpconv4, mlpconv5_filter))

    global_avg_pool = tf.nn.avg_pool(mlpconv5, ksize=[1,8,8,1])
    return global_avg_pool

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颐水风华

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值