一、 卷积


1. why convolution?

1).计算机视觉问题

分类问题:

 物体识别:

新型艺术: 

 

2).对大量数据的深度学习

* 黑白图片与彩色图片

  • RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。

  • 通常情况下,RGB各有256级亮度,用数字表示为从0、1、2……直到255。注意虽然数字最高是255,但是0也是数值之一,因此共256级。

  • 利用全连接网络来训练学习产生的两个问题:

  • 计算量非常大,对内存的要求高;模型越大,要求的数据样本也就越大,获取数据的成本变高?
  • 当数据量不够巨量,根据我们前面的学习指导大模型极容易导致过拟合,模型纠结与无关紧要的细节,用记忆力吓唬人。 

 

2. 卷积原理

1). 卷积网络的神经科学基础

 卷积核在图像中先提取出若干个区域的局部的特征,在进行进一步的综合处理得到更进一步的特征,最终处理得到全局特征 

对于一张待识别的图片,卷积核会进行纵向识别和横向识别,得到新的特征图

卷积操作:newimage=(n−f)+1

  • 视觉系统:脑皮层的视觉神经元和瞳孔所受到到刺激存在某种对应关系,当瞳孔受到某种刺激,后脑皮层的某一部分神经元就会被激活为兴奋状态
  • 神经元检测:前端神经元只对特定的光模式(精确定向的条纹)有强烈反应

 

3. 卷积层的代码实现


TensorFlow提供的进行卷积运算的函数:

tf.nn.conv2d(input,filter,stride,padding,ues_cudnn_on_gpu,data_format,name) 

1.参数input:

指需要做卷积的输入图像,它要求是一个Tensor,具有[batch, in_height, in_width, in_channels]这样的shape,具体含义是[训练时一个batch的图片数量, 图片高度, 图片宽度, 图像通道数],注意这是一个4维的Tensor,要求类型为float32和float64其中之一
例如:input = tf.Variable(tf.random_normal([1,3,3,5]))


2.参数filter:

相当于CNN中的卷积核,它要求是一个Tensor,具有[filter_height, filter_width, in_channels, out_channels]这样的shape,具体含义是[卷积核的高度,卷积核的宽度,图像通道数,卷积核个数],要求类型与参数input相同。
例如:filter = tf.Variable(tf.random_normal([3,3,5,1]))

3.参数padding:

卷积操作得到的新图大小为4,发生了缩小,如此一来有两个问题:

  1. 每次做卷积操作的时候,图像都会缩小,重复几次卷积操作后图像就会变得很小,可能会缩小到1∗11∗1 ,你可能不希望你的图像在每次卷积操作都发生缩小
  2. 图像角落和边缘的像素点利用率很低,尤其是角落的点,只被计算一次,会造成图像边缘信息丢失

 

p的取值,便是由padding决定的:

  1. padding只能设置为"SAME","VALID"其中之一
  2. padding设置为SAME:添加全0进行填充;
  3. SAME: Pad so that output size is the same as the input size
  4. newimage=(n+2p−f)+1=n
    p=(f−1)/2
  5. f=3,p=(3−1)/2=1
    f=5,p=(5−1)/2=2

  6. padding设置为VALID:不进行添加0的操作;默认情况设置为VALID no padding: newimage=(n−f)+1

  7. 4.参数strides:

    卷积时在图像每一维的步长,这是一个一维的向量:[1, stride,stride, 1],因为我们不想在batch和channels上做卷积,所以这两个维度设为了1

  8. 5.参数use_cudnn_on_gpu

    bool类型,选择是否用GPU进行运算加速。默认为True

    6.参数data_format

    data_format就是input的Tensor格式:

  9. TensorFlow格式下,input为[batch,in_height,in_with,in_channels],Theano模式下会将in_channels提前到第二个维度,因此要用data_format指定,一般默认

  10. 若需要提前,指定data_format= 'channels_first'即可

 结果返回一个Tensor,这个输出,就是我们常说的feature map,shape仍然是[batch, height, width, channels]这种形式。

 

  • Theano是一个Python库,可以在CPU或GPU上运行快速数值计算,这是Python深度学习中的一个关键基础库
  • 目前流行的几种工具:Theano、TensorFlow、Torch、MXNet、Caffe、Neon 和 CNTK,其中前四个框架有着众多高质量的学习资源,便于初学者理解和实现,虽然微软的 CNTK 和英特尔的 Nervana Neon 也是强大的工具,我们却很少能见到有关它们的新手级资料。

 

卷积的特点


相比于全连接网络,卷积操作拥有三个特性,参数共享、稀疏连接、平移不变性,前面两个特性是卷积网络有效减少参数的原因。

  • 1、稀疏连接:此概念是相比较与全连接来的,全连接当中每一个神经元会连接到每一个输入点,而稀疏连接只连接到卷积核窗口对应的输入点,由此产生了稀疏连接的效果
  • 2、参数共享:全连接网络中的每一个权重元素都只使用了一次,而在卷积神经网络中,卷积核的每一个参数都会作用在输入图片的每一个位置上,每一个被卷积窗口扫描到的区域共享一组参数,相比于全连接网络中,每一个神经元都要学习一个单独的参数而言,卷积运算中每一层神经元只需要学习一个卷积核大小的参数集合即可,有效降低参数数量
  • 平移等变性:等变是数学中函数的性质,对于函数f(x)与g(x),若f(g(x))=g(f(x)),则称f(x)对于g(x)具有等变性,卷积运算的平移不变性是指卷积函数f(x)对于平移函数g(x)具有等变性,也就是对于一张图片I,先对图像数据点坐标做平移操作再卷积,和先对图像卷积再对特征图片的坐标进行平移,得到的特征图片的结果是一样的,同样能够提取到相应的特征,正是参数共享机制保证了平移不变性。但是这种不变性只是对平移操作才成立,其他的图像缩放、旋转变换下,还需要其他处理机制才能保证不变性。
#tf.nn.conv2d举例
import tensorflow as tf  
  
a =tf.Variable(tf.random_normal([1,4,4,2]))  
a = tf.floor(a) #向下取整的函数

filter = tf.Variable(tf.random_normal([3,3,2,3]))
#filter = tf.floor(filter)

op = tf.nn.conv2d(a, filter, strides=[1, 1, 1, 1], padding='VALID')
init_op=tf.global_variables_initializer()

with tf.Session() as sess:  
    init_op.run()
    print("image:")  
    image=sess.run(a)  
    print (image)  
    
    #print("filter:")  
    #filter=sess.run(filter)  
    #print (filter)
    
    print("reslut:")  
    result=sess.run(op)  
    print (result)  

 

#7.2 卷积运算程序
import tensorflow as tf
import numpy as np

#使用numpy工具初始化一个名为M的数组,形状为4x4,数据类型为float32
#并使用numpy的reshape()函数调整输入的格式

M = np.array([[[2],[1],[2],[-1]],
              [[0],[-1],[3],[0]],
              [[2],[1],[-1],[4]],
              [[-2],[0],[-3],[4]]],dtype="float32").reshape(1, 4, 4, 1)
filter_weight = tf.get_variable("weights",[2, 2, 1, 1],initializer = tf.constant_initializer([[-1, 4],[2, 1]]))

#通过get_variable()函数创建过滤器的偏置项,代码中[1]表示过滤器的深度。

biases = tf.get_variable("biase",[1],initializer = tf.constant_initializer(1))


x = tf.placeholder('float32', [1,None, None,1])


conv = tf.nn.conv2d(x, filter_weight, strides=[1, 1, 1, 1], padding="SAME")

#bias_add()函数具有给每一个节点加上偏置项点功能。这里不能直接使用加法的原因是
#矩阵上不同位置上的节点都需要加上同样的偏置项。因为过滤器深度为1,
#故偏置项只有一个数,结果为3x4的矩阵中每一个值都要加上这个偏置项。
#原型bias_add(value,bias,data_format,name)
add_bias1 = tf.nn.bias_add(conv, biases)


init_op=tf.global_variables_initializer()

with tf.Session() as sess:
    init_op.run()
    conv = sess.run(conv, feed_dict={x: M})
    M_conv1=sess.run(add_bias1, feed_dict={x: M})

    #输出结果并不是一个张量,而是数组
    print("M after convolution: \n", conv)
    print("conv after bias_add1: \n", M_conv1)

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐