终究进入我们的主题了ConvNets或CNNs,它的结构和普通神经网络都1样,之前我们学习的各种技能方法都适用,其主要不同的地方在于:
ConvNet假定输入的是图片,我们根据图片的特性对网络进行设定以到达提高效力,减少计算参数量的目的。
首先我们分析下传统神经网络对图片的处理,如果还是用CIFAR⑴0上的图片,共3072个特点,如果普通网络结构输入那末第1层的每个神经单元都会有3072个权重,如果更大的像素的图片进入后参数更多,而且用于图片处理的网络1般深度达10层之上,加在1起参数的量实在太大,参数过量也会造成过拟合,而且图片也有本身的特点,我们需要利用这些特点,将传统网络改革,加快处理速度和精确度。
我们注意到图片的像素是由3个通道构成的,我们就利用了这个特点将其神经元安置到了3维空间(width, height, depth),分别对应着图片的32x32x3(以CIFAR为例)以下图:
红色是输入层这里的深度是3,输出层是1x1x10的结构。其他几层的含义后面会介绍,现在先知道每层都是height × width × depth结构。
卷积神经网络有3种层:卷积层、池化层和全连接层(Convolutional Layer, Pooling Layer, 及 Fully-Connected Layer)。
以处理CIFAR⑴0的卷积神经网络为例,简单的网络应包括这几层:
[INPUT - CONV - RELU - POOL - FC]也就是[输入-卷积-激活-池化-分类得分],各层分述以下:
注意:
1. 卷及神经网络包括不同的层 (e.g. CONV/FC/RELU/POOL 也是最受欢迎的)
2. 每层都输入输出3d结构的数据,除最后1层
3. 有些层可能没有参数,有些层可能有参数 (e.g. CONV/FC do, RELU/POOL don’t)
4. 有些层可能有超参数有些层也可能没有超参数(e.g. CONV/FC/POOL do, RELU doesn’t)
下图是1个例子,没法用3维表示只能展成1列的情势了。
下面展开讨论各层具体细节:
卷积层是卷积神经网络的核心层,大大提高了计算效力。
卷积层由很多过滤器组成,每一个过滤器都只有1小部份,每次只与原图象上的1小部份连接,UFLDL上的图:
这是1个过滤器不停滑动的结果,
我们这里要更深入些,我们输入的图象是1个3维的,那末每一个过滤器也是有3个维度,假定我们的过滤器是5x5x3的那末我们也会得到1个类似于上图的激活值的映照也就是convolved feature 下图中叫作 activion map,其计算方法是
我们可以有多个过滤器:
更深入1些,当我们滑动的时候有3个超参数:
1. 深度,depth,这是过滤器的数量决定的。
2. 步长,stride,每次滑动的间隔,上面的动画每次只滑动1个数,也就是步长为1.
3. 补零数, zero-padding,有时候根据需要,会用零来拓展图象的面积,如果补零数为1,变长就+2,以下图中灰色的部份就是补的0
下面是1个1维的例子:
其输出的空间维度计算公式是
上面可以知道在卷积层以后得到的结果还是挺多,而且由于滑动窗口的存在,很多信息也有重合,因而有了池化pooling 层,他是将卷积层得到的结果无重合的分来几部份,然后选择每部份的最大值,或平均值,或2范数,或其他你喜欢的值,我们以取最大值的max pool为例:
- 反向传播:最大值的梯度我们之前在反向传播的时候就已学习过了,这里1般都跟踪最大的激活值,这样在反向传播的时候会提高效力.
- Getting rid of pooling. 1些人认为pooling是没有必要的,如The All Convolutional Net ,很多人认为没有池层对生成式模型(generative models)很重要,仿佛以后的发展中,池层可能会逐步减少或消失。
全连接层和卷积层除连接方式不1样,其计算方式都是内积,可以相互转换:
1. FC如果做CONV layer 的工作就相当于其矩阵的多数位置都是0(稀疏矩阵)。
2. FC layer 如果被转变成 CONV layer. 相当于每层的局部连接变成了全部链接如FC layer with K=4096的输入是7×7×512那末对应的卷积层为 F=7,P=0,S=1,K=4096输出为1×1×4096。
例子:
假定1个cnn输入 224x224x3图象,经过若干变化以后某1层输出 7x7x512 到这里以后使用两4096的FC layer及最后1个1000的FC计算分类得分下面是把这3层fc转化为Conv 的进程:
1. 使用 F=7的conv layer 输出为 [1x1x4096];
2. 使用F=1的过滤器,输出为 [1x1x4096];
3. 使用F=1的卷积层,输出为 [1x1x1000]。
每次转化都会将FC的参数转变成conv的参数情势. 如果在转变后的系统中传入更大的图片,也会非常快速的向前运算。例如将384x384的图象输入上面的系统,会在最后3层之前得到[12x12x512]的输出, 经过上面转化的conv 层会得到 [6x6x1000], ((12 - 7)/1 + 1 = 6). 我们1下就得出了6x6的分类结果。
这样1次得到的比原来使用迭代36次得到的要快。这是实际利用中的技能。
另外我们可以用两次步长16的卷积层代替1次步长为32的卷积层来输入上面的图片,提高效力。
下面我们就用CONV, POOL,FC ,RELU 搭建1个卷积神经网络:
我们依照以下结构搭建
INPUT -> [[CONV -> RELU]*N -> POOL?]*M -> [FC -> RELU]*K -> FC
其中N >= 0 (1般N <= 3), M >= 0, K >= 0 (1般K < 3).
这里要注意:我们更偏向于使用多层小size的CONV。
为何呢?
比如3个3x3的和1个7x7的conv层,他们都可以 得到7x7的receptive fields.但是3x3的有以下优点:
1. 3层的非线性组合要比1层线性组合表达能力强;
2. 3层小尺寸的卷积层的参数数量要少,3x3x3<7x7;
3. 反向传播中我们需要使用更多的内存来贮存中间层结果。
值得注意的是Google’s Inception architectures 及Residual Networks from Microsoft Research Asia. Both 等创造了相比以上结构更加复杂的连接结构。
INPUT: [224x224x3] memory: 224*224*3=150K weights: 0
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*3)*64 = 1,728
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*64)*64 = 36,864
POOL2: [112x112x64] memory: 112*112*64=800K weights: 0
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*64)*128 = 73,728
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*128)*128 = 147,456
POOL2: [56x56x128] memory: 56*56*128=400K weights: 0
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*128)*256 = 294,912
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
POOL2: [28x28x256] memory: 28*28*256=200K weights: 0
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*256)*512 = 1,179,648
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
POOL2: [14x14x512] memory: 14*14*512=100K weights: 0
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
POOL2: [7x7x512] memory: 7*7*512=25K weights: 0
FC: [1x1x4096] memory: 4096 weights: 7*7*512*4096 = 102,760,448
FC: [1x1x4096] memory: 4096 weights: 4096*4096 = 16,777,216
FC: [1x1x1000] memory: 1000 weights: 4096*1000 = 4,096,000
TOTAL memory: 24M * 4 bytes ~= 93MB / image (only forward! ~*2 for bwd)
TOTAL params: 138M parameters
注意到内存使用最多的时候在开始几个CONV layers, 参数基本都在最后几个FC层第1个FC有100M个!
内存主要在以下几个方面消耗较多
1. 大量的激活值和梯度值。测试时可以只贮存当前的激活值抛弃之前的在下方几层激活值会大大减少激活值的贮存量。
2. 参数的贮存,在反向传播时的梯度及使用 momentum, Adagrad, or RMSProp时的缓存都会占用贮存,所以估计参数使用的内存时1般最少要乘以3倍
3. 每次网络运行都要记住各种信息比如图形数据的批量等
如果估计网络需要的内存太大,可以适当减小图片的batch,毕竟激活值占用了大量的内存空间。
总结