关于现在的网络结构,我个人认为已经到了一个bottleneck(瓶颈)期了,到了一个比较尴尬的时期就是,有些网络效果好,但是呢,我不知道为什么这个东西效果好,理论方面的东西呢也极其匮乏,下面就是我的一点心得,欢迎讨论,要是说错了,求轻点打脸......
(1)关于卷积conv:卷积这一块呢,我最早接触的时候应该是叫做滑窗(sliding window),这是模式识别或者说机器学习领域的经典做法,那个时候我接触的滑窗应该算是一种固定参数的滑窗或者说是求固定窗口内的一阶二阶梯度,主要的用途呢,就是边缘检测。到了现在呢,卷积也是用来进行高维特征选取的有效工具,有很多人也做过尝试去解释卷积,主要通过:梯度的可视化、卷积模块的可视化和特征图(feature map)的可视化等方式试图去寻找一个pattern来很好的解释它或者说很好的让我们去理解它。在我接触的卷积中呢,主要分为这么几种形式:第一种就是常规的n*n的卷积形式,这种卷积形式呢,就是常规的嘛,有点也就是书上说的平移不变性啊等优点(话说我好像还真就没发现它比其它形式的卷积有啥优势)。第二种,空洞卷积(atrous conv)这种卷积在论文里面第一次看见应该是在Deeplab系列的论文里面看见的,在那里面阐述为可以接受更加广的一个感受野(receptive field)。第三种,就是所谓的一维卷积了,这中形式的卷积出自谷歌之手,第一次出现大概是在阐述inception系列结构的时候做的应用,这种一维形式的卷积呢,主要有两个优点:第一个优点是可以节约参数,将一个3*3的卷积可以分解为两个1*1和一个1*3+3*1的形式,第二个优点呢也是比较明显的,就是采用了这种方式它的计算效率也是非常快的。第4中,就是所谓的1*1卷积了,当时呢,我还以为Network in Network就是所谓的1*1卷积呢,1*1卷积主要有两方面的作用:第一个方面就是它可以增加特征图的数量也可以减少用它可以进行支路数据的融合(dense\res),多一句就是现在貌似用ZeroPadding比较流行, 第二个方面呢,就是用来替换最后一层的全连接(全连接是真的**,需要固定参数,而且参数还非常多),这就可以保证你设计网络是特征图的多样性了。
(2)关于池化pool:emmmm,了解的不多,当初看理论的时候说它是用来提取局部信息的,或者说局部最大值的,主要就是Maxpooling和Averagepooling, 现在有很多网络放弃了pool或者用的很少(用的很少的那一部分也就是在最开始第一个卷积之后和最后输出结果特征图之前用),它的替代品就是大步卷积(strides>1感觉这么翻译好别扭啊)。未完待续.......(2018.12.7)

 

卷积和池化感觉说的也差不多了,那么现在就来说一说目前CV这块的研究方向:

1.Classification:这个方向是比较经典的一个方向,主要就是你输入一个图像,之后我对你输入的东西进行一个分类(这个类别是早就定义好的),如果你的模型事先没有图片中的这个类别会出现什么情况呢?模型也会输出一个类别的,很明显这是错误的。所以现在目前的手机上面的识别,输出错误类别主要有两个方面的原因导致的,一方面就是上面说的根本没有训练那个类别,第二个方面的原因就是涉及到了模型的泛化能力(更直白的说法就是模型在训练集上表现的很好但是在实际测试时不尽如人意)。最开始的阶段呢,Classification主要就是卷积+池化的各种组合,最后连接三层全连接(这个地方优点不确定错了不要咬我,它好像在代码里面被称为“头”TOP)输出最后的结果,这里面要说一下全连接,讲真,全连接其实算是最像神经网络的神经网络了,因为它的模型看起来就很帅气,当然它呢有比较明确的优缺点,先说缺点,从它的名字其实我们就可以看出来,它的参数量相比卷积来说时很大的这就会带来一个致命的问题就是计算效率的降低,还有就是因为它本身是一个全连接的过程,有的时候我们需要对模型要求一定的稀疏性,显然它很“密集”所以一般来说全连接在命名的时候会称之为Dense层;还有一个缺点就是它的维度要求比较固定,这就要求了我们输入图片的固定Size,在没有提出1*1卷积之前有很多人去研究如何结局这一问题(我认为即使现在出来了1*1也没有很好的解决这个问题),最著名的一种解法就是SPP(空间金字塔池化详情可以见Fast Rcnn)。优点,可能是有很多,但是我就知道一个就是在我们做迁移学习的时候,全连接承担了一个类似于“防火墙”的作用,有Top和没Top的差别可不是一点点,有全连接来说迁移学习的效果比没有的训练速度和效果都要好一些。之后呢,Classification进入了第二个阶段,就是我不再去满足当前的这种搭积木式的神经网络结构,还有一个很重要的原因是我们发现了bottle-neck(瓶颈),当我们超过多少层之后(如果我没记错的话是56层),训练的效果就开始“跳崖式”下降,反而不如那些浅层的效果好了,其原因也很简单,就是因为梯度弥散的现象存在,现阶段我们进行训练的神经网络都是采用梯度下降的方式来进行的,它的主要数学公式是利用的求导的链式法则,链式法则是一个连续乘积的形式,我们认为最后的结果梯度是1,之后进行反向传播,当层数变深了之后,你可以将它简单的理解为X1*X2...Xn,n层的乘积等于1,所以这个数值就很小了,小到一定程度,我们就约等于0了。

那么要怎么解决这个问题呢?于是一个比较著名的网络结构出现了:残差网络(ResNet),这个网络很吊,各种博客里面对他的解释也有很多,我就给出一个比较肤浅的解释吧。首先,我上面已经说到梯度弥散这个东西了,它导致了深层网络的训练效果还比不上浅层网路(层数越深模型效果越好这事是约定俗成的,前提是没到bottle-neck),一个比较容易想到的事情就是,虽然不见得让模型的能力提高,但是我可不可以让深层网络的效果至少和浅层一样好,基于这个想法,出来了一个公式,H(x)= X+f(X),在这里面呢,f(x)就被称为残差了,这个公式是什么意思呢?其实完全可以这么理解,当你对x求导的时候,x=1的,于是原来的导数传到这里的时候就“大了”那么一丢丢,就可以继续传播下去了。这里面有一个坑或者说是你实现的时候必须要经历的地方就是关于它的通道数或者说是Channel的一个问题,这个问题的描述应该是这个样子的,首先你要知道tensor的表示形式(N,W,H,Channel)这里面我采用的是ChannelLast的形式 进行表示的,N表示batches也就是你的批处理数,W,H表示的是你的特征图(FeatureMap)的宽度和高度,Channel表示通道数,当卷积的stride>1,Channel数目增加的时候,就会出现问题,就是数目(W,H,C都不一样了)的不一致,导致没有办法相加(如果这个地方你感觉我描述的很不清晰你可以看看numpy矩阵的相加和numpy的Broadcast广播机制这块来进行理解,或者更加简单粗暴的方法是阅读Resnet这部分的逻辑代码),需要你进行一定的处理——(方法其实就是支路数据的pooling+1*1的维度调整)。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐