简介
卷积神经网络是对一类深度神经网络的统称,和其余网络相比,其最大的特色在于卷积操作。
首先简单看看CNN中具有代表性的LeNet5模型。
LeNet5模型(用于手写体识别)输入(input)一张32*32的图片,经过卷积(convolutions)后得到C1层的6张28*28特征图,然后经过下采样(subsampling)得到S2层的6张14*14的图片,继续依次执行卷积和下采样便可以得到最终S4层的16张5*5的图片,在此基础上进行两次全连接层[1]和一次高斯连接即可得到最终的输出(OUTPUT),即1*10的向量,该向量由九个0和一个1组成,其中1在向量中的索引即为该图片的标签。
可以看出CNN从输入层开始,直到输出层结束,中间由若干个卷积层、池化层(下采样)和全连接层组合构成。
卷积神经网络各层的矩阵计算
1. 输入层
每张图片都有自己的尺寸,上面的所有的像素点对应着一个二维矩阵,除此之外还要考虑图片的通道(channels),黑白图片是单通道的,RGB图片是三通道的。所以一张图片其实是三维的,其大小可表示为,通常用节点矩阵来表示。
笔记:实际操作中往往在前面还要乘上一个组成一个四维矩阵,这里暂时不考虑。
2. 卷积层
在一个卷积层中,CNN使用单个过滤器(filter)来扫描整个图片通道。扫描的方向和平时写字顺序一样,从上向下一行一行扫描,而每行又是从左向右扫描。扫描时的卷积窗口的大小等于过滤器的尺寸,而步长(strides)则是窗口每次向右或者向下移动的距离。
下图展示了一个3*3的图片经过2*2的过滤器扫描时,依次出现的四个滑动窗口(这里的strides=1)。
滑动窗口的移动还是以LeNet5模型为例,该模型在第一个卷积层中使用的过滤器的大小是5*5,步长为1,每个滑动窗口都会和过滤器进行点积运算(二者都是5*5的矩阵,点积运算就是两个矩阵对应元素分别相乘然后全部加起来得到最终的一个数字),这样一张32*32的图片经5*5的过滤器扫描,最后计算得到的二维矩阵的行和列的大小都是32-5+1=28,即为C1层中28*28的特征图。
鉴于此,如果给定:过滤器大小,步长,图片的大小,输出特征图大小,则它们之间的换算关系为:
笔记:公式中的表示向上取整
然而上面的描述仅仅考虑过滤器的尺寸大小,除此之外过滤器还有自身的深度(depth),下图展示了具有深度的过滤器在一张32*32的RGB图片上对某个卷积窗口进行扫描时的详细过程:
单个卷积窗口的计算过程图解:
这张图片的维度是,即;
整个过滤器的维度是,其中深度对应着
将这张32*32的RGB图片拆成三个通道,每个通道对应着一个二维矩阵,一般情况下,对不同通道使用不同的卷积核,即.
卷积窗口此时位于各个图片通道的最左上角(深灰色小正方形),它们会分别和对应的卷积核(蓝、橙、绿小正方形)进行点乘并累加,然后加上偏置,便得到图中最下方的一维向量(三个小方块).
上图的计算是过滤器在一个卷积窗口上扫描的计算过程,它最终得到的是一个一维向量。随着卷积窗口的移动,过滤器一行行扫描,结合(1)式,整个卷积层输出的是大小为的三维矩阵。
Q1: 为什么要进行卷积操作?
1.全连接网络的参数过多,卷积层是非全连接的,再加上同一卷积层中卷积权值共享,极大减少参数数量
2.很多时候捕捉某个特征并不需要观察整张图片
Q2:为什么全连接层每层节点都是一字排开,但是卷积层的输入输出都是三维节点矩阵?
全连接层神经网络中,相邻两层之间的节点都有边相连,为了形象表示连接结构,将每层都用一列表示。但是,卷积层神经网络中,相邻两层之间只有部分节点相连,为了展示每一层神经元的维度,将每一层卷积层的节点组织成一个三维矩阵。
如果非要将卷积层按照全连接层的形式展开,李宏毅老师PPT上的这张图片可作为参考:
卷积层部分节点相连图解:
将图中6*6的图片按照一列排开,对应右边1到36号节点;此时此刻卷积窗口的每个数字与过滤器上的权重相乘再相加得到3,刚好对应上图右侧的输出节点3,它是只与此时卷积窗口中9个节点相连的(对应编号分别是1,2,3,7,8,9,13,14,15),颜色也是一一对应的。
Q3:如何计算卷积层的参数和连接数?
由于在扫描单个图片通道时使用的是同一个过滤器,所以无论某个图像元素(比如小鸟等)出现在该图片通道的任何位置,结果都是一样的。那么有
Q4:Tensorflow实现卷积
filter_size = 5
channels = 3
depth = 16
filter_weights = tf.get_variable("weights", [filter_size,filter_size,channels,depth], initializer=xxx)
biases = tf.get_variable("biases", [depth], initializer=xxx)
# tf.nn.conv2d()实现卷积, input的shape为[batch_size, image_size, image_size, channels]
conv = tf.conv2d(input, filter_weights, strides=[1, 1, 1, 1], padding='SAME')
bias = tf.nn.bias_add(conv, biases)
actived_conv = tf.nn.relu(bias)
3. 池化层(下采样层)
池化层和卷积层类似,也有一个类似过滤器的结构,不同的是,池化层的计算不是计算内积,而是直接求出窗口中所有元素中的最大值或者平均值,这两种计算方法分别对应最大池化层和平均池化层。除此之外,卷积层的过滤器是横跨整个深度的,但是池化层只能影响一个深度,所以池化层的过滤器还需要在深度上移动。
笔记:通过卷积层处理的结点矩阵,深度都会变深。而池化层不会改变深度,它会缩小结点矩阵的尺寸,并使其最终达到1*1,形成一个向量,以便于作为全连接层的输入。
-
第一个全连接层在全连接基础上稍有改变 ↩
网友评论