基于CNN网络深度学习杂记
1.CNN 即为卷积神经网络。
参考Charlotte77博客(https://www.cnblogs.com/charlotte77)
1.1为什么需要CNN
传统全连接神经网络对于张量中每一个元素添加权重和偏置,会导致整个网络产生的参数过于巨大。(对于一个2828大小的灰度图像,对其进行矩阵量化并打平后为一个2828=784个元素的一维列向量,隐藏层网络为15个神经元,会添加78415个权重。隐藏层和输出层10个神经元连接后,会添加7841510个权重,最后加上隐藏层和输出层15+10个偏置,总参数量达到78415*10+15+10 = 117625个参数)
并且经过多次反向传播迭代按反向梯度调整参数时,会出现梯度消失的问题。(反向传播即对于当前梯度求导并按照w = w-k*w’的公式更新参数。当梯度消失时,会导致参数无法更新)所以通过CNN能够有效减少神经网络中的参数,并能够保留输入的特征值。
1.2为什么CNN能够在减少参数的情况下仍然可以正确输出结果
对于图像识别,我们不需要完整的判断图像中的每一个像素,大多数情况下只需要提取其中特定的特征值。譬如我们看一张猫的图片,可能看到猫的眼镜或者嘴巴就知道这是张猫片,而不需要说每个部分都看完了才知道,啊,原来这个是猫啊。所以如果我们可以用某种方式对一张图片的某个典型特征识别,那么这张图片的类别也就知道了。这个时候就产生了卷积的概念。
对于卷积的运算公式:
将卷积核翻转180度后对其将相应元素相加即可
如feature map [0][0] = 11+0(-1)+11+1(-1)= 1
feature_map尺寸计算公式:[ (原图片尺寸 -卷积核尺寸)/ 步长 ] + 1
步长即为每次卷积核移动的长度
对于卷积后得到的feature map 为了减少计算量,还可以进行池化处理
以Max_pool即最大值池化为例,
定义pool_size =22 pool_stride =1 即池化大小为2 步长为1
就是在feature map中,每22的矩阵中取得最大值填入输出结果的相应位置。滑动步长为1
这样就提取了卷积后最显著的特征,在部分情况下能够减少计算
当然 不是所有情况下都适合最大值池化。需要考虑周边特征值是否对输出结果同样有影响。这种情况下可以采用平均值池化。即每个池化范围内取平均值。
虽然经历了卷积,池化之后参数减少了,但同时,图片的大小也减小了,为了保持图片输入输出大小不变,需要对原图片进行Zero padding(补0)。
通常情况下,我们希望图片做完卷积操作后保持图片大小不变,所以我们一般会选择尺寸为33的卷积核和1的zero padding,或者55的卷积核与2的zero padding,这样通过计算后,可以保留图片的原始尺寸。那么加入zero padding后的feature_map尺寸 =( width + 2 * padding_size - filter_size )/stride + 1
width为原图片未补0的大小
1.3小结
1.卷积核的尺寸不一定非得为正方形。长方形也可以,只不过通常情况下为正方形。如果要设置为长方形,那么首先得保证这层的输出形状是整数,不能是小数。如果你的图像是边长为 28 的正方形。那么卷积层的输出就满足 [ (28 - kernel_size)/ stride ] + 1 ,这个数值得是整数才行,否则没有物理意义。譬如,你算得一个边长为 3.6 的 feature map 是没有物理意义的。 pooling 层同理。FC 层的输出形状总是满足整数,其唯一的要求就是整个训练过程中 FC 层的输入得是定长的。如果你的图像不是正方形。那么在制作数据时,可以缩放到统一大小(非正方形),再使用非正方形的 kernel_size 来使得卷积层的输出依然是整数。总之,撇开网络结果设定的好坏不谈,其本质上就是在做算术应用题:如何使得各层的输出是整数。
2.卷积核的个数由经验确定。通常情况下,靠近输入的卷积层,譬如第一层卷积层,会找出一些共性的特征,如手写数字识别中第一层我们设定卷积核个数为5个,一般是找出诸如"横线"、“竖线”、“斜线”等共性特征,我们称之为basic feature,经过max pooling后,在第二层卷积层,设定卷积核个数为20个,可以找出一些相对复杂的特征,如“横折”、“左半圆”、“右半圆”等特征,越往后,卷积核设定的数目越多,越能体现label的特征就越细致,就越容易分类出来,打个比方,如果你想分类出“0”的数字,你看到这个特征,能推测是什么数字呢?只有越往后,检测识别的特征越多,试过能识别这几个特征,那么我就能够确定这个数字是“0”。