最关键就是要理解到卷积神经网络的结构:

卷积层-激活函数-池化层-全连接层(大概就是卷积神经网络的机构了!)

神经网络各个层 神经网络各层 知乎_tensorflow


来按惯例说一下为什么要用卷积神经网络,和为何他会那么热门。

答:因为好用,因为错误率低,反正就是牛逼。然后就看一下图,理解一下。(里面框起来的,就是经过三次这个流程。

神经网络各个层 神经网络各层 知乎_卷积_02


按套路介绍一下各个层的特点:

  • 神经网络(neural networks)的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层和池化层(pooling layer,又叫下采样层)。
  • 卷积层:通过在原始图像上平移来提取特征,每一个特征就是一个特征映射。
  • 池化层:通过特征后稀疏参数来减少学习的参数,降低网络的复杂度,(最大池化和平均池化)。
  • (等下会说各个层的怎么去理解)

先说一下卷积层:(用通俗的话来解释何为卷积)

卷积,先意象一下,卷起来,然后积(“集”?)起来。

先了解:步长:下图就是步长的解释。一个方框(33也可以是任意任意)移动的距离、

橙色的那一个矩阵也就是过滤器filter(也叫卷积核)

神经网络各个层 神经网络各层 知乎_池化_03


先了解一下什么叫填充:

上图为步长为2的时候,如果当步长为3的时候,会出现一种情况就是,这个方框去到右边去了。

如图红色,那么有两种方式解决该问题。1.不越过,就是我不移动了,直接往下(VALID)。2.超过就零填充(SAME)(零填充是大家所推荐的方式)。

神经网络各个层 神经网络各层 知乎_神经网络各个层_04


零填充如图:

神经网络各个层 神经网络各层 知乎_ide_05


了解完,那就了解一下什么叫卷积。

再重复一下:卷积,先意象一下,卷起来,然后积(“集”?)起来。

通俗的话来来将就是:将一堆数据(一个方阵下的数)转换成(或卷积成,意象一下)一个数字,集起来,转换成一个数字

对于激活函数:它的作用就是增加网络的非线性分割能力。通常选择有Sigmod 和 relu(更推荐relu)。

  • why?
  • 第一,采用sigmoid等函数,反向传播求误差梯度时,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多
  • 第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(求不出权重和偏置)
    http://playground.tensorflow.org/ 该网址里面有激活函数选择后的产生学习速率的不同结果。

    对于池化层:Pooling层主要的作用是特征提取,通过去掉Feature Map中不重要的样本,进一步减少参数数量。Pooling的方法很多,最常用的是Max Pooling。

    为什么要这么做,因为在图片中,有很多相似的像素点存在,所以我只需要一个最大的那个,就可以了,不必要去对其他相似的像素点进行计算。

    比如这个图片上,这三个方框里面的像素点其实都差不多的。

利用卷积神经网络来实现数字识别案例代码

神经网络各个层 神经网络各层 知乎_神经网络各个层_06

def weight_variables(shape):
    w = tf.Variable(tf.random_normal(shape=shape, mean=0.0, stddev=1.0))
    return w


def bais_variable(shape):
    bais = tf.Variable(tf.constant(0.0, shape=shape))
    return bais


def model():
    # 1、每一次训练数据都需要准备数据的占位符
    with tf.variable_scope("data"):
        x = tf.placeholder(tf.float32, [None, 784])

        y_true = tf.placeholder(tf.int32, [None, 10])

    # 2、开始卷积 ,第一层卷积, 卷积核大小5*5 32个卷积核 步长为1 零填充
    with tf.variable_scope("conv1"):
        # 关于权重都需要随机初始化,然后慢慢让他训练好
        w_conv1 = weight_variables([5, 5, 1, 32])  # 第一个维度为5,第二个维度为5,第三个维度为1

        b_conv1 = bais_variable([32])

        x_reshape = tf.reshape(x, [-1, 28, 28, 1])

        # [None, 28, 28, 1]-----> [None, 28, 28, 32]
        x_relu1 = tf.nn.relu(tf.nn.conv2d(x_reshape, w_conv1, strides=[1, 1, 1, 1], padding="SAME") + b_conv1)

        # 池化 2*2 ,strides2 [None, 28, 28, 32]---->[None, 14, 14, 32]
        x_pool1 = tf.nn.max_pool(x_relu1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 3、二卷积层卷积: 5*5*32,64个filter,strides=1 激活: tf.nn.relu 池化:
    with tf.variable_scope("conv2"):
        # 随机初始化权重,  权重:[5, 5, 32, 64]  偏置[64]
        w_conv2 = weight_variables([5, 5, 32, 64])

        b_conv2 = bais_variable([64])

        # 卷积,激活,池化计算
        # [None, 14, 14, 32]-----> [None, 14, 14, 64]
        x_relu2 = tf.nn.relu(tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2)

        x_pool2 = tf.nn.max_pool(x_relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 4、全连接层 [None, 7, 7, 64]--->[None, 7*7*64]*[7*7*64, 10]+ [10] =[None, 10]
    with tf.variable_scope("fc"):
        w_fc = weight_variables([7 * 7 * 64, 10])

        b_fc = bais_variable([10])

        x_fc_reshape = tf.reshape(x_pool2, [-1, 7 * 7 * 64])

        y_predict = tf.matmul(x_fc_reshape, w_fc) + b_fc

        return x, y_true, y_predict


def conv_fc():
    # 获取真实的数据
    mnist = input_data.read_data_sets("./data/mnist/input_data/", one_hot=True)

    # 定义模型,得出输出
    x, y_true, y_predict = model()

    # 进行交叉熵损失计算
    # 3、求出所有样本的损失,然后求平均值
    with tf.variable_scope("soft_cross"):
        # 求平均交叉熵损失
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))

    # 4、梯度下降求出损失
    with tf.variable_scope("optimizer"):
        train_op = tf.train.GradientDescentOptimizer(0.0001).minimize(loss)

    # 5、计算准确率
    with tf.variable_scope("acc"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))

        # equal_list  None个样本   [1, 0, 1, 0, 1, 1,..........]
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))

    # 定义一个初始化变量的op
    init_op = tf.global_variables_initializer()

    saver = tf.train.Saver()

    # 开启回话运行
    with tf.Session() as sess:
        sess.run(init_op)
        if FLAGES.is_juanji == 0:
            # 循环去训练
            for i in range(1000):
                # 取出真实存在的特征值和目标值
                mnist_x, mnist_y = mnist.train.next_batch(50)

                # 运行train_op训练
                sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})

                print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))

            saver.save(sess, "./tmp/ckpt3/conv_fc_model")

        elif FLAGES.is_juanji == 1:

            saver.restore(sess, "./tmp/ckpt3/conv_fc_model")

            for i in range(500):
                # 取出真实存在的特征值和目标值
                mnist_x, mnist_y = mnist.train.next_batch(50)

                # 运行train_op训练
                sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})

                print("训练第%d步,准确率为:%f" % (i, sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y})))

            saver.save(sess, "./tmp/ckpt3/conv_fc_model")

        elif FLAGES.is_juanji == 2:

            saver.restore(sess, "./tmp/ckpt3/conv_fc_model")

            for i in range(100):
                # 每次测试一张图片 [0,0,0,0,0,1,0,0,0,0]
                x_test, y_test = mnist.test.next_batch(1)

                print("第%d张图片,手写数字图片目标是:%d, 预测结果是:%d" % (
                    i,
                    tf.argmax(y_test, 1).eval(),
                    tf.argmax(sess.run(y_predict, feed_dict={x: x_test, y_true: y_test}), 1).eval()
                ))

    return None


if __name__ == '__main__':
    # full_connected()
    conv_fc()