04卷积神经网络
一. 卷积神经网络定义与比较
1. 全连接神经网络的缺点
- 参数太多,在cifar-10的数据集中,只有32*32*3,就会有这么多权重,如果说更大的图片,比如200*200*3就需要120000多个,这完全是浪费
- 没有利用像素之间位置信息,对于图像识别任务来说,每个像素与周围的像素都是联系比较紧密的。
- 层数限制
2. 卷积神经网络
神经网络的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层和池化层(pooling layer,又叫下采样层)。
l 卷积层:通过在原始图像上平移来提取特征,每一个特征就是一个特征映射
l 池化层:通过特征后稀疏参数来减少学习的参数,降低网络的复杂度(最大池化和平均池化)
二. 卷积神经网络的结构(面试重点)
1. 卷积层过滤器
2. 激活函数Re-lu
f(x) = max(0,x)
第一,采用sigmoid等函数,反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多
第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(求不出权重和偏置)
3. 池化层
Pooling层主要的作用是特征提取,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。
4. 全连接层
前面的卷积和池化相当于做特征工程,后面的全连接相当于做特征加权。最后的全连接层在整个卷积神经网络中起到“分类器”的作用
三. 卷积层的零填充
卷积核在提取特征映射时的动作称之为padding(零填充),由于移动步长不一定能整出整张图的像素宽度。其中有两种方式,SAME和VALID
l SAME:越过边缘取样,取样的面积和输入图像的像素宽度一致。
l VALID:不越过边缘取样,取样的面积小于输入人的图像的像素宽度
四. 相关API
1. 卷积网络
tf.nn.conv2d(input, filter, strides=, padding=, name=None)
计算给定4-D input和filter张量的2维卷积
l input:给定的输入张量,具有[batch,heigth,width,channel],类型为float32,64
l filter:指定过滤器的大小,[filter_height, filter_width, in_channels, out_channels]
l strides:strides = [1, stride, stride, 1],步长
l padding:“SAME”, “VALID”,使用的填充算法的类型,使用“SAME”。其中”VALID”表示滑动超出部分舍弃,“SAME”表示填充,使得变化后height,width一样大
2. 激活函数
tf.nn.relu(features, name=None) features:卷积后加上偏置的结果return:结果
3. 池化层
tf.nn.max_pool(value, ksize=, strides=, padding=,name=None) 输入上执行最大池数
- value:4-D Tensor形状[batch, height, width, channels]
- ksize:池化窗口大小,[1, ksize, ksize, 1]
- strides:步长大小,[1,strides,strides,1]
- padding:“SAME”, “VALID”,使用的填充算法的类型,使用“SAME”
附:案例代码
1 # 初始化权重和偏置 2 def init_weight(shape): 3 weight = tf.Variable(tf.random_normal(shape, mean=0.0, stddev=1.0), name="w") 4 return weight 5 6 7 def init_bias(shape): 8 bias = tf.Variable(tf.constant(0.0, shape=shape)) 9 return bias 10 11 12 def model(): 13 """ 14 自定义得卷积模型 15 :return: 16 """ 17 # 1.建立占位符 18 with tf.variable_scope("data"): 19 x = tf.placeholder(tf.float32, [None, 784]) 20 y_true = tf.placeholder(tf.int64, [None, 10]) 21 22 # 2.卷积层1 23 with tf.variable_scope("conv1"): 24 w_conv1 = init_weight([5, 5, 1, 32]) 25 b_conv1 = init_bias([32]) 26 x_reshape = tf.reshape(x, [-1, 28, 28, 1]) 27 # [None,28,28,1]->[None,28,28,32] 28 x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1) 29 # 池化2*2 [None,28,28,32]->[None,14,14,32] 30 x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME") 31 32 # 3.卷积层2 33 with tf.variable_scope("conv2"): 34 w_conv2 = init_weight([5, 5, 32, 64]) 35 b_conv2 = init_bias([64]) 36 37 # [None,14,14,32]->[None,14,14,64] 38 x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2) 39 # 池化2*2 [None,14,14,64]->[None,7,7,64] 40 x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME") 41 42 # 4.全连接层 [None,7,7,64]->[None,7*7*64]*[7*7*64,10]->[None,10] 43 with tf.variable_scope("allconv"): 44 w_conv = init_weight([7*7*64, 10]) 45 b_conv = init_bias([10]) 46 47 x_pool_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64]) 48 y_predict = tf.matmul(x_pool_reshape, w_conv) + b_conv 49 50 return x, y_true, y_predict 51 52 53 def conv_fc(): 54 # 获取数据 55 mnist = input_data.read_data_sets("./tmp/input_data", one_hot=True) 56 57 # 定义模型,得出输出 58 x, y_true, y_predict = model() 59 60 # 求损失平均值 61 with tf.variable_scope("soft_cross"): 62 # 求平均交叉熵损失 63 loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict)) 64 65 # 梯度下降求出损失 66 with tf.variable_scope("optimizer"): 67 train_op = tf.train.GradientDescentOptimizer(0.001).minimize(loss) 68 69 # 计算准确率 70 with tf.variable_scope("acc"): 71 equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1)) 72 # 计算张量平均值 73 accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32)) 74 75 init_op = tf.global_variables_initializer() 76 with tf.Session() as sess: 77 sess.run(init_op) 78 79 for i in range(1000): 80 # 取出目标值,特征值 81 m_x, m_y = mnist.train.next_batch(50) 82 sess.run(train_op, feed_dict={x: m_x, y_true: m_y}) 83 print("第%d步,准确率:%f" % (i, sess.run(accuracy, feed_dict={x: m_x, y_true: m_y})))