深度学习04--卷积神经网络

卷积神经网络

与神经网络的对比

  • 传统意义上的多层神经网络是只有输入层、隐藏层、输出层。其中隐藏层的层数根据需要而定,没有明确的理论推导来说明到底多少层合适
  • 卷积神经网络CNN,在原来多层神经网络的基础上,加入了更加有效的特征学习部分,具体操作就是在原来的全连接层前面加入了卷积层与池化层。卷积神经网络出现,使得神经网络层数得以加深,“深度”学习由此而来。

网络原理

三个结构

神经网络(neural networks)的基本组成包括输入层、隐藏层、输出层。而卷积神经网络的特点在于隐藏层分为卷积层和池化层(pooling layer,又叫下采样层)以及激活层。每一层的作用

  • 卷积层:通过在原始图像上平移来提取特征
  • 激活层:增加非线性分割能力
  • 池化层:减少学习的参数,降低网络的复杂度(最大池化和平均池化)

为了能够达到分类效果,还会有一个全连接层(Full Connection)也就是最后的输出层,进行损失计算并输出分类结果。

卷积层

卷积神经网络中每层卷积层由若干卷积单元(卷积核)组成,每个卷积单元的参数都是通过反向传播算法最佳化得到的。
卷积运算的目的是特征提取,第一层卷积层可能只能提取一些低级的特征如边缘、线条和角等层级,更多层的网络能从低级特征中迭代提取更复杂的特征。

卷积核(Filter)的四大要素

  • 卷积核个数

那么如果在某一层结构当中,不止是一个人观察,多个人(卷积核)一起去观察。那就得到多张观察结果。不同的卷积核带的权重和偏置都不一样,即随机初始化的参数

  • 卷积核大小(1*1,3*3,5*5)

  • 卷积核步长

 

  • 卷积核零填充大小

输出大小计算公式

卷积网络API

激活函数

Relu

 

为什么采用新的激活函数

激活函数API

深化层

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

  • max_polling:取池化窗口的最大值
  • avg_polling:取池化窗口的平均值

深化层计算

池化层也有窗口的大小以及移动步长,那么之后的输出大小怎么计算?计算公式同卷积计算公式一样,通常池化层采用2x2大小、步长为2窗口

深化层API

全连接层

前面的卷积和池化相当于做特征工程,最后的全连接层在整个卷积神经网络中起到“分类器”的作用。

总结

案例:CNN-Mnist手写数字识别

网络设计

 

代码

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


tf.compat.v1.disable_eager_execution()
# 1、利用数据,在训练的时候实时提供数据
# mnist手写数字数据在运行时候实时提供给给占位符


tf.compat.v1.app.flags.DEFINE_integer("is_train", 1, "指定是否是训练模型,还是拿数据去预测")
FLAGS = tf.compat.v1.app.flags.FLAGS


def create_weights(shape):
    return tf.Variable(initial_value=tf.compat.v1.random_normal(shape=shape, stddev=0.01))


def create_model(x):
    """
    构建卷积神经网络
    :param x:
    :return:
    """
    # 1)第一个卷积大层
    with tf.compat.v1.variable_scope("conv1"):

        # 卷积层
        # 将x[None, 784]形状进行修改
        input_x = tf.reshape(x, shape=[-1, 28, 28, 1])
        # 定义filter和偏置
        conv1_weights = create_weights(shape=[5, 5, 1, 32])
        conv1_bias = create_weights(shape=[32])
        conv1_x = tf.compat.v1.nn.conv2d(input=input_x, filter=conv1_weights, strides=[1, 1, 1, 1], padding="SAME") + conv1_bias

        # 激活层
        relu1_x = tf.nn.relu(conv1_x)

        # 池化层
        pool1_x = tf.compat.v1.nn.max_pool(value=relu1_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 2)第二个卷积大层
    with tf.compat.v1.variable_scope("conv2"):

        # 卷积层
        # 定义filter和偏置
        conv2_weights = create_weights(shape=[5, 5, 32, 64])
        conv2_bias = create_weights(shape=[64])
        conv2_x = tf.compat.v1.nn.conv2d(input=pool1_x, filter=conv2_weights, strides=[1, 1, 1, 1], padding="SAME") + conv2_bias

        # 激活层
        relu2_x = tf.compat.v1.nn.relu(conv2_x)

        # 池化层
        pool2_x = tf.compat.v1.nn.max_pool(value=relu2_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

    # 3)全连接层
    with tf.compat.v1.variable_scope("full_connection"):
        # [None, 7, 7, 64]->[None, 7 * 7 * 64]
        # [None, 7 * 7 * 64] * [7 * 7 * 64, 10] = [None, 10]
        x_fc = tf.reshape(pool2_x, shape=[-1, 7 * 7 * 64])
        weights_fc = create_weights(shape=[7 * 7 * 64, 10])
        bias_fc = create_weights(shape=[10])
        y_predict = tf.matmul(x_fc, weights_fc) + bias_fc

    return y_predict


def full_connected_mnist():
    """
    单层全连接神经网络识别手写数字图片
    特征值:[None, 784]
    目标值:one_hot编码 [None, 10]
    :return:
    """
    mnist = input_data.read_data_sets("../mnist_data/", one_hot=True)
    # 1、准备数据
    # x [None, 784] y_true [None. 10]
    with tf.compat.v1.variable_scope("mnist_data"):
        x = tf.compat.v1.placeholder(tf.float32, [None, 784])
        y_true = tf.compat.v1.placeholder(tf.int32, [None, 10])

    y_predict = create_model(x)

    # 3、softmax回归以及交叉熵损失计算
    with tf.compat.v1.variable_scope("softmax_crossentropy"):
        # labels:真实值 [None, 10]  one_hot
        # logits:全脸层的输出[None,10]
        # 返回每个样本的损失组成的列表
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))

    # 4、梯度下降损失优化
    with tf.compat.v1.variable_scope("optimizer"):
        # 学习率
        train_op = tf.compat.v1.train.AdamOptimizer(0.001).minimize(loss)

    # 5、得出每次训练的准确率(通过真实值和预测值进行位置比较,每个样本都比较)
    with tf.compat.v1.variable_scope("accuracy"):
        equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
        accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))

    # (2)收集要显示的变量
    # 先收集损失和准确率
    #tf.summary.scalar("losses", loss)
    #tf.summary.scalar("acc", accuracy)

    # 初始化变量op
    init_op = tf.compat.v1.global_variables_initializer()

    # (3)合并所有变量op
    #merged = tf.compat.v1.summary.merge_all()

    # 创建模型保存和加载
    #saver = tf.compat.v1.train.Saver()

    # 开启会话去训练
    with tf.compat.v1.Session() as sess:
        # 初始化变量
        sess.run(init_op)

        # (1)创建一个events文件实例
        #file_writer = tf.compat.v1.summary.FileWriter("../tmp/summary/", graph=sess.graph)

        # 加载模型
        # if os.path.exists("./tmp/modelckpt/checkpoint"):
        #     saver.restore(sess, "./tmp/modelckpt/fc_nn_model")

        if FLAGS.is_train == 1:
            # 循环步数去训练
            for i in range(500):
                # 获取数据,实时提供
                # 每步提供50个样本训练
                mnist_x, mnist_y = mnist.train.next_batch(50)
                # 运行训练op
                sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
                print("训练第%d步的准确率为:%f, 损失为:%f " % (i+1,
                                     sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y}),
                                     sess.run(loss, feed_dict={x: mnist_x, y_true: mnist_y})
                                     )
                  )

                # 运行合变量op,写入事件文件当中
                #summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
                #file_writer.add_summary(summary, i)
                # if i % 100 == 0:
                #     saver.save(sess, "./tmp/modelckpt/fc_nn_model")

        else:
            # 如果不是训练,我们就去进行预测测试集数据
            for i in range(100):
                # 每次拿一个样本预测
                mnist_x, mnist_y = mnist.test.next_batch(1)
                print("第%d个样本的真实值为:%d, 模型预测结果为:%d" % (
                                                      i+1,
                                                      tf.argmax(sess.run(y_true, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval(),
                                                      tf.argmax(sess.run(y_predict, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval()
                                                      )
                                                      )

    return None


if __name__ == "__main__":
    full_connected_mnist()

 

posted @ 2021-01-29 22:13  MoooJL  阅读(213)  评论(0编辑  收藏  举报