卷积神经网络CNN(Convolutional Neural Network)
深度学习之卷积神经网络CNN
一. CNN的引入
在人工的全连接神经网络中,每相邻两层之间的每个神经元之间都是有边相连的。当输入层的特征维度变得很高时,这是全连接神经网络需要训练的参数就会增大很多,计算速度就会变得很慢。下图可以容易的看出全连接神经网络处理图像中需要的训练参数过多的问题。
而在卷积神经网络中,卷积层的神经元只与前一层的部分神经元节点相连,即它的神经元间的连接是非全连接的,且同一层中某些神经元之间的连接的权重w和偏移b是共享的(即相同的),这样大量地减少了需要训练参数的数量
卷积神经网络CNN的结构一般包含这几个层:
- 输入层:用于数据的输入
- 卷积层:使用卷积核进行特征提取和特征映射
- 激励层:由于卷积也是一种线性运算,因此需要增加非线性映射
- 池化层:进行下采样,对特征图稀疏处理,减少数据运算量
- 全连接层:通常在CNN的尾部进行重新拟合,减少特征信息的损失
- 输出层:用于输出结果
中间还可以使用一些其他的功能层:
- 归一化层:在CNN中对特征进行归一化
- 切分层:对某些(图片)数据进行分区域的单独学习
- 融合层:对独立进行特征学习的分支进行融合
二. CNN的层次结构
输入层:
在CNN的输入层中,(图片)数据输入的格式与全连接神经网络的输入格式(一维向量)不太一样。CNN的输入层的输入格式保留了图片本身的结构
对于黑白的28*28的图片,CNN的输入层是一个28 * 28的二维神经元
而对于RGB格式的28×28图片,CNN的输入则是一个 3×28×28的三维神经元(RGB中的每一个颜色通道都有一个 28×2828×28 的矩阵),如下图所示:
卷积层:
重要概念:
- local receptive fields(感受视野)
- shared weights(共享权值)
假设输入的是一个 28×282的的二维神经元,我们定义5×55×5 的 一个 local receptive fields(感受视野),即 隐藏层的神经元与输入层的5×5个神经元相连,这个5*5的区域就称之为Local Receptive Fields,如下图所示:
可类似看做:隐藏层中的神经元具有一个固定大小的感受视野去感受上一层的部分特征。在全连接神经网络中,隐藏层的神经元的感受视野足够大乃至可以看到上一层的所有特征
而在卷积神经网络中,隐藏层中的神经元的感受视野比较小,只能看到上一次的部分特征,上一层的其他特征可以通过平移感受视野来得到同一层的其他神经元,由同一层其他神经元来看:
设移动的步长为1:从左到右扫描,每次移动 1 格,扫描完之后,再向下移动一格,再次从左到右扫描。
具体过程如动图所示:设移动的步长为1:从左到右扫描,每次移动 1 格,扫描完之后,再向下移动一格,再次从左到右扫描。
可看出 卷积层的神经元是只与前一层的部分神经元节点相连,每一条相连的线对应一个权重w
一个感受视野带有一个卷积核,我们将感受视野中的权重w矩阵称为卷积核;将感受视野对输入的扫描间隔称为步长。当步长比较大时(stride>1),为了扫描到边缘的一些特征,感受视野可能会“出界”,这时需要对边界扩充(pad),边界扩充可以设为 0 或 其他值。步长 和 边界扩充值的大小由用户来定义。
卷积核的大小由用户来定义,即定义的感受视野的大小;卷积核的权重矩阵的值,便是卷积神经网络的参数,为了有一个偏移项 ,卷积核可附带一个偏移项 b ,它们的初值可以随机来生成,可通过训练进行变化。
因此 感受视野 扫描时可以计算出下一层神经元的值为:
对下一层的所有神经元来说,它们从不同的位置去探测了上一层神经元的特征。
我们将通过 一个带有卷积核的感受视野 扫描生成的下一层神经元矩阵 称为 一个feature map (特征映射图),如下图的右边便是一个 feature map:
因此在同一个feature map上的神经元使用的卷积核是相同的,因此这些神经元shared weights,共享卷积核中的权值和附带的偏移。一个feature map对应一个卷积核,若我们使用三个不同的卷积核,可以输出三个feature map:(感受视野: 5 * 5,步长stride:1)
因此在CNN的卷积层,我们需要训练的参数大大地减少到了(5 *5 + 1) * 3 = 78个
假设输入的是28 *28的RGB图片,即输入的是一个3 * 28 * 28 的二维神经元,这是卷积大小不止用长和宽来表示,还有深度,感受视野也对应有了深度,如下图所示:
由图可知:感受视野: 3 * 2 * 2,卷积核: 3 *2 * 2,深度为3;下一层的神经元的值为:。卷积核的深度和感受视野的深度一样,都由输入数据来决定,长款可由自己来设定,数目也可以由自己来设定,一个卷积核依然对应一个feature map
注:“strid**e=1stride=1”表示在长和宽上的移动间隔都为1
激励层
激励层主要对卷积层的输出进行一个非线性映射,因为卷积层的计算还是一种线性计算。使用的激励函数一般为ReLu函数:
卷积层和激励层通常合并在一起成为“卷积层”
池化层:
当输入经过卷积层时,若感受视野比较小,步长stride比较小,得到的feature map(特征图)还是比较大,可以通过池化层来对每一个feature map进行降维操作,输出的深度还是不变的,依然为feature map的个数
池化层也有一个“池化视野(filter)”来对feature map矩阵进行扫描,对“池化视野”中的矩阵值进行计算,一般有两种计算方法
- Max pooling:取“池化视野”矩阵中的最大值
- Average pooling:取“池化视野”矩阵中的平均值
扫描的过程同样会涉及的扫描布长stride,扫描方式同卷积层一样,先从左到右扫描,结束则向下移动布长大小,再从左到右。如下图示例所示:
其中“池化视野”filter: 2 *2,步长stride:2.(注:“池化视野”为个人叫法)
最后可将3个24 *24的feature map下采样得到3个2 * 24 * 24的特征矩阵
归一化层
-
Batch Normalization
Batch Normalization(批量归一化)实现了在神经网络层的中间进行预处理的操作,即在上一层的输入归一化处理后再进入网络的下一层,这样可有效地防止“梯度弥散”,加速网络训练
Batch Normalization具体的算法如下图所示:
每次训练时,取 batch_size 大小的样本进行训练,在BN层中,将一个神经元看作一个特征,batch_size 个样本在某个特征维度会有 batch_size 个值,然后在每个神经元 维度上的进行这些样本的均值和方差,通过公式得到 ,再通过参数 和进行线性映射得到每个神经元对应的输出 $$\boldsymbol{y}_{i}$$ 。在BN层中,可以看出每一个神经元维度上,都会有一个参数 和,它们同权重一样可以通过训练进行优化。
在卷积神经网络中进行批量归一化时一般对 未进行ReLu激活的 feature map进行批量归一化,输出后再作为激励层的输入,可达到调整激励函数偏导的作用。
一种做法是将 feature map 中的神经元作为特征维度,参数 和 的数量和则等于 ,这样做的话参数的数量会变得很多
另一个做法是把 一个 feature map 看做一个特征维度,一个 feature map 上的神经元共享这个 feature map的 参数 和 ,参数 和 的数量和则等于 ,计算均值和方差则在batch_size个训练样本在每一个feature map维度上的均值和方差。
注: 指的是一个样本的feature map数量,feature map跟神经元一样也有一定的排列顺序
Batch Normalization 算法的训练过程和测试过程的区别:
在训练过程中,我们每次都会将 batch_size 数目大小的训练样本 放入到CNN网络中进行训练,在BN层中自然可以得到计算输出所需要的 均值 和 方差 ;
而在测试过程中,我们往往只会向CNN网络中输入一个测试样本,这时在BN层计算的均值和方差会均为 0,因为只有一个样本输入,因此BN层的输入也会出现很大的问题,从而导致CNN网络输出的错误。所以在测试过程中,我们需要借助训练集中所有样本在BN层归一化时每个维度上的均值和方差,当然为了计算方便,我们可以在 batch_num 次训练过程中,将每一次在BN层归一化时每个维度上的均值和方差进行相加,最后再进行求一次均值即可。
切分层
在一些应用中,需要对图片进行切割,独立地对某一部分区域进行单独学习,这样可以对特定部分进行通过调整感受视野进行力度更大的学习
融合层
融合层可以对切分层进行融合,也可以对不同大小的卷积核学习到的特征进行融合
融合的方法有几种,一种是特征矩阵之间的拼接级联,另一种是特征矩阵进行运算(+,-,x,max,conv)
全连接层和输出层
全连接层主要对特征进行重新拟合,减少特征信息的丢失;输出层主要准备做好最后目标结果的输出
经典的卷积神经网络结构通常为
输入层 ----> (卷积层 + ----> 池化层?) + ----> 全连接层 + ----> 输出层
Tensorflow代码
主要的函数说明
卷积层:
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
参数说明:
- data_format:表示输入的格式,有两种分别为:“NHWC”和“NCHW”,默认为“NHWC
- data_format 设置为 “NHWC” 时,排列顺序为 [batch, height, width, channels];
- data_format 设置为 “NCHW” 时,排列顺序为 [batch, channels, height, width]。
N表示这批图像有几张,H表示图像在竖直方向有多少像素,W表示水平方向像素数,C表示通道数(例如黑白图像的通道数 C = 1,而 RGB 彩色图像的通道数 C = 3)
两种格式的区别如下图所示:
NCHW 中,C 排列在外层,每个通道内像素紧挨在一起,即 ‘RRRRRRGGGGGGBBBBBB’ 这种形式。
NHWC 格式,C 排列在最内层,多个通道对应空间位置的像素紧挨在一起,即 ‘RGBRGBRGBRGBRGBRGB’ 这种形式。
- input:输入是一个4维格式的(图像)数据,数据的 shape 由 data_format 决定
- filter:卷积核是一个4维格式的数据:shape表示为:[height,width,in_channels, out_channels],分别表示卷积核的高、宽、深度(与输入的in_channels应相同)、输出 feature map的个数(即卷积核的个数)。
- strides:表示步长,一个长度为4的一维列表,每个元素跟data_format互相对应,表示在data——format每一维上的移动步长。当输入的默认格式为“NHWC”,则strides = [batch , in_height , in_width, in_channels],其中batch和in_channel要求一定为1,即只能在一个样本的一个通道上的特征图上进行移动,in_height,in_width表示卷积核在特征图的高度和宽度上移动的步长
- padding:表示填充方式,“SAME”表示采用填充的方式,简单地理解以0填充边缘,当stride为1时,输入和输出的维度相同,“VALID”表示采用不填充的方式,多余的进行丢弃
池化层:
tf.nn.max_pool(value,ksize,strides,padding,data_format=’NHWC’,name=None)
tf.nn.avg_pool(…)
- value:表示池化的输入,一个4维格式的数据,数据的shape由data_format决定,默认情况下shape为[batch, height, width, channels]
- 其他参数与tf.nn.cov2d类型
- ksize:表示池化窗口的大小,一个长度为4的一维列表,一般为[1, height, width, 1],因不想在batch和channels上做池化,则将其值设为1。
Batch Normalization层:
battch_normalization(x, mean, variance, offset, scale, variance_epsilon, name = “None”)
- mean 和 variance通过tf.nn.moments来进行计算。batch_mean,batch_var = tf.nn.moments(x, axes = [0, 1, 2], keep_dims = True),注意axes的输入。对于以feature map为维度的全局归一化,若feature map的shape为[batcj, height, width, depth],则将axes赋值为[0, 1, 2]
- x为输入的feature map四维数据,offset、scale为一维Tensor数据,shape等于feature map的深度depth
源代码:
1 | import torch |