zoukankan      html  css  js  c++  java
  • P73 卷积神经网络识别手写数字

    https://www.bilibili.com/video/BV184411Q7Ng?p=73

     

     数据集介绍:

     

     1.设计占位符:

     注解:

    • [None, 784] 样本数据量未知。[None, 10] 每个样本都有10个类别的概率。

    2.设计网络结构:

     

    注解:

    • 最后一层全连接层,[7,7,64]要变成一个二维的矩阵,[7*7*64],就是说用这么多的特征数量和10个神经元进行全连接。再经过sigmoid函数的作用,变成10个概率值。
    """
    用单层神经网络实现手写数字识别
    
    
    def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format="NHWC", dilations=[1, 1, 1, 1], name=None):
      Computes a 2-D convolution given 4-D `input` and `filter` tensors.
        参数说明:
      Given an input tensor of shape `[batch, in_height, in_width, in_channels]`
      and a filter / kernel tensor of shape
      `[filter_height, filter_width, in_channels, out_channels]`, this op
      performs the following:
    
      1. Flattens the filter to a 2-D matrix with shape
         `[filter_height * filter_width * in_channels, output_channels]`.
      2. Extracts image patches from the input tensor to form a *virtual*
         tensor of shape `[batch, out_height, out_width,
         filter_height * filter_width * in_channels]`.
      3. For each patch, right-multiplies the filter matrix and the image patch
         vector.
    
    
    
    """
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    #FLAGS=tf.app.flags.FlAGS
    #tf.app.flags.DEFINE_integer("is_train",1,"指定程序是预测还是训练")
    #is_train=1 #is_train的值设为1,代表是训练
    is_train=0 #is_train的值设为0,代表是训练之后的预测
    def full_connected():
        mnist=input_data.read_data_sets("./data/mnist/input_data/",one_hot=True)
        #建立数据的占位符, x [None,784] y_true [None,10]
        with tf.variable_scope("data"):
            x=tf.placeholder(tf.float32,[None,784])
            y_true=tf.placeholder(tf.int32,[None,10])
        #2、建立一个全连接层的神经网络w [784,10] b [10]
        with tf.variable_scope("fc_model"):
            # 随机初始化权重和偏置
            weight=tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0,name='w'))
            bias=tf.Variable(tf.constant(0.0,shape=[10]))
            #预测None个样本的输出结果[None, 784]*[784,10]+[10]=[None,10]
            y_predict=tf.matmul(x,weight)+bias
        #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.1).minimize(loss)
        #5、计算准确率
        with tf.variable_scope("acc"):
            equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))
            #equal_list is None个样本  [1,0,1,1,0,0,0,1,1,0...]
            accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))
        # 收集变量,单个数字值的收集
        tf.summary.scalar("losses",loss)#收集损失
        tf.summary.scalar("acc",accuracy)#收集准确率
        # 高维度变量收集
        tf.summary.histogram("weightes",weight)
        tf.summary.histogram("biases",bias)
    
    
        # 定义一个初始化的变量op
        init_op=tf.global_variables_initializer()
        # 定义一个合并变量的op
        merged=tf.summary.merge_all()
    
        # 创建一个saver
        saver=tf.train.Saver()
    
    
        #开启会话去训练
        with tf.Session() as sess:
            #初始化变量
            sess.run(init_op)
    
            #建立events文件,然后写入
            filewriter=tf.summary.FileWriter("./tmp/summary/test/",graph=sess.graph)
    
            if is_train==1:
    
    
                #迭代步数去训练,更新参数进行预测
                for i in range(2000):
                    #取出样本的特征值和目标值
                    mnist_x,mnist_y=mnist.train.next_batch(50)
                    #运行train_op训练
                    sess.run(train_op,feed_dict={x:mnist_x,y_true:mnist_y})
    
    
    
                    # 写入每步训练的值
                    summary=sess.run(merged,feed_dict={x:mnist_x,y_true:mnist_y})
    
                    filewriter.add_summary(summary,i)
    
                    print("训练第%d步,准确率为:%f"%(i,sess.run(accuracy,feed_dict={x:mnist_x,y_true:mnist_y})))
    
                #保存模型
                saver.save(sess,"./tmp/ckpt/fc_model")
            else:
                # 加载模型,主要是加载训练之后保存在模型中的weight和bias
                saver.restore(sess,"./tmp/ckpt/fc_model")
                # 如果是0,做预测
                for i in range(100):
                    # 每次测试一张图片
                    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
    
    
    
    def weight_variables(shape):
        """
        自定义一个随机初始化权重的函数
        因为w是要迭代更新的,所以它要定义成一个tf的变量
        """
        w=tf.Variable(tf.random_normal(shape=shape,mean=0.0,stddev=1.0))
        return w
    
    
    def bias_variables(shape):
        """
        自定义一个随机初始化偏置的函数
        """
        b=tf.Variable(tf.constant(0.0,shape=shape))
        return b
    
    
    
    
    def model():
        """
        自定义一个卷积模型
        :return:
        """
        """
        1、准备数据的占位符
        """
        # 1、准备数据的占位符, x [None,784] y_true [None,10]
        with tf.variable_scope("data"):
            x = tf.placeholder(tf.float32, [None, 784])
            y_true = tf.placeholder(tf.int32, [None, 10])
        """
        2、卷积层1,卷积:核->5*5*1,strides=1,padding="SAME"
        激活,tf.nn.relu、池化
        """
        with tf.variable_scope("conv1"):
            #要有一些随机初始化的权重w和偏置bias
            # 随机初始化权重
            w_conv1=weight_variables([5,5,1,32])
    
            # 随机初始化bias,有多少个filter,就有多少个bias
            b_conv1=bias_variables([32])
    
            #因为tf.nn.conv2d()的第一个参数是:[batch, in_height, in_width, in_channels]
            #所以需要把输入数据改成张量 [None,784]->[None,28,28,1]
            x_reshape=tf.reshape(x,[-1,28,28,1]) #当不知道有多少样本的时候,此处不能填写None,要填写-1
    
    
            # 卷积:[None,28,28,1]->[None,28,28,32]
            conv1=tf.nn.conv2d(x_reshape,w_conv1,strides=[1,1,1,1],padding="SAME")+b_conv1
            x_relu1=tf.nn.relu(conv1)# 卷积后使之经过激活函数
    
            # 池化 pooling,2*2,strides=2 [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")
    
        """
        2、卷积层2,卷积核->5*5*32,filter=64,strides=1,padding="SAME"
        激活,tf.nn.relu、池化
        注意:每一张图像的通道数此时变成了32
        卷积核此时应是:5*5*32,因为一个人要观察32张图,共有64个人观察
        
        """
        with tf.variable_scope("conv2"):
            # 要有一些随机初始化的权重w和偏置bias
            # 随机初始化权重
            w_conv2 = weight_variables([5, 5, 32, 64])
    
            # 随机初始化bias,有多少个filter,就有多少个bias
            b_conv2 = bias_variables([64])
    
            # 卷积,激活,池化计算:[None,14,14,32]->[None,14,14,64]
            conv2 = tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2
            x_relu2 = tf.nn.relu(conv2)  # 卷积后使之经过激活函数
    
            # 池化 pooling,2*2,strides=2 [None,14,14,64]->[None,7,7,64]
            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("full_connected"):
    
            #随机初始化权重和偏置
            w_fc=weight_variables([7*7*64,10])
            b_fc=bias_variables([10])
    
            #进行矩阵运算得出每个样本的10个结果
            # 进行矩阵运算之前,修改形状:4维张量到2维矩阵
            # [None,7,7,64]->[None,7*7*64]
            x_pool2_reshape = tf.reshape(x_pool2, [-1, 7*7*64]) #-1代表不知道多少个样本,每个样本都是7*7*64个特征
            y_predict=tf.matmul(x_pool2_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.1).minimize(loss)
        #5、计算准确率
        with tf.variable_scope("acc"):
            equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))
            #equal_list is None个样本  [1,0,1,1,0,0,0,1,1,0...]
            accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))
    
    
        # 定义一个初始化的变量op
        init_op=tf.global_variables_initializer()
    
        #开启会话运行程序
        with tf.Session() as sess:
            sess.run(init_op) #进行变量初始化
    
            #循环去训练
    
    
            # 迭代步数去训练,更新参数进行预测
            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})))
    
    
    
    
    
    if __name__ == '__main__':
        conv_fc()

    运行结果:

    训练第0步,准确率为:0.200000
    训练第1步,准确率为:0.200000
    训练第2步,准确率为:0.160000
    训练第3步,准确率为:0.060000
    训练第4步,准确率为:0.120000
    训练第5步,准确率为:0.100000
    训练第6步,准确率为:0.200000
    训练第7步,准确率为:0.140000

    .

    .

    .

    训练第995步,准确率为:0.100000
    训练第996步,准确率为:0.100000
    训练第997步,准确率为:0.080000
    训练第998步,准确率为:0.140000
    训练第999步,准确率为:0.120000

    这样收敛过慢的结果,原因考虑学习率太大。

    """
    用单层神经网络实现手写数字识别
    
    
    def conv2d(input, filter, strides, padding, use_cudnn_on_gpu=True, data_format="NHWC", dilations=[1, 1, 1, 1], name=None):
      Computes a 2-D convolution given 4-D `input` and `filter` tensors.
        参数说明:
      Given an input tensor of shape `[batch, in_height, in_width, in_channels]`
      and a filter / kernel tensor of shape
      `[filter_height, filter_width, in_channels, out_channels]`, this op
      performs the following:
    
      1. Flattens the filter to a 2-D matrix with shape
         `[filter_height * filter_width * in_channels, output_channels]`.
      2. Extracts image patches from the input tensor to form a *virtual*
         tensor of shape `[batch, out_height, out_width,
         filter_height * filter_width * in_channels]`.
      3. For each patch, right-multiplies the filter matrix and the image patch
         vector.
    
    
    
    """
    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    #FLAGS=tf.app.flags.FlAGS
    #tf.app.flags.DEFINE_integer("is_train",1,"指定程序是预测还是训练")
    #is_train=1 #is_train的值设为1,代表是训练
    is_train=0 #is_train的值设为0,代表是训练之后的预测
    def full_connected():
        mnist=input_data.read_data_sets("./data/mnist/input_data/",one_hot=True)
        #建立数据的占位符, x [None,784] y_true [None,10]
        with tf.variable_scope("data"):
            x=tf.placeholder(tf.float32,[None,784])
            y_true=tf.placeholder(tf.int32,[None,10])
        #2、建立一个全连接层的神经网络w [784,10] b [10]
        with tf.variable_scope("fc_model"):
            # 随机初始化权重和偏置
            weight=tf.Variable(tf.random_normal([784,10],mean=0.0,stddev=1.0,name='w'))
            bias=tf.Variable(tf.constant(0.0,shape=[10]))
            #预测None个样本的输出结果[None, 784]*[784,10]+[10]=[None,10]
            y_predict=tf.matmul(x,weight)+bias
        #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.1).minimize(loss)
        #5、计算准确率
        with tf.variable_scope("acc"):
            equal_list=tf.equal(tf.argmax(y_true,1),tf.argmax(y_predict,1))
            #equal_list is None个样本  [1,0,1,1,0,0,0,1,1,0...]
            accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))
        # 收集变量,单个数字值的收集
        tf.summary.scalar("losses",loss)#收集损失
        tf.summary.scalar("acc",accuracy)#收集准确率
        # 高维度变量收集
        tf.summary.histogram("weightes",weight)
        tf.summary.histogram("biases",bias)
    
    
        # 定义一个初始化的变量op
        init_op=tf.global_variables_initializer()
        # 定义一个合并变量的op
        merged=tf.summary.merge_all()
    
        # 创建一个saver
        saver=tf.train.Saver()
    
    
        #开启会话去训练
        with tf.Session() as sess:
            #初始化变量
            sess.run(init_op)
    
            #建立events文件,然后写入
            filewriter=tf.summary.FileWriter("./tmp/summary/test/",graph=sess.graph)
    
            if is_train==1:
    
    
                #迭代步数去训练,更新参数进行预测
                for i in range(2000):
                    #取出样本的特征值和目标值
                    mnist_x,mnist_y=mnist.train.next_batch(50)
                    #运行train_op训练
                    sess.run(train_op,feed_dict={x:mnist_x,y_true:mnist_y})
    
    
    
                    # 写入每步训练的值
                    summary=sess.run(merged,feed_dict={x:mnist_x,y_true:mnist_y})
    
                    filewriter.add_summary(summary,i)
    
                    print("训练第%d步,准确率为:%f"%(i,sess.run(accuracy,feed_dict={x:mnist_x,y_true:mnist_y})))
    
                #保存模型
                saver.save(sess,"./tmp/ckpt/fc_model")
            else:
                # 加载模型,主要是加载训练之后保存在模型中的weight和bias
                saver.restore(sess,"./tmp/ckpt/fc_model")
                # 如果是0,做预测
                for i in range(100):
                    # 每次测试一张图片
                    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
    
    
    
    def weight_variables(shape):
        """
        自定义一个随机初始化权重的函数
        因为w是要迭代更新的,所以它要定义成一个tf的变量
        """
        w=tf.Variable(tf.random_normal(shape=shape,mean=0.0,stddev=1.0))
        return w
    
    
    def bias_variables(shape):
        """
        自定义一个随机初始化偏置的函数
        """
        b=tf.Variable(tf.constant(0.0,shape=shape))
        return b
    
    
    
    
    def model():
        """
        自定义一个卷积模型
        :return:
        """
        """
        1、准备数据的占位符
        """
        # 1、准备数据的占位符, x [None,784] y_true [None,10]
        with tf.variable_scope("data"):
            x = tf.placeholder(tf.float32, [None, 784])
            y_true = tf.placeholder(tf.int32, [None, 10])
        """
        2、卷积层1,卷积:核->5*5*1,strides=1,padding="SAME"
        激活,tf.nn.relu、池化
        """
        with tf.variable_scope("conv1"):
            #要有一些随机初始化的权重w和偏置bias
            # 随机初始化权重
            w_conv1=weight_variables([5,5,1,32])
    
            # 随机初始化bias,有多少个filter,就有多少个bias
            b_conv1=bias_variables([32])
    
            #因为tf.nn.conv2d()的第一个参数是:[batch, in_height, in_width, in_channels]
            #所以需要把输入数据改成张量 [None,784]->[None,28,28,1]
            x_reshape=tf.reshape(x,[-1,28,28,1]) #当不知道有多少样本的时候,此处不能填写None,要填写-1
    
    
            # 卷积:[None,28,28,1]->[None,28,28,32]
            conv1=tf.nn.conv2d(x_reshape,w_conv1,strides=[1,1,1,1],padding="SAME")+b_conv1
            x_relu1=tf.nn.relu(conv1)# 卷积后使之经过激活函数
    
            # 池化 pooling,2*2,strides=2 [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")
    
        """
        2、卷积层2,卷积核->5*5*32,filter=64,strides=1,padding="SAME"
        激活,tf.nn.relu、池化
        注意:每一张图像的通道数此时变成了32
        卷积核此时应是:5*5*32,因为一个人要观察32张图,共有64个人观察
        
        """
        with tf.variable_scope("conv2"):
            # 要有一些随机初始化的权重w和偏置bias
            # 随机初始化权重
            w_conv2 = weight_variables([5, 5, 32, 64])
    
            # 随机初始化bias,有多少个filter,就有多少个bias
            b_conv2 = bias_variables([64])
    
            # 卷积,激活,池化计算:[None,14,14,32]->[None,14,14,64]
            conv2 = tf.nn.conv2d(x_pool1, w_conv2, strides=[1, 1, 1, 1], padding="SAME") + b_conv2
            x_relu2 = tf.nn.relu(conv2)  # 卷积后使之经过激活函数
    
            # 池化 pooling,2*2,strides=2 [None,14,14,64]->[None,7,7,64]
            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("full_connected"):
    
            #随机初始化权重和偏置
            w_fc=weight_variables([7*7*64,10])
            b_fc=bias_variables([10])
    
            #进行矩阵运算得出每个样本的10个结果
            # 进行矩阵运算之前,修改形状:4维张量到2维矩阵
            # [None,7,7,64]->[None,7*7*64]
            x_pool2_reshape = tf.reshape(x_pool2, [-1, 7*7*64]) #-1代表不知道多少个样本,每个样本都是7*7*64个特征
            y_predict=tf.matmul(x_pool2_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 is None个样本  [1,0,1,1,0,0,0,1,1,0...]
            accuracy=tf.reduce_mean(tf.cast(equal_list,tf.float32))
    
    
        # 定义一个初始化的变量op
        init_op=tf.global_variables_initializer()
    
        #开启会话运行程序
        with tf.Session() as sess:
            sess.run(init_op) #进行变量初始化
    
            #循环去训练
    
    
            # 迭代步数去训练,更新参数进行预测
            for i in range(2000):
                # 取出样本的特征值和目标值
                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})))
    
    
    
    
    
    if __name__ == '__main__':
        conv_fc()

    学习率改成了0.0001,循环步数改成了2000次的运行结果是:

    训练第0步,准确率为:0.080000
    训练第1步,准确率为:0.160000
    训练第2步,准确率为:0.100000
    训练第3步,准确率为:0.180000
    训练第4步,准确率为:0.180000
    训练第5步,准确率为:0.120000

    .

    .

    .

    训练第1995步,准确率为:0.780000
    训练第1996步,准确率为:0.800000
    训练第1997步,准确率为:0.820000
    训练第1998步,准确率为:0.780000
    训练第1999步,准确率为:0.820000

    注解:

    • 准确率得到了明显的提升。
    • 最后的一个全连接层的激活函数是softmax.

    常见的网络结构:

     

     注解:

    • 杨乐昆写的。

     注解:

    • 参数数量6千万级别,一般的机器跑这个网络是跑不动的。

     注解:

    • 这个是googlenet网络。
    • inception是特定的网络结构。
    • 加入dropout是因为参数太多了,需要随机丢失一些,以减少计算量,最主要的目的还是降低过拟合。

     

    注解:

    •  tensorflow的库里面已经实现了googlenet的inception结构。
    • 如果图片像素数量比较多,可以考虑使用inception结构。
  • 相关阅读:
    跳表(SkipList)及ConcurrentSkipListMap源码解析
    动态主机配置协议DHCP
    电子邮件
    万维网WWW
    运维技巧(4):管理邮箱收发限制
    运维技巧(3):管理邮箱配额限制:重点是powershell命令操作
    运维技巧(2):创建邮箱方法详解
    运维技巧(1):如何通过邮件头和传输跟踪日志查看原始客户端IP
    管理客户端连接(6):客户端软件可以连接上邮箱
    配置Exchange 防病毒和反垃圾邮件(9)
  • 原文地址:https://www.cnblogs.com/yibeimingyue/p/14189905.html
Copyright © 2011-2022 走看看