1. 卷积神经网络——卷积层、池化层和激活函数
2018年11月20日,在看tensorflow的时候发现还是有很多概念没有理解透彻,发现一个很赞的资源(估计大家都知道的,只有我现在才发现),吴恩达老师在网易云课堂上开的深度学习的 课程 ,感觉很赞.本文实际上是吴恩达卷积神经网络视频学习笔记。
2019年2月14日,再次温故这部分的内容,添加了1.1章节的自问自答,添加了对池化层实现反向传播的方式,添加了激活函数relu和sigmoid的对比。
通过一个3 * 3的每列值相同、第一列为1,第二列为0,第三列为-1的过滤器可以检测垂直的边沿。注意到1表示亮,-1表示暗。这样可以发现正负值的边沿。
对于垂直边缘过滤器而言,重要的是中间一列为0,左右两列的值可以相差尽可能的大。
这个过滤器的数值也是可以通过反向传播皮运行算法学习的,不一定需要在算法开始之前就决定。
深度学习甚至可以去学习其他的边沿,无论是45度、73度乃至是其他的角度,虽然比手工要复杂一些,但是确实具有这样的能力。
为什么需要填充?大家都知道,卷积就是用过滤器(f x f)从左到右、从上到下的扫描一个矩阵(n x n)。有两种卷积操作,一种称为valid-conv,一种称为same-conv。每次卷积的时候,过滤器右侧碰到矩阵右边界就结束当前行的扫描,下侧碰到矩阵下边界就结束扫描,因此通过过滤器的图像都会缩小,变为(n-f+1) * (n-f+1)。valid-conv就是这样的卷积操作,而same-conv会在卷积之前填充原始图,使得卷积之后的大小不变。
一般来说燃哗,若原图像大小为n * n,过滤器大小为f * f,那么需要padding的大小为p=(f-1)/2。一般来说我们会设置f为奇数,很少看见偶数的过滤器。其中的原因之一就是为了对称填充。另一个原因可能是一般需要将过滤器的中间点用于定位卷积的位置,而偶数过滤器没有中间点。
上面的提到的卷积过程每次只移动一步。实际上过滤器可以移动不止一步,用s表示步长。那么n x n的矩阵输入, f x f的过滤器, p填充padding,以及s步长的情况下,输出的矩阵大小为 (n+2p-f)/2+1 x (n+2p-f)/2+1 ,这里是向下取整的,这意味过滤器只能在输入图像内部移动,不可以移动出边缘。
注意 在tensorflow中,有两种填充方式,一种是same,一种是valid。same是填充,而valid是不填充。如果遇到valid,那么实际计算矩阵大小的时候,是向上取悄袜整,而不是这里提到的向下取整。如果是same模式,那么最后的矩阵形状是n/s,也是向上取整
上面提到的卷积的输入是n x n的,这一般是灰度图像。对应彩色图像则存在RGB三个颜色channel,这样的图片是n x n x 3。此时的过滤器也必须存在第三个维度,即channel维度,且一个过滤器的channel维度必须和输入的channel维度一致。这样的卷积结果就是三个维度上,过滤器和输入的重叠位置乘积之和。最后的输出是(n - f + 1) x ( n - f +1)的。 注意,输出是二维的
我们可以使用N个不同的过滤器得到不同的N个二维输出,按照输入的格式将其叠起来,这样输出就是 (n - f + 1) x ( n - f +1) x N了。
在上面一节中已经讲了如何得到输入和一个过滤器卷积之后的结果。通常会给卷积的结果添加一个偏执,然后使用非线性的函数进行处理,得到的就是这层网络的输出。将过滤器的参数标记为W,偏置为 b(一个channel的输出矩阵Wa的偏置是一个实数,而非一个矩阵。一个layer的偏置b的维度和通道数channel一致) , 输入数据为上层的激活值。这样每个过滤器处理之后的结果就可以看成是经过了该layer一个节点之后的输出。
下面是每层的符号标记,以及根据上一层计算下一层输入大小的公式,右下角是使用BP学习更新的时候参数更新的次数。可以看到每层的参数的个数只和这层的filter的大小、数目有关,而和输入的规模无关。这样就可以通过控制参数的数量避免过拟合了。
可以从下面的课件中看到,卷积神经网络的趋势是长度和高度逐渐减少,而channel逐渐加深。最后一层会将卷积层平铺开来,形成一个全连接。全连接层会连接到最后一个判别函数上,判别函数可以是logistic或者softmax层,用于输出类别或者概率。
一般情况下,卷积网络除了卷积层之外,还会有池化层和全连接层,这些层可以提供更好的学习。
池化层一般在卷积层之后,可以也可以看成一个过滤器,实际上实现的一个采样的功能,其主要的思想是,着重提取具有某种倾向的特征,比如最大池化对应的是更显着的特征;平均池化对应的是更加平滑的特征。过滤器有几点不同
一般常用的池化层有max_pooling和average_pooling.max_pooling更加常用。 ,最大池化层意味着检测某个特征,并始终将这个特征留在池化层的输出中 。
池化层的输入n x n x nc,过滤器 f x f,步长s,输出 ((n-f)/s+1) x ((n-f)/s+1) * nc。
一般取s=2,这意味着输入的长宽减小一半。
比较好奇的一个问题是,池化层的存在对反向传播有什么影响?我们都知道在传统的神经网络中,反向传播算法实际上就是利用函数的梯度进行反向传播的,那么池化层这种既改变了矩阵大小又不好求导的情况,怎么处理呢?
(下面的内容来自 迷川浩浩_ZJU 的博客 )
mean pooling的前向传播就是把一个patch中的值求取平均来做pooling,那么反向传播的过程也就是把某个元素的梯度等分为n份分配给前一层,这样就保证池化前后的梯度(残差)之和保持不变,还是比较理解的。mean pooling比较容易让人理解错的地方就是会简单的认为直接把梯度复制N遍之后直接反向传播回去,但是这样会造成loss之和变为原来的N倍,网络是会产生梯度爆炸的。
2、max pooling
max pooling也要满足梯度之和不变的原则,max pooling的前向传播是把patch中最大的值传递给后一层,而其他像素的值直接被舍弃掉。那么反向传播也就是把梯度直接传给前一层某一个像素,而其他像素不接受梯度,也就是为0。所以max pooling操作和mean pooling操作不同点在于需要记录下池化操作时到底哪个像素的值是最大,也就是max id
一般概念上的一层包括卷积层和池化层,之所以不把池化层当做新的一层是因为池化层没有需要学习的参数,一般意义上的layer是有权重和参数需要学习的。
尽量不要自己设置超参数,而是尽量参考别人论文里面使用的超参数,选择一个在别人任务中效果很好的超参数。
下面的表中列举了上面的网络每一层的数据规模a^(l)以及参数数量。可以发现数据的规模逐渐减小。主卷积层的参数比较少,而进入全连接层之后参数数量很大。(表格中最后三列的参数数量可能存在错误,应该是48000 + 120, 120 * 84 + 84, 84 * 10 + 10)
以上的两个特征可以明显的减少参数。减少过拟合
(内容来自 迷川浩浩_ZJU 的博客 )
常用的激活函数有sigmoid函数和relu函数.
Relu(x)={if x>0 then x;else 0}为了在反向传播算法中可以正常使用,将其在x=0x=0处的导数置为1,所以它的导数也就变为了 δRelu(x)={if x>0 then 1 else 0}
Relu是一个非常优秀的激活哈数,相比较于传统的Sigmoid函数,有三个作用
2. 卷积神经网络
1、二维互相关运算
二维互相关(cross-correlation)运算的输入是一个二维输入数组和一个二维核(kernel)数组,输出也是一个二维数组,其中核数组通常称为卷积核或过滤器(filter)。卷积核的尺寸通常小于输入数组,卷积核在输入数组上滑动,在每个位置上,卷积核与该位置处的输入子数组按元素相乘并求和,得到输出数组中相应位置的元素。图1展示了一个互相关运算的例子,阴影部分分别是输入的第一个计算区域、核数组以及对应的输出。
2、二维卷积层
卷积层得名于卷积运算,但卷积层中用到的并非卷积运算而是互相关运算。我们将核数组上下翻转、左右翻转,再与输入数组做互相关运算,这一过程就是卷积运算。由于卷积层的核数组是可学习的,所以使用互相关运算与使用卷积运算并无本质区别。
二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏置来得到输出。卷积层的模型参数包括卷积核和标量偏置。
3、特征图与感受野
二维卷积层输出的二维数组可以看作是输入在空间维度(宽和高)上某一级的表征,也叫特征图(feature map)。影响元素x的前向计算的所有可能输入区域(可能大于输入的实际尺寸)叫做x的感受野(receptive field)。
以图1为例,输入中阴影部分的四个元素是输出中阴影部分元素的感受野。我们将图中形状为2×2的输出记为Y,将Y与另一个形状为2×2的核数组做互相关运算,输出单个元素z。那么,z在Y上的感受野包括Y的全部四个元素,在输入上的感受野包括其中全部9个元素。可见,我们可以通过更深的卷积神经网络使特征图中单个元素的感受野变得更加广阔,从而捕捉输入上更大尺寸的特征。
4、填充和步幅
我们介绍卷积层的两个超参数,即填充和步幅,它们可以对给定形状的输入和卷积核改变输出形状。
4.1 填充(padding)
是指在输入高和宽的两侧填充元素(通常是0元素),图2里我们在原输入高和宽的两侧分别添加了值为0的元素。
如果原输入的高和宽是 和 ,卷积核的高和宽是 和 ,在高的两侧一共填充 行,在宽的两侧一共填充 列,则输出形状为:
)
我们在卷积神经网络中使用奇数高宽的核,比如3×3,5×5的卷积核,对于高度(或宽度)为大小为2k+1的核,令步幅为1,在高(或宽)两侧选择大小为k的填充,便可保持输入与输出尺寸相同。
4.2 步幅(stride)
在互相关运算中,卷积核在输入数组上滑动,每次滑动的行数与列数即是步幅(stride)。此前我们使用的步幅都是1,图3展示了在高上步幅为3、在宽上步幅为2的二维互相关运算。
一般来说,当高上步幅为 ,宽上步幅为 时,输出形状为:
如果 ,那么输出形状将简化为:
更进一步,如果输入的高和宽能分别被高和宽上的步幅整除,那么输出形状将是:(nh/sh)×(nw/sw)
当 时,我们称填充为p;当 时,我们称步幅为s。
5、多输入通道和多输出通道
之前的输入和输出都是二维数组,但真实数据的维度经常更高。例如,彩色图像在高和宽2个维度外还有RGB(红、绿、蓝)3个颜色通道。假设彩色图像的高和宽分别是h和w(像素),那么它可以表示为一个3×h×w的多维数组,我们将大小为3的这一维称为通道(channel)维。
5.1 多输入通道
卷积层的输入可以包含多个通道,图4展示了一个含2个输入通道的二维互相关计算的例子。
5.2 多输出通道
卷积层的输出也可以包含多个通道,设卷积核输入通道数和输出通道数分别为ci和co,高和宽分别为kh和kw。如果希望得到含多个通道的输出,我们可以为每个输出通道分别创建形状为ci×kh×kw的核数组,将它们在输出通道维上连结,卷积核的形状即co×ci×kh×kw。
对于输出通道的卷积核,我们提供这样一种理解,一个ci×kh×kw的核数组可以提取某种局部特征,但是输入可能具有相当丰富的特征,我们需要有多个这样的ci×kh×kw的核数组,不同的核数组提取的是不同的特征。
5.3 1x1卷积层
最后讨论形状为1×1的卷积核,我们通常称这样的卷积运算为1×1卷积,称包含这种卷积核的卷积层为1×1卷积层。图5展示了使用输入通道数为3、输出通道数为2的1×1卷积核的互相关计算。
1×1卷积核可在不改变高宽的情况下,调整通道数。1×1卷积核不识别高和宽维度上相邻元素构成的模式,其主要计算发生在通道维上。假设我们将通道维当作特征维,将高和宽维度上的元素当成数据样本,那么1×1卷积层的作用与全连接层等价。
6、卷积层与全连接层的对比
二维卷积层经常用于处理图像,与此前的全连接层相比,它主要有两个优势:
一是全连接层把图像展平成一个向量,在输入图像上相邻的元素可能因为展平操作不再相邻,网络难以捕捉局部信息。而卷积层的设计,天然地具有提取局部信息的能力。
二是卷积层的参数量更少。不考虑偏置的情况下,一个形状为(ci,co,h,w)的卷积核的参数量是ci×co×h×w,与输入图像的宽高无关。假如一个卷积层的输入和输出形状分别是(c1,h1,w1)和(c2,h2,w2),如果要用全连接层进行连接,参数数量就是c1×c2×h1×w1×h2×w2。使用卷积层可以以较少的参数数量来处理更大的图像。
X=torch.rand(4,2,3,5)
print(X.shape)
conv2d=nn.Conv2d(in_channels=2,out_channels=3,kernel_size=(3,5),stride=1,padding=(1,2))
Y=conv2d(X)
print('Y.shape: ',Y.shape)
print('weight.shape: ',conv2d.weight.shape)
print('bias.shape: ',conv2d.bias.shape)
输出:
torch.Size([4, 2, 3, 5])
Y.shape: torch.Size([4, 3, 3, 5])
weight.shape: torch.Size([3, 2, 3, 5])
bias.shape: torch.Size([3])
7、池化
7.1 二维池化层
池化层主要用于缓解卷积层对位置的过度敏感性。同卷积层一样,池化层每次对输入数据的一个固定形状窗口(又称池化窗口)中的元素计算输出,池化层直接计算池化窗口内元素的最大值或者平均值,该运算也分别叫做最大池化或平均池化。图6展示了池化窗口形状为2×2的最大池化。
二维平均池化的工作原理与二维最大池化类似,但将最大运算符替换成平均运算符。池化窗口形状为p×q的池化层称为p×q池化层,其中的池化运算叫作p×q池化。
池化层也可以在输入的高和宽两侧填充并调整窗口的移动步幅来改变输出形状。池化层填充和步幅与卷积层填充和步幅的工作机制一样。
在处理多通道输入数据时,池化层对每个输入通道分别池化,但不会像卷积层那样将各通道的结果按通道相加。这意味着池化层的输出通道数与输入通道数相等。
CNN网络中另外一个不可导的环节就是Pooling池化操作,因为Pooling操作使得feature map的尺寸变化,假如做2×2的池化,假设那么第l+1层的feature map有16个梯度,那么第l层就会有64个梯度,这使得梯度无法对位的进行传播下去。其实解决这个问题的思想也很简单,就是把1个像素的梯度传递给4个像素,但是需要保证传递的loss(或者梯度)总和不变。根据这条原则,mean pooling和max pooling的反向传播也是不同的。
7.2 mean pooling
mean pooling的前向传播就是把一个patch中的值求取平均来做pooling,那么反向传播的过程也就是把某个元素的梯度等分为n份分配给前一层,这样就保证池化前后的梯度(残差)之和保持不变,还是比较理解的,图示如下:
mean pooling比较容易让人理解错的地方就是会简单的认为直接把梯度复制N遍之后直接反向传播回去,但是这样会造成loss之和变为原来的N倍,网络是会产生梯度爆炸的。
7.3 max pooling
max pooling也要满足梯度之和不变的原则,max pooling的前向传播是把patch中最大的值传递给后一层,而其他像素的值直接被舍弃掉。那么反向传播也就是把梯度直接传给前一层某一个像素,而其他像素不接受梯度,也就是为0。所以max pooling操作和mean pooling操作不同点在于需要记录下池化操作时到底哪个像素的值是最大,也就是max id。
源码中有一个max_idx_的变量,这个变量就是记录最大值所在位置的,因为在反向传播中要用到,那么假设前向传播和反向传播的过程就如下图所示。
7.4 Pytorch 实现池化层
我们使用Pytorch中的nn.MaxPool2d实现最大池化层,关注以下构造函数参数:
kernel_size – the size of the window to take a max over
stride – the stride of the window. Default value is kernel_size
padding – implicit zero padding to be added on both sides
forward函数的参数为一个四维张量,形状为 ,返回值也是一个四维张量,形状为 ,其中N是批量大小,C,H,W分别表示通道数、高度、宽度。
X=torch.arange(32,dtype=torch.float32).view(1,2,4,4)
pool2d=nn.MaxPool2d(kernel_size=3,padding=1,stride=(2,1))
Y=pool2d(X)
print(X)
print(Y)
练习
1、假如你用全连接层处理一张256 \times 256256×256的彩色(RGB)图像,输出包含1000个神经元,在使用偏置的情况下,参数数量是:
答:图像展平后长度为3×256×256,权重参数和偏置参数的数量是3× 256× 256 × 1000 + 1000 =196609000。
2、假如你用全连接层处理一张256×256的彩色(RGB)图像,卷积核的高宽是3×3,输出包含10个通道,在使用偏置的情况下,这个卷积层共有多少个参数:
答:输入通道数是3,输出通道数是10,所以参数数量是10×3×3×3+10=280。
3、conv2d = nn.Conv2d(in_channels=3, out_channels=4, kernel_size=3, padding=2),输入一张形状为3×100×100的图像,输出的形状为:
答:输出通道数是4,上下两侧总共填充4行,卷积核高度是3,所以输出的高度是104 - 3 + 1=102104−3+1=102,宽度同理可得。
4、关于卷积层,以下哪种说法是错误的:
A.1×1卷积可以看作是通道维上的全连接
B.某个二维卷积层用于处理形状为3×100×100的输入,则该卷积层无法处理形状为3×256×256的输入
C.卷积层通过填充、步幅、输入通道数、输出通道数等调节输出的形状
D .两个连续的3×3卷积核的感受野与一个5×5卷积核的感受野相同
答:选B,对于高宽维度,只要输入的高宽(填充后的)大于或等于卷积核的高宽即可进行计算。
the first layer is a 3 × 3 convolution, the second is a fully connected layer on top of the 3 × 3 output grid of the first layer (see Figure 1). Sliding this small network over the input activation grid boils down to replacing the 5 × 5 convolution with two layers of 3 × 3 convolution.
我们假设图片是5*5的
我们使用5*5的卷积核对其卷积,步长为1,得到的结果是:(5-5)/1+1=1
然后我们使用2个卷积核为3*3的,这里的两个是指2层:
第一层3*3:
得到的结果是(5-3)/1+1=3
第二层3*3:
得到的结果是(3-3)/1+1=1
所以我们的最终得到结果感受野大小和用5*5的卷积核得到的结果大小是一样的!!!
5、关于池化层,以下哪种说法是错误的:
A.池化层不参与反向传播
B.池化层没有模型参数
C.池化层通常会减小特征图的高和宽
D.池化层的输入和输出具有相同的通道数
答:A
选项1:错误,池化层有参与模型的正向计算,同样也会参与反向传播
选项2:正确,池化层直接对窗口内的元素求最大值或平均值,并没有模型参数参与计算
选项3:正确
选项4:正确
参考文献:
https://www.boyuai.com/
https://blog.csdn.net/qq_21578849/article/details/94667699
https://www.hu.com/question/265791259/answer/298610437
https://blog.csdn.net/zouxiaolv/article/details/97366681
3. 卷积神经网络
卷积神经网络 (Convolutional Neural Networks,CNN)是一种前馈神经网络。卷积神经网络是受生物学上感受野(Receptive Field)的机制而提出的。感受野主要是指听觉系统、本体感觉系统和视觉系统中神经元的一些性质。比如在视觉神经系统中,一个神经元的感受野是指视网膜上的特定区域,只有这个区域内的刺激才能够激活该神经元。
卷积神经网络又是怎样解决这个问题的呢?主要有三个思路:
在使用CNN提取特征时,到底使用哪一层的输出作为最后的特征呢?
答:倒数第二个全连接层的输出才是最后我们要提取的特征,也就是最后一个全连接层的输入才是我们需要的特征。
全连接层会忽视形状。卷积层可以保持形状不变。当输入数据是图像时,卷积层会以3维数据的形式接收输入数据,并同样以3维数据的形式输出至下一层。因此,在CNN中,可以(有可能)正确理解图像等具有形状的数据。
CNN中,有时将 卷积层的输入输出数据称为特征图(feature map) 。其中, 卷积层的输入数据称为输入特征图(input feature map) , 输出数据称为输出特征图(output feature map)。
卷积层进行的处理就是 卷积运算 。卷积运算相当于图像处理中的“滤波器运算”。
滤波器相当于权重或者参数,滤波器数值都是学习出来的。 卷积层实现的是垂直边缘检测 。
边缘检测实际就是将图像由亮到暗进行区分,即边缘的过渡(edge transitions)。
卷积层对应到全连接层,左上角经过滤波器,得到的3,相当于一个神经元输出为3.然后相当于,我们把输入矩阵拉直为36个数据,但是我们只对其中的9个数据赋予了权重。
步幅为1 ,移动一个,得到一个1,相当于另一个神经单元的输出是1.
并且使用的是同一个滤波器,对应到全连接层,就是权值共享。
在这个例子中,输入数据是有高长方向的形状的数据,滤波器也一样,有高长方向上的维度。假设用(height, width)表示数据和滤波器的形状,则在本例中,输入大小是(4, 4),滤波器大小是(3, 3),输出大小是(2, 2)。另外,有的文献中也会用“核”这个词来表示这里所说的“滤波器”。
对于输入数据,卷积运算以一定间隔滑动滤波器的窗口并应用。这里所说的窗口是指图7-4中灰色的3 × 3的部分。如图7-4所示,将各个位置上滤
波器的元素和输入的对应元素相乘,然后再求和(有时将这个计算称为乘积累加运算)。然后,将这个结果保存到输出的对应位置。将这个过程在所有位置都进行一遍,就可以得到卷积运算的输出。
CNN中,滤波器的参数就对应之前的权重。并且,CNN中也存在偏置。
在进行卷积层的处理之前,有时要向输入数据的周围填入固定的数据(比如0等),这称为填充(padding),是卷积运算中经常会用到的处理。比如,在图7-6的例子中,对大小为(4, 4)的输入数据应用了幅度为1的填充。“幅度为1的填充”是指用幅度为1像素的0填充周围。
应用滤波器的位置间隔称为 步幅(stride) 。
假设输入大小为(H, W),滤波器大小为(FH, FW),输出大小为(OH, OW),填充为P,步幅为S。
但是所设定的值必须使式(7.1)中的 和 分别可以除尽。当输出大小无法除尽时(结果是小数时),需要采取报错等对策。顺便说一下,根据深度学习的框架的不同,当值无法除尽时,有时会向最接近的整数四舍五入,不进行报错而继续运行。
之前的卷积运算的例子都是以有高、长方向的2维形状为对象的。但是,图像是3维数据,除了高、长方向之外,还需要处理通道方向。
在3维数据的卷积运算中,输入数据和滤波器的通道数要设为相同的值。
因此,作为4维数据,滤波器的权重数据要按(output_channel, input_channel, height, width)的顺序书写。比如,通道数为3、大小为5 × 5的滤
波器有20个时,可以写成(20, 3, 5, 5)。
对于每个通道,均使用自己的权值矩阵进行处理,输出时将多个通道所输出的值进行加和即可。
卷积运算的批处理,需要将在各层间传递的数据保存为4维数据。具体地讲,就是按(batch_num, channel, height, width)的顺序保存数据。
这里需要注意的是,网络间传递的是4维数据,对这N个数据进行了卷积运算。也就是说,批处理将N次的处理汇总成了1次进行。
池化是缩小高、长方向上的空间的运算。比如,如图7-14所示,进行将2 × 2的区域集约成1个元素的处理,缩小空间大小。
图7-14的例子是按步幅2进行2 × 2的Max池化时的处理顺序。“Max池化”是获取最大值的运算,“2 × 2”表示目标区域的大小。如图所示,从
2 × 2的区域中取出最大的元素。此外,这个例子中将步幅设为了2,所以2 × 2的窗口的移动间隔为2个元素。另外,一般来说,池化的窗口大小会和步幅设定成相同的值。比如,3 × 3的窗口的步幅会设为3,4 × 4的窗口的步幅会设为4等。
除了Max池化之外,还有Average池化等。相对于Max池化是从目标区域中取出最大值,Average池化则是计算目标区域的平均值。 在图像识别领域,主要使用Max池化。 因此,本书中说到“池化层”时,指的是Max池化。
池化层的特征
池化层有以下特征。
没有要学习的参数
池化层和卷积层不同,没有要学习的参数。池化只是从目标区域中取最大值(或者平均值),所以不存在要学习的参数。
通道数不发生变化
经过池化运算,输入数据和输出数据的通道数不会发生变化。如图7-15所示,计算是按通道独立进行的。
对微小的位置变化具有鲁棒性(健壮)
输入数据发生微小偏差时,池化仍会返回相同的结果。因此,池化对输入数据的微小偏差具有鲁棒性。比如,3 × 3的池化的情况下,如图
7-16所示,池化会吸收输入数据的偏差(根据数据的不同,结果有可能不一致)。
经过卷积层和池化层之后,进行Flatten,然后丢到全连接前向传播神经网络。
(找到一张图片使得某个filter响应最大。相当于filter固定,未知的是输入的图片。)未知的是输入的图片???
k是第k个filter,x是我们要找的参数。?这里我不是很明白。我得理解应该是去寻找最具有代表性的特征。
使用im2col来实现卷积层
卷积层的参数是需要学习的,但是池化层没有参数需要学习。全连接层的参数需要训练得到。
池化层不需要训练参数。全连接层的参数最多。卷积核的个数逐渐增多。激活层的size,逐渐减少。
最大池化只是计算神经网络某一层的静态属性,没有什么需要学习的,它只是一个静态属性 。
像这样展开之后,只需对展开的矩阵求各行的最大值,并转换为合适的形状即可(图7-22)。
参数
• input_dim ― 输入数据的维度:( 通道,高,长 )
• conv_param ― 卷积层的超参数(字典)。字典的关键字如下:
filter_num ― 滤波器的数量
filter_size ― 滤波器的大小
stride ― 步幅
pad ― 填充
• hidden_size ― 隐藏层(全连接)的神经元数量
• output_size ― 输出层(全连接)的神经元数量
• weitght_int_std ― 初始化时权重的标准差
LeNet
LeNet在1998年被提出,是进行手写数字识别的网络。如图7-27所示,它有连续的卷积层和池化层(正确地讲,是只“抽选元素”的子采样层),最后经全连接层输出结果。
和“现在的CNN”相比,LeNet有几个不同点。第一个不同点在于激活函数。LeNet中使用sigmoid函数,而现在的CNN中主要使用ReLU函数。
此外,原始的LeNet中使用子采样(subsampling)缩小中间数据的大小,而现在的CNN中Max池化是主流。
AlexNet
在LeNet问世20多年后,AlexNet被发布出来。AlexNet是引发深度学习热潮的导火线,不过它的网络结构和LeNet基本上没有什么不同,如图7-28所示。
AlexNet叠有多个卷积层和池化层,最后经由全连接层输出结果。虽然结构上AlexNet和LeNet没有大的不同,但有以下几点差异。
• 激活函数使用ReLU。
• 使用进行局部正规化的LRN(Local Response Normalization)层。
• 使用Dropout
TF2.0实现卷积神经网络
valid意味着不填充,same是填充
or the SAME padding, the output height and width are computed as:
out_height = ceil(float(in_height) / float(strides[1]))
out_width = ceil(float(in_width) / float(strides[2]))
And
For the VALID padding, the output height and width are computed as:
out_height = ceil(float(in_height - filter_height + 1) / float(strides[1]))
out_width = ceil(float(in_width - filter_width + 1) / float(strides[2]))
因此,我们可以设定 padding 策略。在 tf.keras.layers.Conv2D 中,当我们将 padding 参数设为 same 时,会将周围缺少的部分使用 0 补齐,使得输出的矩阵大小和输入一致。
4. 构建ResNet卷积神经网络
2015年,微软亚洲研究院的何凯明团队发布了一种特殊的卷积神经网络——残差神经网络(ResNet)。在残差神经网络出现之前,最深的深度神经网络只有二三十层左右,这该神经网络却可以在实验中轻松达到上百层甚至上千层,另外不会占用过多训练时间,也正因如此,图像识别准确率有了显着增强。此模型更是在同年的ImageNet大赛中,获得图像分类、定位、检测三个项目的冠军。在国际大赛上取得如此优异的成绩,证明了残差神经网络是个实用性强且优异的模型。在本研究中的猫狗二分类的实验中,也是基于残差神经网络来构建分类模型的。
在本文中我们将把kaggle猫狗数据集应用于ResNet-18和ResNet-50网络模型。使用Resnet来探究当前使用卷积神经网络的准确率。如图4-1为ResNet的经典网络结构图——ResNet-18。
ResNet-18都是由BasicBlock组成,从图4-2也可得知50层及以上的ResNet网络模型由BottleBlock组成。在我们就需要将我们预处理过的数据集放入现有的Resnet-18和ResNet-50模型中去训练,首先我们通过前面提到的图像预处理把训练图像裁剪成一个96x96的正方形尺寸,然后输入到我们的模型中,这里就介绍一下ResNet-18的网络模型的结构,因为ResNet50与第五章的ResNet-34模型结构相仿。
ResNet-18的模型结构为:首先第一层是一个7×7的卷积核,输入特征矩阵为[112,112,64],经过卷积核64,stride为2得到出入特征矩阵[56,56,64]。第二层一开始是由一个3×3的池化层组成的,接着是2个残差结构,一开始的输入的特征矩阵为[56,56,64],需要输出的特征矩阵shape为[28,28,128], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[56,56,64]这个特征矩阵的高和宽从56通过主分支的stride为2来缩减为原来的一半即为28,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1x1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过128个卷积核将输入的特征矩阵的深度也变为了128。第三层,有2个残差结构,输入的特征矩阵shape是[28,28,128],输出特征矩阵shape是[14,14,256], 然而主分支与shortcut的输出特征矩阵shape必须相同,所以[14,14,256]这个特征矩阵的高和宽从14通过主分支的stride为2来缩减为原来的一半即为7,再通过128个卷积核来改变特征矩阵的深度。然而这里的shortcut加上了一个1×1的卷积核,stride也为2,通过这个stride,输入的特征矩阵的宽和高也缩减为原有的一半,同时通过256个卷积核将输入的特征矩阵的深度也变为了256。第四层,有2个残差结构,经过上述的相同的变化过程得到输出的特征矩阵为[7,7,512]。第五层,有2个残差结构, 经过上述的相同的变化过程得到输出的特征矩阵为[1,1,512]。接着是平均池化和全连接层。
5. 卷积神经网络CNN(Convolutional Neural Network)
上图计算过程为,首先我们可以将右边进行卷积的可以称为过滤器也可以叫做核,覆盖到左边第一个区域,然后分别按照对应位置相乘再相加,3*1+1*1+2*1+0*0+0*0+0*0+1*(-1)+8*(-1)+2*(-1)=-5;
按照上述的计算方法逐步按右移一个步长(步长可以设定为1,2,...等),然后按往下移,逐渐计算相应的值,得出最终的值。
如上图显示,对于第一个图像矩阵对应的图,一边是白色,一边是黑色,那么中间就会存在一个垂直的边缘,我们可以选择一个垂直边缘检测过滤器,如乘法右边的矩阵,那么两者做卷积后得出的图会显示如等号右边的结果矩阵对应的灰度图中间会有一个白色的中间带,也就是检测出来的边缘,那为什么感觉中间边缘带会比较宽呢?而不是很细的一个局域呢?原因是我们输入的图像只有6*6,过于小了,如果我们选择输出更大的尺寸的图,那么结果来说就是相对的一个细的边缘检测带,也就将我们的垂直边缘特征提取出来了。
上述都是人工选择过滤器的参数,随着神经网络的发展我们可以利用反向传播算法来学习过滤器的参数
我们可以将卷积的顾虑器的数值变成一个参数,通过反向传播算法去学习,这样学到的过滤器或者说卷积核就能够识别到很多的特征,而不是依靠手工选择过滤器。
- padding 操作,卷积经常会出现两个问题:
1.每经过一次卷积图像都会缩小,如果卷积层很多的话,后面的图像就缩的很小了;
2.边缘像素利用次数只有一次,很明显少于位于中间的像素,因此会损失边缘图像信息。
为了解决上述的问题,我们可以在图像边缘填充像素,也就是 padding 操作了。
如果我们设置在图像边缘填充的像素数为p,那么经过卷积后的图像是:(n+2p-f+1)x(n+2p-f+1).
如何去选择p呢
通常有两种选择:
-Valid:也就是说不填充操作(no padding),因此如果我们有nxn的图像,fxf的过滤器,那么我们进行卷积nxn fxf=(n-f+1)x(n-f+1)的输出图像;
-Same:也就是填充后是输出图像的大小的与输入相同,同样就有(n+2p)x(n+2p) fxf=nxn,那么可以算,n+2p-f+1=n,得到p=(f-1)/2。
通常对于过滤器的选择有一个默认的准则就是选择过滤器的尺寸是奇数的过滤器。
- 卷积步长设置(Strided COnvolution)
卷积步长也就是我们进行卷积操作时,过滤器每次移动的步长,上面我们介绍的卷积操作步长默认都是1,也就是说每次移动过滤器时我们是向右移动一格,或者向下移动一格。
但是我们可以对卷积进行步长的设置,也就是我们能够对卷积移动的格数进行设置。同样假如我们的图像是nxn,过滤器是fxf,padding设置是p,步长strided设置为s,那么我们进行卷积操作后输出的图像为((n+2p-f)/s+1)x((n+2p-f)/s+1),那么这样就会出现一个问题,如果计算结果不是整数怎么办?
一般是选择向下取整,也就是说明,只有当我们的过滤器完全在图像上能够覆盖时才对它进行计算,这是一个惯例。
实际上上述所述的操作在严格数学角度来说不是卷积的定义,卷积的定义上我们计算的时候在移动步长之前也就是对应元素相乘之前是需要对卷积核或者说我们的过滤器进行镜像操作的,经过镜像操作后再把对应元素进行相乘这才是严格意义上的卷积操作,在数学角度上来说这个操作不算严格的卷积操作应该是属于互相关操作,但是在深度学习领域中,大家按照惯例都省略了反转操作,也把这个操作叫做卷积操作
我们知道彩色图像有RGB三个通道,因此对于输入来说是一个三维的输入,那么对三维输入的图像如何进行卷积操作呢?
例子,如上图我们输入图像假设为6×6×3,3代表有RGB三个通道channel,或者可以叫depth深度,过滤器的选择为3×3×3,其中需要规定的是,顾虑器的channel必须与输入图像的channel相同,长宽没有限制,那么计算过程是,我们将过滤器的立体覆盖在输入,这样对应的27个数对应相乘后相加得到一个数,对应到我们的输出,因此这样的方式进行卷积后我们得出的输出层为4×4×1。如果我们有多个过滤器,比如我们分别用两个过滤器一个提取垂直特征,一个提取水平特征,那么输出图4×4×2 。也就是代表我们输出的深度或者说通道与过滤器的个数是相等的。
第l层的卷积标记如下:
加入我们的过滤器是3×3×3规格的,如果我们设定10个过滤器,那么需要学习的参数总数为每个过滤器为27个参数然后加上一个偏差bias那么每个过滤器的参数为28个,所以十个过滤器的参数为280个。从这里也就可以看出,不管我们输入的图片大小是多大,我们都只需要计算这些参数,因此参数共享也就很容易理解了。
为了缩减模型的大小,提高计算速度,同时提高所提取特征的鲁棒性,我们经常会使用池化层。池化层的计算方式与卷积类似,只是我们需要对每一个通道都进行池化操作。
池化的方式一般有两种:Max Pooling和Average Pooling。
上面为Max Pooling,那么计算方法与卷积类似,首先设定超参数比如过滤器的大小与步长,然后覆盖到对应格子上面,用最大值取代其值作为输出的结果,例如上图为过滤器选择2×2,步长选择为2,因此输出就是2×2的维度,每个输出格子都是过滤器对应维度上输入的最大值。如果为平均池化,那么就是选择其间的平均值作为输出的值。
因此从上面的过程我们看到,通过池化操作能够缩小模型,同时能让特征值更加明显,也就提高了提取特征的鲁棒性。
6. 怎样用python构建一个卷积神经网络
用keras框架较为方便
首先安装anaconda,然后腔升瞎通过pip安装keras
7. 卷积神经网络
一般由卷积层,汇聚层,和全连接层交叉堆叠而成,使用反向传播算法进行训练(反向传播,再重新看一下)
卷积神经网络有三个结构上的特性:局部连接,权重共享以及子采样
滤波器filter 卷积核convolution kernel
局部连接,其实就是根据时间,权重递减 最后为0 参数就传播不到远处了
局部连接 乘以 滤波器 得特征映射
互相关,是一个衡量两个序列相关性的函数,
互相关和卷积的区别在于 卷积核仅仅是否进行翻转,因此互相关也可以称为 不翻转卷积
使用卷积 是为了进行特征抽取,卷积核 是否进行翻转和其特征抽取的能力无关。
当卷积核是可以学习的参数,卷积和互相关是等价的,因此,其实两者差不多。
Tips:P是代表特征映射