卷积神经网络-CNN

前面介绍的算法能够将精度提升到98%,然而卷积神经网络能够将精度提升到99%。

卷积神经网络-CNN

CNN是一种多层神经网络;
相比于传统的BP(back propagation):
1、权值太多,计算量太大;
2、权值太多,需要大量样本进行训练;
由此提出:局部感受野,原理是部分工作,部分不工作。
CNN
CNN通过局部感受野和权值共享减少神经网络需要训练的参数个数。卷积窗口通常为5x5;部分神经元的权值是一样的;
卷积计算
在这里插入图片描述
卷积的步长和要得到多少卷积特征有关;
池化pooling
Pooling常用的三种方式:
1、max-pooling
2、mean-pooling
3、stochastic pooling
常用的池化窗口为2x2,步长为2;
池化的作用是保留更加重要的特征,提取比较大的值,即重要特征。
卷积Padding
SAME PADDING:给平面外部补0;卷积窗口采样后得到一个跟原来大小相同的平面;(必须覆盖所有的原始数据)
VALID PADDING:不会超过平面外部;卷积窗口采样后得到一个比原来平面小的平面;(不能超出原始数据)
在这里插入图片描述在这里插入图片描述
由于SAME PADDING需要保持卷积之后的平面和原始平面大小一样,因此在与卷积核运算时,会超出原始平面范围,需对超出平面部分进行补0;
VALID PADDING需要保证卷积之后的平面均为有效值,因此与卷积核运算过程不会超出原始平面范围。
例子
假设有一个2828的平面,用22步长为2的窗口对其进行pooling操作。
使用SAME PADDING的方式,得到1414的平面
使用VALID PADDING的方式,得到14
14的平面

假设一个23的平面,用22步长为2的窗口对其进行pooling操作。
使用SAME PADDING的方式,得到12的平面
使用VALID PADDING的方式,得到1
1的平面
LeNET-5
在这里插入图片描述

卷积神经网络应用于MINIT数据集分类

# 加载数据 定义变量
mnist = input_data.read_data_sets('MNIST_data',one_hot=True)
#每个批次的大小
batch_size = 64
#计算一共有多少个批次
n_batch = mnist.train.num_examples // batch_size
#定义两个placeholder
x = tf.placeholder(tf.float32,[None,784])        #28*28
y = tf.placeholder(tf.float32,[None,10])
# tf.placeholder 初始化一个数组,None指任意行,
#初始化权值
def weight_variable(shape):
    initial = tf.truncated_normal(shape,stddev=0.1)   #生成一个截断的正态分布
    return tf.Variable(initial)
#初始化偏置
def bias_variable(shape):
    initial = tf.constant(0.1,shape=shape)        # Creates a constant tensor.
    return tf.Variable(initial)
#卷积层
def conv2d(x,W):
    #x input tensor of shape `[batch, in_height, in_width, in_channels]`
    #W filter / kernel tensor of shape [filter_height, filter_width, in_channels, out_channels]
    #`strides[0] = strides[3] = 1`. strides[1]代表x方向的步长,strides[2]代表y方向的步长
    #padding: A `string` from: `"SAME", "VALID"`
    return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
#池化层
def max_pool_2x2(x):
    # Performs the max pooling on the input.
    # 第一个参数value: 需要池化的输入,一般池化层接在卷积层后面,所以输入通常是feature map,依然是[batch, height, width, channels]这样的shape
    # 第二个参数ksize:池化窗口的大小,取一个四维向量,一般是[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1
    # 第三个参数strides:和卷积类似,窗口在每一个维度上滑动的步长,一般也是[1, stride,stride, 1]
    # 第四个参数padding:和卷积类似,可以取'VALID' 或者'SAME'
    return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

卷积层和池化层

#改变x的格式转为4D的格式[batch, in_height, in_width, in_channels] [批次大小 高度 宽度 通道数]
x_image = tf.reshape(x,[-1,28,28,1])   # -1 自动匹配维度的含义       

#初始化第一个卷积层的权值和偏置
W_conv1 = weight_variable([5,5,1,32])#5*5的采样窗口,32个卷积核从1个平面抽取特征   #输入通道数1
b_conv1 = bias_variable([32])#每一个卷积核一个偏置值

#把x_image和权值向量进行卷积,再加上偏置值,然后应用于relu激活函数
h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)#进行max-pooling

#初始化第二个卷积层的权值和偏置    # 输入32 输出64
W_conv2 = weight_variable([5,5,32,64])#5*5的采样窗口,64个卷积核从32个平面抽取特征
b_conv2 = bias_variable([64])#每一个卷积核一个偏置值

#把h_pool1和权值向量进行卷积,再加上偏置值,然后应用于relu激活函数
h_conv2 = tf.nn.relu(conv2d(h_pool1,W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)#进行max-pooling

28 * 28的图片第一次卷积后还是28 * 28,第一次池化后变为14 * 14
第二次卷积后为14 * 14,第二次池化后变为了7 * 7
进过上面操作后得到64张7 * 7的平面
(64,7,7,64) 7 * 7 特征值的大小 64 * 64 是图片多少
卷积不改变维度,池化才改变维度

全链接层

#初始化第一个全连接层的权值
W_fc1 = weight_variable([7*7*64,1024])#上一层有7*7*64个神经元,全连接层有1024个神经元
b_fc1 = bias_variable([1024])#1024个节点

#把池化层2的输出扁平化为1维,将第二层池化层输出,转换维度为一维
h_pool2_flat = tf.reshape(h_pool2,[-1,7*7*64])    # 7*7*64 代表神经元个数   -1 自动匹配
#求第一个全连接层的输出::输出维度1*1024
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1) + b_fc1)

#keep_prob用来表示神经元的输出概率
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob)    # dropout 防止过拟合

#初始化第二个全连接层
W_fc2 = weight_variable([1024,10])
b_fc2 = bias_variable([10])

#计算输出 输出维度1*10
prediction = tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2) + b_fc2)

代价函数,梯度下降优化,取误差的全局极小值

#交叉熵代价函数
cross_entropy = tf.losses.softmax_cross_entropy(y,prediction)
#使用AdamOptimizer进行优化
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#结果存放在一个布尔列表中
correct_prediction = tf.equal(tf.argmax(prediction,1),tf.argmax(y,1))#argmax返回一维张量中最大的值所在的位置
#求准确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

新建会话,开始训练模型
此处可以结合上一讲,自适应的学习率,看看效果

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for epoch in range(21):
        for batch in range(n_batch):
            batch_xs,batch_ys =  mnist.train.next_batch(batch_size)
            sess.run(train_step,feed_dict={x:batch_xs,y:batch_ys,keep_prob:0.7})

        acc = sess.run(accuracy,feed_dict={x:mnist.test.images,y:mnist.test.labels,keep_prob:1.0})
        print ("Iter " + str(epoch) + ", Testing Accuracy= " + str(acc))

上一讲自适应的学习率

lr = tf.Variable(0.001, dtype=tf.float32)
# 每次迭代时候更新
sess.run(tf.assign(lr, 0.001 * (0.95 ** epoch)))

learning_rate = sess.run(lr)

长短时记忆网络-LSTM

卷积网络比LSTM更加适合处理图像

#定义RNN网络
def RNN(X,weights,biases):
    # inputs=[batch_size, max_time, n_inputs]
    inputs = tf.reshape(X,[-1,max_time,n_inputs])  # LSTM对数据格式有要求 3维  与卷积类似
    #定义LSTM
    lstm_cell = tf.nn.rnn_cell.LSTMCell(lstm_size)   # 有lstm_size个brock
#    final_state[state, batch_size, cell.state_size]
#    final_state[0]是cell state
#    final_state[1]是hidden_state
#    outputs: The RNN output `Tensor`.
#       If time_major == False (default), this will be a `Tensor` shaped:
#         `[batch_size, max_time, cell.output_size]`.
#       If time_major == True, this will be a `Tensor` shaped:
#         `[max_time, batch_size, cell.output_size]`.
    outputs,final_state = tf.nn.dynamic_rnn(lstm_cell,inputs,dtype=tf.float32)         # 输出三维数据与softmax略有不一样 final_state指最终的输出
    # outputs 保留28个序列的每个输出。softmax激活函数
    results = tf.nn.softmax(tf.matmul(final_state[1],weights) + biases)
    return results
#计算RNN的返回结果,接下来的计算过程,与前几讲所述的内容基本一致
prediction= RNN(x, weights, biases)  

以图像处理的数据集为例,卷积神经网络的效果明显优于RNN

发布了44 篇原创文章 · 获赞 8 · 访问量 6734

猜你喜欢

转载自blog.csdn.net/zhaodeming000/article/details/95041283