CNN一些知识点

来源:互联网 发布:初级网络优化工程师 编辑:程序博客网 时间:2024/06/07 00:08

介绍

大数据,更多类别,需要更大“容量“的网络;卷积网络就是一个好的选择,局部连接,权值共享等特征,使其参数少,训练容易;而且还可以通过长度,和宽度来控制”容量“。
尽管CNN有很多优势,但是对于高像素图像的分类问题,计算仍然是一个主要的瓶颈。幸运的是,高性能GPU,并行计算,高度优化的2D卷积计算是的训练成为可能。

池化

==

稀疏编码减小了量化误差,效果也十分显著(14%的正确率提升),但是经过稀疏编码得到的结果是一个矩阵而不是向量(具体可以看paper),矩阵的两个维度分别是word和location,这个矩阵是无法直接拿来分类的,所以需要对它做pooling变成一个向量,这就是题主所说的pooling。
池化是为了解决卷积神经网络卷积后产生的大量数据而诞生的,在提取出大量密集特征或卷积特征之后,一个通常的选择是使用这些特征进行分类。但是这往往会面临运算数据过大或者重复特征很多产生过拟合的现象。
首先对于卷积特征或密集特征来说,具有图像“平稳性”的特点,即卷积的每次位移,并非是以尺度为单位,而是以像素为单位的。有大量的像素点被多次计算,导致该像素周围的卷积特征均有该像素点的贡献,故在一定范围内的卷积或者密集特征具有一定程度的平稳性,该属性意味着在相邻小区域搜集的特征往往会具有类似的数据。
因此,为了统计一个大图像,人们自然的方式是聚集这些不同小区域的特定特征的值,汇总到比这些同居数据要低的多的尺寸的特征中,一方面可以保留不同“分块”的细节特征,另一方面也可以提升分类器效果,减少内存消耗和过拟合现象等。人们可以计算出图像分块后每个区域特征的平均值(或最大值),这些分块的特征平均值(最大值)取代了原始的特征而成为新的被聚合的特征。我们称此聚集操作为池化操作,称上述取平均值(最大值)聚集的操作为平均池化(最大池化)。

一般池化(General Pooling)


=====================


我们定义池化窗口的大小为sizeX,即下图中红色正方形的边长,定义两个相邻池化窗口的水平位移/竖直位移为stride。一般池化由于每一池化窗口都是不重复的,所以sizeX=stride。
最常见的池化操作为平均池化mean pooling和最大池化max pooling: 平均池化:计算图像区域的平均值作为该区域池化后的值。 最大池化:选图像区域的最大值作为该区域池化后的值。

重叠池化(OverlappingPooling)


重叠池化正如其名字所说的,相邻池化窗口之间会有重叠区域,此时sizeX>stride。

空金字塔池化(Spatial Pyramid Pooling)Spatial Pyramid Pooling in Deep Convolutional Networks for Visual Recognition


空间金字塔池化可以把任何尺度的图像的卷积特征转化成相同维度,这不仅可以让CNN处理任意尺度的图像,还能避免cropping和warping操作,导致一些信息的丢失,具有非常重要的意义。
一般的CNN都需要输入图像的大小是固定的,这是因为全连接层的输入需要固定输入维度,但在卷积操作是没有对图像尺度有限制,所有作者提出了空间金字塔池化,先让图像进行卷积操作,然后转化成维度相同的特征输入到全连接层,这个可以把CNN扩展到任意大小的图像。

空间金字塔池化的思想来自于Spatial Pyramid Model,它一个pooling变成了多个scale的pooling。用不同大小池化窗口作用于卷积特征,我们可以得到1X1,2X2,4X4的池化结果,由于conv5中共有256个过滤器,所以得到1个256维的特征,4个256个特征,以及16个256维的特征,然后把这21个256维特征链接起来输入全连接层,通过这种方式把不同大小的图像转化成相同维度的特征。
对于不同的图像要得到相同大小的pooling结果,就需要根据图像的大小动态的计算池化窗口的大小和步长。假设conv5输出的大小为aa,需要得到nn大小的池化结果,可以让窗口大小sizeX为 [a/n],步长为[a/n] 。下图以conv5输出的大小为13*13为例。

SPP其实就是一种多个scale的pooling,可以获取图像中的多尺度信息;在CNN中加入SPP后,可以让CNN处理任意大小的输入,这让模型变得更加的flexible。
Reference
1. 图像分类中的max pooling和average pooling是对特征的什么来操作的,结果是什么?
(http://www.zhihu.com/question/23437871)
2. A Theoretical Analysis of Feature Pooling in Visual Recognition, ICML, 2010,P
(http://www.di.ens.fr/willow/pdfs/icml2010b.pdf)
3. Comparison of Mid-Level Feature Coding Approaches And Pooling Strategies in Visual Concept
Detection (http://claret.wdfiles.com/local–files/start/CodingAndPooling_Sup_CVIU2012.pdf)
4. Protected Pooling Method Of Sparse Coding In Visual Classi cation,ICCVG,2014
(http://3dimage.ee.tsinghua.edu.cn/files/publications/ICCVG14_ZhichenZhao.pdf)
5. Linear Spatial Pyramid Matching Using Sparse Coding for Image Classification
(http://www.ifp.illinois.edu/~jyang29/papers/CVPR09-ScSPM.pdf)
6. 池化方法总结(Pooling) (http://demo.netfoucs.com/danieljianfeng/article/details/42433475)
7. Deep learning:四十七(Stochastic Pooling简单理解)
(http://www.cnblogs.com/tornadomeet/p/3432093.html)

Better non-linear transformation

sigmoid变换的目的

============

很多人知道sigmoid函数是神经网络中常用的非线性变换方式,有几人知道为什么sigmoid函数比别的非线性变换更有吸引力吗?数学性质好固然不错,但决定一个函数形式是否对所研究的问题合理才是第一位的。做sigmoid变换的目的是把(-inf,+inf)取值范围的信号(用x表示)映射到(0,1)范围内(用y表示):y=h(x)。为此目的,我们应该选择什么样的h呢?h变换可理解成对x的一种编码。当然h最好是双射,意味着可以从y反解码获得x。

最优的映射h

理论上,满足双射的h有无穷多种,该怎么选择呢?实际上双射是不可能,因为观测y时不可避免引入误差,即y=h(x)+e,其中e为误差(你也可尝试考虑x有误差的情况)。在有误差e的情况下,x和y就不是一一映射了。任何h从y反解码得到的x都是不可靠的。问题:有没有一种映射h,在有误差的情况做到最优?
通俗讲,就是寻找一个映射h能在有观测误差e的情况下最优的保持输入信号的信息,用信息论的语言描述就是x与y之间的互信息最大,有这个关系成立:
其中:I(x,y) 表示x与y的互信息;H(y) 表示y的熵;H(y|x) 表示y对x的条件熵;当有y=h(x)+e 时,H(y|x)=H(e) 。I(x,y)的互信息由两项决定:H(y)=H(h(x))和H(e)。其中第二项H(e)完全由误差决定,第一项H(y)由映射h决定,H(y)越大越好。
问题:给定y取值范围(0,1),熵H(y)什么时候最大?答案是当y服从均匀分布时熵最大,
因此能把x映射成一个服从均匀分布的变量y的映射h是最优的。
问题来了:当知道x的概率密度为f(x)时(这个函数可能很奇怪),什么样的h能把x变换成均匀分布的信号呢?
可能有人遇到这样的面试题:如果用c的库函数rand()生成服从高斯分布或贝塔分布,or其他分布的随机数?应该有不少人知道答案吧。C函数rand可生成[0,1)均匀分布随机数,用一种叫inverse cumulative distribution function的变换方法可以生成任意分布的随机数。感兴趣的同学可以查资料。回到正题,此处我们的目标和面试题相反,要从任意分布的信号生成均匀分布的信号,其实也和cumulative distribution function累积分布函数有关。
答案是:知道x的概率密度函数f(x),那么对f(x)的积分可得累积分布函数F(x),F就是最优的h,即y=F(x)最优。
这几段话也许不那么容易理解,但想象一下高斯分布的概率密度函数是一个倒置的钟形函数,累积分布函数是不是和sigmoid长的很像?(尽管我们知道高斯分布的累积分布函数没有闭式解)。
核心思想前面应该已经说完了。Sigmoid变换对于概率密度函数呈倒置钟形的信号来说是最优变换,而现实中倒置钟形分布的信号又比比皆是,很多自然的信号都是这样,譬如高斯分布就很普遍。换句话说:对于概率密度不是倒置钟形的信号会有自己最优的变换,而不一定是sigmoid函数。
关于为什么要把信号x压缩到[0,1]之类的一个局部范围内。无论在人脑还是电脑,信号都是用电压(伏特)表示的,电压变化幅度大,对信号的刻画当然更逼真,但能耗也必然升高。生物体必须在能耗和信息传递的准确性之间折中。
1981年,一位叫simo Lauglin的学者对苍蝇复眼中一类神经元的刺激(即我们讨论的x)的响应函数(即我们讨论的h)进行了研究,神奇的发现当刺激x的概率密度函数f(x)变化时,响应函数h也会随之变化,而且h总是和f的积分F类似。下面的图片就是来自这篇论文。
我的歪解,它能压缩无用长尾巴,扩展核心分辨率-感觉这理解好弱智。期待老师木的正解。还是这张图,请注意下半部分红线标识的部分:对y的等距量化,对应到输入信号x时是非等距量化,同样长的y区间,对应到x时区间是不等的。同样长度的y,在x高密度区域只能编码一小段,而在x低密度区域却编码一长段。
Reference
1. Deep Learning Made Easier by Linear Transformations in Perceptrons
(http://jmlr.csail.mit.edu/proceedings/papers/v22/raiko12/raiko12.pdf)
2. 为什么我们喜欢用sigmoid这类S型非线性变换? (http://www.52cs.org/?p=363)

ReLU非线性


模拟神经元输出的标准函数一般是:tanh(x)或者sigmoid(x)函数,由于此类函数在x非常大或者非常小时,函数输出基本不变,所以此类函数成为饱和函数;f(x)=max(0,x),扭曲线性函数,是一种非线性的非饱和函数。在训练时间上,非饱和函数比饱和函数训练更快。而且这种扭曲线性函数,不但保留了非线性的表达能力,而且由于其具有线性性质(正值部分),相比tanh和sigmoid函数在误差反向传递时,不会有由于非线性引起的梯度弥散形象(顶层误差较大,由于逐层递减误差传递,引起低层误差很小,导致深度网络地层

局部归一化

ReLU函数,不需要归一化来防止饱和现象,如果没有神经元产生一个正的激活值,学习就会在这个神经元发生;然而,作者发现局部归一化帮助泛化。局部归一化公式:![局部归一化公式:](http://img.blog.csdn.net/20150829163940220)具体方式:选取临近的n个特征图,在特征图的同一个空间位置(x,y),依次平方,然后求和,在乘以alpha,在加上K。这个局部归一化方式“what is the best multi-stage architecture for Object Recognition”中的局部归一化方法不同;本文的归一化只是多个特征图同一个位置上的归一化,属于特征图之间的局部归一化(属于纵向归一化),作者命名为亮度归一化;“what……”论文中在特征图之间基础上还有同一特征图内邻域位置像素的归一化(横向,纵向归一化结合);“what……”归一化方法计算复杂,但是没有本文中alpha,k,n等参数,本文通过交叉验证来确定这三个参数;此外,本文的归一化方法没有减去均值,感觉是因为ReLU只对正值部分产生学习,如果减去均值会丢失掉很多信息。这种归一化方式对结果有1%左右的提升。

Better Regularization

正则化方法:防止过拟合,提高泛化能力
在训练数据不够多时,或者overtraining时,常常会导致overfitting(过拟合)。其直观的表现如下图所示,随着训练过程,网络在training data上的error渐渐减小,但是在验证集上的error却反而渐渐增大——因为训练出来的网络过拟合了训练集,对训练集外的数据却不work。

为了防止overfitting,可以用的方法有很多,下文就将以此展开。有一个概念需要先说明,在机器学习算法中,我们常常将原始数据集分为三部分:training data、validation data,testing data。这个validation data是什么?它其实就是用来避免过拟合的,在训练过程中,我们通常用它来确定一些超参数(比如根据validation data上的accuracy来确定early stopping的epoch大小、根据validation data确定learning rate等等)。那为啥不直接在testing data上做这些呢?因为如果在testing data做这些,那么随着训练的进行,我们的网络实际上就是在一点一点地overfitting我们的testing data,导致最后得到的testing accuracy没有任何参考意义。因此,training data的作用是计算梯度更新权重,validation data如上所述,testing data则给出一个accuracy以判断网络的好坏。
避免过拟合的方法有很多:early stopping、数据集扩增(Data augmentation)、正则化(Regularization)包括L1、L2(L2 regularization也叫weight decay),dropout。

L1 regularization


在原始的代价函数后面加上一个L1正则化项,即所有权重w的绝对值的和,乘以 lamada这里不像L2正则化项那样,需要再乘以1/2,具体原因上面已经说过。
同样先计算导数:
上式中sgn(w)表示w的符号。那么权重w的更新规则为:
比原始的更新规则多出了η * λ * sgn(w)/n这一项。当w为正时,更新后的w变小。当w为负时,更新后的w变大——因此它的效果就是让w往0靠,使网络中的权重尽可能为0,也就相当于减小了网络复杂度,防止过拟合。
另外,上面没有提到一个问题,当w为0时怎么办?
当w等于0时, 是不可导的.所以我们只能按照原始的未经正则化的方法去更新w,这就相当于去掉 这一项,所以我们可以规定sgn(0)=0,这样就把w=0的情况也统一进来了.(在编程的时候,令sgn(0)=0,sgn(w>0)=1,sgn(w<0)=-1)

L2 regularization


L2正则化就是在代价函数后面再加上一个正则化项:
C0代表原始的代价函数,后面那一项就是L2正则化项,它是这样来的:所有参数w的平方的和,除以训练集的样本大小n。λ就是正则项系数,权衡正则项与C0项的比重。另外还有一个系数1/2,1/2经常会看到,主要是为了后面求导的结果方便,后面那一项求导会产生一个2,与1/2相乘刚好凑整。
L2正则化项是怎么避免overfitting的呢?我们推导一下看看,先求导:
可以发现L2正则化项对b的更新没有影响,但是对于w的更新有影响:
在不使用L2正则化时,求导结果中w前系数为1,现在w前面系数为 1?ηλ/n ,因为η、λ、n都是正的,所以 1-ηλ/n小于1,它的效果是减小w,这也就是权重衰减(weight decay)的由来。当然考虑到后面的导数项,w最终的值可能增大也可能减小。
另外,需要提一下,对于基于mini-batch的随机梯度下降,w和b更新的公式跟上面给出的有点不同:

对比上面w的更新公式,可以发现后面那一项变了,变成所有导数加和,乘以η再除以m,m是一个mini-batch中样本的个数。
到目前为止,我们只是解释了L2正则化项有让w“变小”的效果,但是还没解释为什么w“变小”可以防止overfitting?人们普遍认为:更小的权值w,从某种意义上说,表示网络的复杂度更低,对数据的拟合刚刚好(这个法则也叫做奥卡姆剃刀)。而在实际应用中,也验证了这一点,L2正则化的效果往往好于未经正则化的效果。

dropout


L1、L2正则化是通过修改代价函数来实现的,而Dropout则是通过修改神经网络本身来实现的,它是在训练网络时用的一种技巧(trike)。它的流程如下:
假设我们要训练上图这个网络,在训练开始时,我们随机地“删除”一半的隐层单元,视它们为不存在,得到如下的网络:
保持输入输出层不变,按照BP算法更新上图神经网络中的权值(虚线连接的单元不更新,因为它们被“临时删除”了)。
以上就是一次迭代的过程,在第二次迭代中,也用同样的方法,只不过这次删除的那一半隐层单元,跟上一次删除掉的肯定是不一样的,因为我们每一次迭代都是“随机”地去删掉一半。第三次、第四次……都是这样,直至训练结束。
以上就是Dropout,它为什么有助于防止过拟合呢?可以简单地这样解释,运用了dropout的训练过程,相当于训练了很多个只有半数隐层单元的神经网络(后面简称为“半数网络”),每一个这样的半数网络,都可以给出一个分类结果,这些结果有的是正确的,有的是错误的。随着训练的进行,大部分半数网络都可以给出正确的分类结果,那么少数的错误分类结果就不会对最终结果造成大的影响。
更加深入地理解,可以看看Hinton和Alex两牛2012的论文《ImageNet Classification with Deep Convolutional Neural Networks》
Reference
Deep learning:四十六(DropConnect简单理解)

artificial expansion of the training data/数据集扩增(data augmentation)


“有时候不是因为算法好赢了,而是因为拥有更多的数据才赢了。”
从中可见训练数据有多么重要,特别是在深度学习方法中,更多的训练数据,意味着可以用更深的网络,训练出更好的模型。既然这样,收集更多的数据不就行啦?如果能够收集更多可以用的数据,当然好。但是很多时候,收集更多的数据意味着需要耗费更多的人力物力,有弄过人工标注的同学就知道,效率特别低,简直是粗活。
所以,可以在原始数据上做些改动,得到更多的数据,以图片数据集举例,可以做各种变换,如:

  • 将原始图片旋转一个小角度
  • 添加随机噪声
  • 一些有弹性的畸变(elastic distortions),论文《Best practices for convolutional neural networks applied to visual document analysis》对MNIST做了各种变种扩增。
  • 截取(crop)原始图片的一部分。比如DeepID中,从一副人脸图中,截取出了100个小patch作为训练数据,极大地增加了数据集。感兴趣的可以看《Deep learning face representation from predicting 10,000 classes》.
    更多数据意味着什么?
    用50000个MNIST的样本训练SVM得出的accuracy94.48%,用5000个MNIST的样本训练NN得出accuracy为93.24%,所以更多的数据可以使算法表现得更好。在机器学习中,算法本身并不能决出胜负,不能武断地说这些算法谁优谁劣,因为数据对算法性能的影响很大。
    Reference
    • Deep Learning with Kernel Regularization for Visual Recognition
    • Comparison of Regularization Methods for ImageNet Classification with Deep Convolutional Neural Networks
    • 正则化方法:L1和L2 regularization、数据集扩增、dropout
      http://blog.csdn.net/u012162613/article/details/44261657

Better loss function

在有监督的机器学习中,需要有标签数据,与此同时,也需要有对应的损失函数(Loss Function)。
在Caffe中,目前已经实现了一些损失函数,包括最常见的L2损失函数,对比损失函数,信息增益损失函数等等。在这里做一个笔记,归纳总结Caffe中用到的不同的损失函数,以及分析它们各自适合的使用场景。

此部分见>DL: Recent Advance of CNN

http://gujiuxiang.github.io/2015/06/22/DL-Progress-CNNs/

Fast processing of CNNs

    深层模型训练需要各种技巧,例如网络结构的选取,神经元个数的设定,权重参数的初始化,学习率的调整,Mini-batch的控制等等。即便对这些技巧十分精通,实践中也要多次训练,反复摸索尝试。此外,深层模型参数多,计算量大,训练数据的规模也更大,需要消耗很多计算资源。如果可以让训练加速,就可以在同样的时间内多尝试几个新主意,多调试几组参数,工作效率会明显提升,对于大规模的训练数据和模型来说,更可以将难以完成的任务变成可能。这一节就谈谈深层模型的训练加速方法。

参考:DL-Progress-CNNs/

0 0