20170316#cs231n#8.Convolutional Neural Networks

Convolutional Neural Networks (CNNs / ConvNets) 卷积神经网络

卷积神经网络大体上和原先的神经网络一样,但不同在于假设输入都是图片,这让我们可以在结构中编码一些特定的特性

常规神经网络对于大尺寸的图片无法很好适应,对于大图片,全连接性很浪费而且会使得参数激增导致很快就过拟合。

卷积神经网络中神经元的三维排列
卷积神经网络的某一层中,层中的神经元有三个维度:width、height、depth(这里的深度指的是激活数据的第三个维度,而不是指整个神经网络的深度(即不是指层数))

层中的神经元将只与前一层的部分区域连接而不是fully-connected,当然最后的输出是scores,例如1×1×10,其中10是depth这一维度的

左图是一个常规的三层神经网络。
右图是一个卷积神经网络。每一层都是通过一个含参或不含参的可导函数,把3D input转换到3D output。 三个维度width、height和depth如图所示。在图里面红色输入层装的是图片,所以它的width和height是图片的两个维度,depth则为3(RGB三个通道)

用来构建CNN的层

三种最主要的构建CNN的层:Convolutional Layer(CONV), Pooling Layer(POOL), and Fully-Connected Layer(FC)

  • CNN有几种不同类型的层,其中最流行的是CONV/FC/RELU/POOL
  • 每一层都是通过一个可导函数,把3D input转换到3D output。
  • 有的层有参数,有的没有(CONV/FC有,所以可以通过梯度下降被训练;RELU/POOL没有)
  • 有的层有额外的超参数,有的没有(CONV/FC/POOL有,RELU没有)

Convolutional Layer

卷积层是CNN的核心成分,而且产生了网络中绝大部分计算量

CONV layer的参数由一些可以学习的filter滤波器组成。每个滤波器在空间上(width和height)都比较小,但是深度和输入数据一样。假设我们现在在CONV层上有12个filter,每个卷积filter最后会生成一个2D(width和height) activation map,在depth上把这些activation map排列起来,然后就可以输出这CONV层的结果了

Local Connectivity 局部连接

让每个神经元只与输入数据的局部区域连接。这个连接的空间大小叫神经元的receptive field(等价于filter的大小),是个超参数。在depth方向上,这个连接的大小总是和输入的深度一样。
我们对待spatial dimensions空间维度(width和height)与对待depth dimension是不同的:connections连接在空间(width和weigth)上是局部的,但depth总是和input的depth一样。(其实是不一定的…)

example:Suppose an input volume had size [16x16x20]. Then using an example receptive field size of 3x3, every neuron in the Conv Layer would now have a total of 3*3*20 = 180 (and +1 bias parameter) connections to the input volume. Notice that, again, the connectivity is local in space (e.g. 3x3), but full along the input depth (20).

Spatial arrangement 空间排列

三个超参数控制输出的大小:depth, stride and zero-padding

  • depth的输出的深度是一个超参数,它和使用的滤波器的数量一致。我们把和input中相同区域连接的一系列输出神经元称为 depth column深度列(有些人称为fibre纤维)(深度列中每个输出神经元由不同的滤波器生成)
  • stride步幅,是filter的滑动幅度。

    When the stride is 1 then we move the filters one pixel at a time. When the stride is 2 (or uncommonly 3 or more, though this is rare in practice) then the filters jump 2 pixels at a time as we slide them around. This will produce smaller output volumes spatially.

  • 有时候把输入的边界填充0是很有意义的。zero-padding(零填充)的大小也是个超参数

假定input为 W ,CONV Layer的receptive field为F,stride为 S ,zero-padding为P,输出的神经元数量为 (WF+2P)/S+1 。【注:这地方看看就好,其实写的不是很严谨】

For example for a 7x7 input and a 3x3 filter with stride 1 and pad 0 we would get a 5x5 output. With stride 2 we would get a 3x3 output.

设置 P=(F1)/2 当stride S=1 的时候可以确保输入体和输出体的有相同的spatial空间大小(width和height)

stride步长 S 是有限制的,假设input W=10,zero-padding P=0 ,filter F=3 ,这个时候 S=2 是不行的因为 (WF+2P)/S+1=(103+0)/2+1=4.5 不是一个整数。所以卷积神经网络需要做一点小改变去适应

Parameter Sharing 参数共享

将depth维度上一个单独的2维切片看做depth slice深度切片(例如一个大小为[55×55×96]的output数据体有96个深度切片,每个大小为[55×55]),每个深度切片内所有神经元weight和bias都为同一个。(也就是说一共需要96组weight)
在前向传播的时候,每个深度切片可以认为是weight和input的卷积的结果(CONV),所以我们也常称某一深度切片内的所有weight的集合为filter滤波器(或* kernel*卷积核),因为他们对input进行了卷积
在反向传播的时候,要计算每个神经元对它weight的gradient,但是需要把同一个深度切片上的所有神经元对weight的gradient累加,这样就得到了对共享权重的梯度。这样,每个深度切片只更新一个权重集。

因为图片具有平移不变性,所有在同个深度切片内用同一个卷积核就比较有意义了

注意有时候参数共享假设可能没有意义,特别是当卷积神经网络的输入图像是一些明确的中心结构时候。这时候我们就应该期望在图片的不同位置学习到完全不同的特征。一个具体的例子就是输入图像是人脸,人脸一般都处于图片中心。你可能期望不同的特征,比如眼睛特征或者头发特征可能(也应该)会在图片的不同位置被学习。在这个例子中,通常就放松参数共享的限制,将层称为局部连接层(Locally-Connected Layer)。

K的值总是2的指数北。 滤波器尺寸F总是奇数,一般来说最小的尺寸是3*3,(2其实也可以,但很少人用)
用零填充的意义在于保证从input到output的过程中,数据的width和height保持不变

用矩阵乘法实现卷积运算

input[227x227x3],filter[11x11x3] 所以width和height为(227-11)/4+1=55,55*55=3025,11*11*3=363
im2col:将input的局部区域拉伸为column
所以X_col[363x3025],但要注意receptive fields之间是有重复的,所以在input X_col不同列中就会有重复数字

卷积层的权重也被拉伸为column,如果有96个[11x11x3]的filter,就生成W_row[96x363]

卷积的结果np.dot(W_row, X_col)与为等价,得到的output为[96 x 363]

最后再把output进行reshape为[55x55x96]

这种矩阵乘法很浪费空间,因为在input X_col不同列中有重复数字。优点是矩阵乘法有很多高效的实现方式,im2col的思路可以用在Pooling

Backpropagation

卷积的反向传播对于data和权重还是一个卷积

*1×1卷积

因为depth是3,1×1卷积与3维dot product是同理的

*扩张卷积

卷积层中每个元素不一定是像上述一样连续的,元素之间也可以是有间隙的,这就叫扩张。

w[0]*x[0] + w[1]*x[1] + w[2]*x[2],此时扩张为0。如果扩张为1,那么计算为: w[0]*x[0] + w[1]*x[2] + w[2]*x[4]

来源:http://www.jianshu.com/p/9c4396653324

前向传播

反向传播

Pooling Layer

它的作用在于降低空间尺寸和减少参数数量和计算量,因此也可以控制overfit。插入于卷积层之间。

Pooling层对input的每一个depth slice单独操作,然后resize他们的空间尺寸(Max操作或平均操作)。
空间尺寸的减少通常是在pool层进行的。

一个最常用的形式就是pool layer有一个2×2的滤波器,stride是2,对每一个depth slice进行downsample降采样。将其中75%activation都丢掉。

每次MAX operation都会选取2×2区域中的最大值。然后depth的维度大小保持不变。

只需要两个超参数F和S。因为对于input,pool层用的是固定函数进行计算,所以没有引入参数。而且在pool层用zero-padding不常见。

在实际中一般只有两种常见的超参数设置形式。

  • 一种是F=3,S=2(也叫overlapping pooling重叠池化)
  • 更常见的是F=2,S=2

Pool的receptive fields的size太大容易对输入造成破坏。

注意,pool层没有参数,卷积层才有,因为Pool层只进行downsample

General Pooling一般的pooling方法

除了MAX pooling,还可以使用其他的函数,比如平均pooling(average pooling)或L-2范式pooling(L2-norm pooling)等等。
现在平均pool已经少用了,实践证明,最大pool效果比平均pool要好

注意上图中的depth维度保持不变

反向传播

max(x, y) 函数操作的反向传播中,梯度可以理解为只沿前向传播中的最大数回传。
因此在前向经过pool层的时候会记录max数的index(索引位置),(这个也叫作switches)。因此在反向传播的时候梯度路线会更加高效。

放弃pool层

有些人说可以只重复使用CONVlayers,而用更大stride的CONVlayer去代替pool层的功能。
在生成模型中,不使用POOL层还是挺重要的,例如在variational autoencoders (VAEs)和generative adversarial networks (GANs)

但是现在看来Pooling层在大部分网络中还是挺重要的。

Normalization Layer

在实际中发现归一化层的贡献特别小,所以现在不怎么用了。

Fully-connected layer FC层/全连接层

这个和之前常规神经网络中的FC层一样。他的激活数据可以由矩阵乘法和bias项得到。

Converting FC layers to CONV layers

FC和CONV都有dot product所以相互转换还是可能的。
其实就是用一个和图像一样大的滤波器,因而用CONV实现FC操作

一个用处在于可以把图片分割成多个部分分别预测结果。例如本来[224x224]只能对一张[224x224]照片进行预测。现在可以将其用于[384x384]的照片,并且stride为32.那么[384x384]图片就被拆分为6x6张[224x224],进行分别预测。

自然,相较于使用被转化前的原始卷积神经网络对所有36个位置进行迭代计算,使用转化后的卷积神经网络进行一次前向传播计算要高效得多,因为36次计算都在共享计算资源。这一技巧在实践中经常使用,一次来获得更好的结果。比如,通常将一张图像尺寸变得更大,然后使用变换后的卷积神经网络来对空间上很多不同位置进行评价得到分类评分,然后再求这些分值的平均值。

如果想要stride是16而不是32,那么就多次使用前向传播。第一次用原图,第二次把原图的weigth平移16,第三次把height平移16,最后一次把weight和height同时平移16然后代入CNN中。

采用多个有小的滤波器的CONV要好过用单个大的滤波器

假设你一层一层地重叠了3个3x3的卷积层(层与层之间有非线性激活函数)。在这个排列下,第一个卷积层中的每个神经元都对输入数据体有一个3x3的视野。第二个卷积层上的神经元对第一个卷积层有一个3x3的视野,也就是对输入数据体有5x5的视野。同样,在第三个卷积层上的神经元对第二个卷积层有3x3的视野,也就是对输入数据体有7x7的视野。假设不采用这3个3x3的卷积层,二是使用一个单独的有7x7的感受野的卷积层,那么所有神经元的感受野也是7x7,但是就有一些缺点。

  • 多个卷积层与非线性的激活层交替的结构,比单一卷积层的结构更能提取出深层的更好的特征。
  • 假设所有的数据有C个通道,那么单独的7x7卷积层将会包 C×(7×7×C)=49C2 个参数,而3个3x3的卷积层的组合仅有 3×(C×(3×3×C))=27C2 个参数。

直观说来,最好选择带有小滤波器的卷积层组合,而不是用一个带有大的滤波器的卷积层。前者可以表达出输入数据中更多个强力特征,使用的参数也更少。唯一的不足是,在进行反向传播时,中间的卷积层可能会导致占用更多的内存。

但是传统的网络已经遭到来自Google的Inception结构和微软亚洲研究院的Residual Networks的挑战
在ImageNet找到表现最好的网络是个好办法

Layer Sizing Patterns 层尺寸设计样式

input layer的尺寸大小应该可以被2整除好多次

conv layers:应该使用比较小的filters(3x3 或最多 5x5),stride S=1 。而且要对input进行零填充,以保证CONV层的输出与输入的空间维度尺寸相同。当 F=3 P=1 ;当 F=5 P=2 。通常有 P=(F1)/2 用于保持输入尺寸。如果想要用更大的filter sizes(例如7×7或更大),一般就只有在第一个面对原始图像的卷积层。

pool layers:对空间维度进行downsampling,通常是设置成用2×2的receptive fields(即 F=2 )和stride为2(即 S=2 )的max-pooling,这将会丢弃75%的activation。还有一种不大常见的是 F=3 S=2 。但是max-pooling的receptive field值大于3就很不常见了,因为pooling其实是有损失且有点激烈的。这会导致不好的结果

步长为1的好处:小的步长在实际中表现得更好,而且步长为1可以让downsampling只发生在Pool layers,而CONV层只负责对input的depth进行变化

使用零填充:如果不使用,会使得数据体的尺寸在经过CONV层后逐渐变小,而且边缘信息容易被逐渐冲散。

因为内存限制所做的妥协:一般只对第一层做修改以对内存妥协。例如在ZF net第一层中用filter 7x7和stride 2。AlexNet中filer 11x11和stride 4

ResNet



FC层之前用均值化去约减,可以减少大量参数,而且效果差不多

计算考量

在训练的时候因为前向后向所以必须保留初始层的数据(这些数据往往很大),但是在test的时候只需要前向,所以我们可以在前向之后把之前的数据删除

来自参数尺寸:即整个网络的参数的数量,在反向传播时它们的梯度值,以及使用momentum、Adagrad或RMSProp等方法进行最优化时的每一步计算缓存。因此,存储参数向量的内存,通常需要在参数向量的数量的基础上乘以3或者更多。

卷积神经网络还有各种零散的内存占用,例如image data batches,扩张数据等等

如果计算内存不够导致网络工作的不好,那么常用的方法就是降低batch size,因为大部分内存都是被激活数据消耗了

参考资料:
http://cs231n.github.io/convolutional-networks/
https://zhuanlan.zhihu.com/p/22339097

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值