CNN有三个特性
稀疏链接参数共享 :平移不变性自然图像有其固有特性,也就是说,图像的一部分的统计特性与其他部分是一样的。这也意味着我们在这一部分学习的特征也能用在另一部分上,所以对于这个图像上的所有位置,我们都能使用同样的学习特征。
更恰当的解释是,当从一个大尺寸图像中随机选取一小块,比如说 8x8 作为样本,并且从这个小块样本中学习到了一些特征,这时我们可以把从这个 8x8 样本中学习到的特征作为探测器,应用到这个图像的任意地方中去。特别是,我们可以用从 8x8 样本中所学习到的特征跟原本的大尺寸图像作卷积,从而对这个大尺寸图像上的任一位置获得一个不同特征的激活值。
在tensorflow中,tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)可以方便的实现卷积操作,其具体用法如下:
除去name参数用以指定该操作的name,与方法有关的一共五个参数 第一个参数input:指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一 第二个参数filter:相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同,有一个地方需要注意,第三维in_channels,就是参数input的第四维 第三个参数strides:卷积时在图像每一维的步长,这是一个一维的向量,长度4 第四个参数padding:string类型的量,只能是”SAME”,”VALID”其中之一,这个值决定了不同的卷积方式(后面会介绍) 第五个参数:use_cudnn_on_gpu:bool类型,是否使用cudnn加速,默认为true 结果返回一个Tensor,这个输出,就是我们常说的feature map 返回值: shape = [batch,out_high,out_width,out_channels]
在上面这个例子中,有一张[5*5*5]的输入,使用了6个[2*2]的卷积核去做卷积,至于参数strides可以理解为strides=[1,x_step,y_step,1]. x_step即每次向x轴方向的步长,y_step表示每次向y轴方向的步长。参数padding 可以为”SAME”,表示卷积核可以停留在图像边缘,缺失的地方用0代替,或者”VALID”表示卷积核只能在图像内部
import tensorflow as tf input = tf.Variable(tf.random_normal([1,5,5,5])) filter = tf.Variable(tf.random_normal([2,2,5,6])) op = tf.nn.conv2d(input, filter, strides=[1,2,2,1], padding="VALID") with tf.Session() as sess: sess.run(tf.global_variables_initializer()) res = sess.run(op) print res.shape >>>(1, 2, 2, 6)同样的,有一张[5*5*5]的输入,使用了6个[2*2]的卷积核去做卷积,参数padding = “VALID”即卷积核在图像内部运动,从结果上看,输出结果形状的高度和宽度都变小了。
假设有这样一张图,双通道 第一个通道: 第二个通道: 用程序去做最大值池化:
import tensorflow as tf image = tf.constant([ [[1.0,2.0,3.0,4.0], [5.0,6.0,7.0,8.0], [8.0,7.0,6.0,5.0], [4.0,3.0,2.0,1.0]], [[4.0,3.0,2.0,1.0], [8.0,7.0,6.0,5.0], [1.0,2.0,3.0,4.0], [5.0,6.0,7.0,8.0]] ]) image = tf.reshape(image,[1,4,4,2]) pooling = tf.nn.max_pool(image, ksize=[1,2,2,1],strides=[1,1,1,1],padding="VALID") with tf.Session() as sess: sess.run(pooling) print pooling.eval() >>>[[[[ 8. 7.] [ 6. 6.] [ 7. 8.]] [[ 8. 7.] [ 8. 7.] [ 8. 7.]] [[ 4. 4.] [ 8. 7.] [ 8. 8.]]]]最大值池化pooling之后的结果为
一个完整的CNN例子见: https://github.com/Johnson0722/Tensorflow_demos/blob/master/simple_CNN.py