TensorFlow-深度学习-11-卷积神经网络(CNN)

我们在计算机中所看到的图像,在计算机中表示为一个个矩阵,一串串数字。在神经网络中,我们需要将这些数据在输入端reshape成一个1行n列的数组。通常我们使用的图片不会太小,否则特征点很容易丢失,可即便是一张28*28的图像(mnist手写数据集),在输入层也有784个神经元,更何况一个数据集少则几百张图片,多则上万张图片,这对于简单的神经网络来说压力很大,而且计算量复杂,运行速度慢,效率低下。而卷积神经网络能够有效的提取图像中的主要特征信息,剔除无用的信息,减少计算量,还能够共享权值,这样一来,训练效率提高了,速度提升了,准确率也提高了。

CNN可以应用于图像分类,检测,识别领域,其训练准确度高,能扩展到n层神经网络,所以现在做在计算机视觉领域比较火。CNN由输入和输出层以及多个隐藏层组成,隐藏层可分为卷积层,池化层、RELU层和全连通层。

在这里插入图片描述
CNN通过一系列的卷积池化,最终把特征信息慢慢浓缩出来,利用最后一层特征可以做各种任务:比如分类、回归等。一般的,通过3次卷积就可以达到不错的效果:

第一次卷积可以提取出低层次的特征。

第二次卷积可以提取出中层次的特征。

第三次卷积可以提取出高层次的特征。

1、输入层

输入层的图像可以是灰度图也可以是彩色图,一般是2维向量。

2、卷积层

在OpenCv图像处理中,均值模糊就用到了卷积,只不过用到的滤波器是用来去噪点的,包括canny边缘检测也是一样,也是用了sobel算子和高斯滤波器,得到了边缘图像。所以,不同的滤波器有不同的作用。
在这里插入图片描述
上图中,如果左图是原图,左图红框是卷积核,右图是卷积核每次步长为1移动所产生的的新的图像。左右图中的红框一一对应。比如左图中红框:
1x1+1x0+1x1+1x0+1x1+0x1+1x1+0x0+0x1=4,正好就是右图中红框中的4。从左图到右图好像图像缩小了,这是使用了padding='Valid’方式,即不补0操作,如果要想使图像不缩小,可以使用padding="SAME"方式,即补0操作,就是在左图矩阵的上下左右全部加上0,即:
在这里插入图片描述

3、池化层

池化层又称下采样,它的作用是减小数据处理量同时保留有用信息。怎么减少数据量?那就只能删除数据了。池化层分类3类:
1、平均池化;
2、最大池化;
3、随机池化。

池化层与卷积层的操作有些类似,也有一个卷积核,一般来说该卷积核为2X2大小,步长也为2。
1、平均池化:
在这里插入图片描述
2X2窗口上的4个数值相加处于4就是输出的结果,如上图所示。

2、最大值池化:
在这里插入图片描述
找出卷积核中标定的4邻域中的最大值,如上图所示。

3、随机池化
这个比较不常用,不确定性太多。在4邻域中也随机找出一个值,生成新的特征数据。

4、RELU

RELU是一个激活函数,之前也有介绍过:TensorFlow-深度学习-09-激活与损失函数

5、全连通层

经过卷积-池化-卷积-池化…这样的操作之后,接下来就是基本的神经网络了。可以在神经网络这段神经网络过程中加入dropout,解决神经网络的过拟合问题,提高训练效果。

以上就是CNN的基本流程,总结起来就是:流程:输入层——>第一层卷积层——>第一层池化层——>第二层卷积层——>第二层池化层——>三层全连通层——>输出层

具体参考这篇文章,写的很详细:https://www.cnblogs.com/fydeblog/p/7450413.html

实例:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("mnist/", one_hot=True)


def cnn_demo():
    x = tf.placeholder(shape=[None, 784], dtype=tf.float32)
    x_image = tf.reshape(x, shape=[-1, 28, 28, 1])  # 把一维reshape成2维,[-1,28,28,1]分别表示batch_size,28*28(高,宽)大小,灰度图像
    y = tf.placeholder(shape=[None, 10], dtype=tf.float32)  # 输出值

    '''----------初始化第一次卷积核----------'''
    conv_w1 = tf.Variable(tf.truncated_normal(shape=[5, 5, 1, 32], stddev=0.1),
                          dtype=tf.float32)  # 滤波器, [5,5,1,32]分别表示使用5*5的采样大小,因为是灰度图,所以通道是为1,32表示用32个卷积核采用成32个的特征平面
    conv_b1 = tf.Variable(tf.truncated_normal(shape=[32], stddev=0.1), dtype=tf.float32)  # 32个平面就有32个偏置项

    conv1_out = tf.nn.conv2d(input=x_image, filter=conv_w1, strides=[1, 1, 1, 1],
                             padding='SAME')  # 卷积运算,strides=[1,1,1,1],strides[0]和strides[3]都是固定的,中间两个1表示步长为1,向右向下都往走1步
    relu_conv1 = tf.nn.relu(tf.add(conv1_out, conv_b1))

    '''---------第一层池化计算-----------------'''
    pool_conv1 = tf.nn.max_pool(relu_conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1],
                                padding="SAME")  # ksize是窗口大小(2*2),步长为2

    '''----------初始化第二次卷积核----------'''
    conv_w2 = tf.Variable(tf.truncated_normal(shape=[5, 5, 32, 64], stddev=0.1),
                          dtype=tf.float32)  # 滤波器,[5,5,32,64]分别表示使用5*5的采样大小,32表示32张灰度图,64表示用32个卷积核采用成64个的特征平面
    conv_b2 = tf.Variable(tf.truncated_normal(shape=[64], stddev=0.1), dtype=tf.float32)  # 32个平面就有32个偏置项

    conv2_out = tf.nn.conv2d(input=pool_conv1, filter=conv_w2, strides=[1, 1, 1, 1],
                             padding='SAME')  # 卷积运算,strides=[1,1,1,1],strides[0]和strides[3]都是固定的,中间两个1表示步长为1,向右向下都往走1步
    relu_conv2 = tf.nn.relu(tf.add(conv2_out, conv_b2))
    pool_conv2 = tf.nn.max_pool(relu_conv2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1],
                                padding="SAME")  # ksize是窗口大小(2*2),步长为2

    '''
    一张28*28的图片,经过第一层卷积之后,图像变成32张28*28的大小,第一次池化之后变成14*14大小
    经过第二次卷积之后,图像变成64张14*14大小,第二次池化之后变成7*7大小
    
    
    '''
    # -------下面就是人工神经网络的应用了-------------
    '''--------------第一层全连接层-------------'''
    hidden_num1 = 100
    hidden_num2=50
    drouout_value = tf.placeholder(dtype=tf.float32)
    fc_w1 = tf.Variable(tf.truncated_normal(shape=[7 * 7 * 64, hidden_num1], stddev=0.1), dtype=tf.float32)
    fc_b1 = tf.Variable(tf.truncated_normal(shape=[hidden_num1]), dtype=tf.float32)
    pool_conv2 = tf.reshape(pool_conv2, shape=[-1, 7 * 7 * 64])  # -1表示所有图片,相当于None

    # --------------计算第一层(隐层)神经网络--------------
    nn1 = tf.add(tf.matmul(pool_conv2, fc_w1), fc_b1)
    out1 = tf.nn.dropout(tf.nn.relu(nn1), keep_prob=drouout_value)  # 激活函数,并且加入dropout

    '''--------------第二层全连接层-------------'''
    fc_w2 = tf.Variable(tf.truncated_normal(shape=[hidden_num1, hidden_num2], stddev=0.1), dtype=tf.float32)
    fc_b2 = tf.Variable(tf.truncated_normal(shape=[hidden_num2]), dtype=tf.float32)

    # --------------计算第二层(隐层)神经网络--------------
    nn2 = tf.add(tf.matmul(out1, fc_w2), fc_b2)
    out2 = tf.nn.dropout(tf.nn.relu(nn2),keep_prob=drouout_value)  # 激活函数,并且加入dropout

    '''--------------第三层全连接层-------------'''
    fc_w3 = tf.Variable(tf.truncated_normal(shape=[hidden_num2, 10], stddev=0.1), dtype=tf.float32)
    fc_b3 = tf.Variable(tf.truncated_normal(shape=[10]), dtype=tf.float32)
    # --------------计算第二层(隐层)神经网络--------------
    nn3 = tf.add(tf.matmul(out2, fc_w3), fc_b3) #最后一层一般不做激活
    #out3 = tf.nn.relu(nn3)  # 激活函数


    # ----------------计算loss-------------------
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=y, logits=nn3))
    step = tf.train.GradientDescentOptimizer(learning_rate=0.03).minimize(loss)  # 梯度下降优化器

    # ---------------准确率----------------------
    acc_mat = tf.equal(tf.argmax(y, 1), tf.argmax(nn3, 1))  # 返回的是True和False
    acc_ret = tf.reduce_sum(tf.cast(acc_mat, dtype=tf.float32))
    init = tf.global_variables_initializer()
    with tf.Session() as sess:

        batch_size = 128
        sess.run(init)
        for i in range(10000):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            sess.run(step, feed_dict={x: batch_xs, y: batch_ys, drouout_value: 0.6})

            if (i + 1) % 1000 == 0:
                curr_acc, curr_loss = sess.run([acc_ret, loss],
                                               feed_dict={x: mnist.test.images[:1000], y: mnist.test.labels[:1000],
                                                          drouout_value: 1.0})
                print("第"+str((i+1)//1000)+"次:","准确值:", curr_acc/10,"%", "损失值:", curr_loss)


if __name__ == "__main__":
    cnn_demo()

运行结果:
在这里插入图片描述
我之前在全连接层只加了一层隐层,效果达到了99%,后来加了两层,就达到了上图的结果,所以,调节神经网络也是需要经验的。

发布了88 篇原创文章 · 获赞 39 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Daker_Huang/article/details/88776076