精华内容
下载资源
问答
  • 该程序使用Python实现BP神经网络mnist手写数字识别。压缩包中给出训练好的权重以及偏移量的mat文件,在程序运行后输入mnist文件夹中图片路径的后缀就可以进行预测,如:4/mnist_test_4.png。压缩包给出训练集的mat...
  • 本资源为纯python实现mnist手写识别的代码,为作者本人所写,供深度学习初学者共同交流探讨,欢迎二次创作,网络为三层,可达到97%上准确率,模型可以选择多种训练方式,学习率,激活函数,损失函数等我都写了相关...
  • 文件包含两部分:一是mnist手写数字数据集,二是基于tersorflow实现的手写数字识别
  • 1、Mnist_cnn.py 该脚本文件 用TensorFlow框架 实现CNN卷积神经网络处理Mnist手写数字识别数据集,准确率达到99.21%; 2、Mnist_cnn_tensorboard.py 该脚本文件在Mnist_cnn.py的基础上实现可视化。
  • 本篇文章主要介绍了PyTorch CNN实战之MNIST手写数字识别示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 基于python3.7版本的tensorflow2.0实现mnist手写数字识别代码
  • 案例运用bp神经网络对手写数字mnist数据集进行分类,训练集精度达到99%,验证集精度达到96%以上。一个输入层一个隐藏层一个输出层,激活函数sigmoid,最后一个softmax,loss function为交叉熵损失函数。
  • 基于CNN的MNIST手写数字识别,最简单的卷积神经网络,附带源码和说明文档,代码有UI页面,可以实现对MNIST数字识别,也可以实现对手写录入数字识别
  • (1)认识MNIST数据集的数据格式,对MNIST数据集进行划分作为多层感知机的训练和测试数据; (2)利用python语言从零开始搭建多层感知机网络; (3) 通过调整参数提高多层感知机网络的准确度,并对实验结果进行评估...
  • 我们需要做的第⼀件事情是获取 MNIST 数据。如果你是⼀个 git ⽤⼾,那么你能够通过克隆这本书的代码仓库获得数据,实现我们的⽹络来分类数字 git clone ...
  • 主要介绍了Python利用逻辑回归模型解决MNIST手写数字识别问题,结合实例形式详细分析了Python MNIST手写识别问题原理及逻辑回归模型解决MNIST手写识别问题相关操作技巧,需要的朋友可以参考下
  • 需要下载MNIST数据集,将路径修改为本地MNIST数据集的地址。需要OpenCV与Tensorflow环境
  • MNIST手写数字识别问题的多层神经网络模型实践 按课程案例,动手完成编码实践。 自行设计一种神经网络模型,并尝试采用不同超参数,让模型的准确率达到97.5%。 提交要求: 1、你认为最优的一次带运行结果的源代码...
  • mnist.npz文件是手写数字的离线数据集,可以直接本地导入而且无需人工拆分为训练数据和测试数据,以及对应的数字标签,作为深度学习入门项目的数据集,可在python中打印出所有数字图像。
  • MNIST手写数字识别库及图片提取代码
  • python实实现现基基于于SVM手手写写数数字字识识别别功功能能 这篇文章主要为大家详细介绍了python实现基于SVM手写数字识别功能文中示例代码介绍的非常详细具有一 定的参考 值感兴趣的小伙伴们可以参考一下 本文实例...
  • mnist手写数字识别python3.8 tensorflow cpu 2.3.0 原文链接:https://geektutu.com/post/tensorflow-mnist-simplest.html 本文介绍了机器学习中的hello word ----------mnist ???? 原文采用: python 3.6 ...

    mnist手写数字识别–python3.8 tensorflow cpu 2.3.0

    原文链接:https://geektutu.com/post/tensorflow-mnist-simplest.html

    本文介绍了机器学习中的hello word ----------mnist 😗

    原文采用:

    python 3.6
    tensorflow 1.4
    

    本文采用:(截至2020年10月最高支持tensorflow版本,部分代码略作修改)

    python 3.8.5(64位)
    tensorflow cpu 2.3.0
    

    先上结果:
    loss:
    在这里插入图片描述accuracy:
    在这里插入图片描述

    神经网络:
    在这里插入图片描述
    在这里插入图片描述

    bias and weight distribution:
    在这里插入图片描述

    Histograms:
    在这里插入图片描述
    在这里插入图片描述

    代码:

    model.py

    import tensorflow as tf
    from tensorflow.python.framework.ops import disable_eager_execution
    disable_eager_execution()
    
    class Network:
        def __init__(self):
            self.learning_rate = 0.001
            self.global_step = tf.Variable(0, trainable=False, name="global_step")
    
            self.x = tf.compat.v1.placeholder(tf.float32, [None, 784], name="x")
            self.label = tf.compat.v1.placeholder(tf.float32, [None, 10], name="label")
    
            self.w = tf.Variable(tf.zeros([784, 10]), name="fc/weight")
            self.b = tf.Variable(tf.zeros([10]), name="fc/bias")
            self.y = tf.nn.softmax(tf.matmul(self.x, self.w) + self.b, name="y")
    
            self.loss = -tf.reduce_sum(self.label * tf.compat.v1.log(self.y + 1e-10))
            self.train = tf.compat.v1.train.GradientDescentOptimizer(self.learning_rate).minimize(
                self.loss, global_step=self.global_step)
    
            predict = tf.equal(tf.argmax(self.label, 1), tf.argmax(self.y, 1))
            self.accuracy = tf.reduce_mean(tf.cast(predict, "float"))
    
            # 创建 summary node
            # w, b 画直方图
            # loss, accuracy画标量图
            tf.compat.v1.summary.histogram('weight', self.w)
            tf.compat.v1.summary.histogram('bias', self.b)
            tf.compat.v1.summary.scalar('loss', self.loss)
            tf.compat.v1.summary.scalar('accuracy', self.accuracy)
    
    

    train.py

    import tensorflow as tf
    from tensorflow.examples.tutorials.mnist import input_data
    from model import Network
    from tensorflow.python.framework.ops import disable_eager_execution
    disable_eager_execution()
    
    
    CKPT_DIR = 'ckpt'
    
    
    class Train:
        def __init__(self):
            self.net = Network()
            self.sess = tf.compat.v1.Session()
            self.sess.run(tf.compat.v1.global_variables_initializer())
            self.data = input_data.read_data_sets('./data_set', one_hot=True)
    
        def train(self):
            batch_size = 64
            train_step = 20000
            step = 0
            save_interval = 1000
            saver = tf.compat.v1.train.Saver(max_to_keep=5)
    
            # merge所有的summary node
            merged_summary_op = tf.compat.v1.summary.merge_all()
            # 可视化存储目录为当前文件夹下的 log
            merged_writer = tf.compat.v1.summary.FileWriter("./log", self.sess.graph)
    
            ckpt = tf.train.get_checkpoint_state(CKPT_DIR)
            if ckpt and ckpt.model_checkpoint_path:
                saver.restore(self.sess, ckpt.model_checkpoint_path)
                # 读取网络中的global_step的值,即当前已经训练的次数
                step = self.sess.run(self.net.global_step)
                print('Continue from')
                print('        -> Minibatch update : ', step)
    
            while step < train_step:
                x, label = self.data.train.next_batch(batch_size)
                _, loss, merged_summary = self.sess.run(
                    [self.net.train, self.net.loss, merged_summary_op],
                    feed_dict={self.net.x: x, self.net.label: label}
                )
                step = self.sess.run(self.net.global_step)
    
                if step % 100 == 0:
                    merged_writer.add_summary(merged_summary, step)
    
                if step % save_interval == 0:
                    saver.save(self.sess, CKPT_DIR + '/model', global_step=step)
                    print('%s/model-%d saved' % (CKPT_DIR, step))
    
        def calculate_accuracy(self):
            test_x = self.data.test.images
            test_label = self.data.test.labels
            accuracy = self.sess.run(self.net.accuracy,
                                     feed_dict={self.net.x: test_x, self.net.label: test_label})
            print("准确率: %.2f,共测试了%d张图片 " % (accuracy, len(test_label)))
    
    
    if __name__ == "__main__":
        app = Train()
        app.train()
        app.calculate_accuracy()
    # tensorboard --logdir=./log
    

    predict.py

    在这里插import tensorflow as tf
    import numpy as np
    from PIL import Image
    from tensorflow.python.framework.ops import disable_eager_execution
    disable_eager_execution()
    from model import Network
    
    
    # python 3.6
    # tensorflow 1.4
    # pillow(PIL) 4.3.0
    # 使用tensorflow的模型来预测手写数字
    # 输入是28 * 28像素的图片,输出是个具体的数字
    
    
    CKPT_DIR = 'ckpt'
    
    
    class Predict:
        def __init__(self):
            self.net = Network()
            self.sess = tf.compat.v1.Session()
            self.sess.run(tf.compat.v1.global_variables_initializer())
    
            # 加载模型到sess中
            self.restore()
    
        def restore(self):
            saver = tf.compat.v1.train.Saver()
            ckpt = tf.compat.v1.train.get_checkpoint_state(CKPT_DIR)
            if ckpt and ckpt.model_checkpoint_path:
                saver.restore(self.sess, ckpt.model_checkpoint_path)
            else:
                raise FileNotFoundError("未保存任何模型")
    
        def predict(self, image_path):
            # 读图片并转为黑白的
            img = Image.open(image_path).convert('L')
            flatten_img = np.reshape(img, 784)
            x = np.array([1 - flatten_img])
            y = self.sess.run(self.net.y, feed_dict={self.net.x: x})
    
            # 因为x只传入了一张图片,取y[0]即可
            # np.argmax()取得独热编码最大值的下标,即代表的数字
            print(image_path)
            print('        -> Predict digit', np.argmax(y[0]))
    
    
    if __name__ == "__main__":
        app = Predict()
        app.predict('./test_images/0.png')
        app.predict('./test_images/1.png')
        app.predict('./test_images/4.png')
    入代码片
    

    测试图片:
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    文件设置:
    在这里插入图片描述
    data_set 为训练的MNIST库,运行代码自动生成
    ckpt为保存模型,运行代码自动生成
    log为可视化路径,运行代码自动生成
    test_images为识别图片的地址

    在project路径运行tensorboard:

    tensorboard --logdir=./log

    浏览器访问localhost得到可视化结果,端口6006(具体见cmd运行结果):http://localhost:6006/

    在这里插入图片描述
    pycharm中显示结果:

    train.py:

    在这里插入图片描述

    predict.py:
    在这里插入图片描述

    展开全文
  • FCN实现手写数字数据集MNIST识别,代码为自己翻写,包含MNIST数据集,代码与大量注释,及24页原创报告
  • python实现mnist手写数字识别

    千次阅读 2020-07-17 16:51:08
    看了《python神经网络编程》,跟着书上敲了一下mnist手写数字的代码,对神经网络有了初步的了解。 此项目为三层神经网络识别,激活函数采用sigmoid函数,数据集为mnist手写数字集,训练集包括60000个样本,测试集...

    看了《python神经网络编程》,跟着书上敲了一下mnist手写数字的代码,对神经网络有了初步的了解。

    此项目为三层神经网络识别,激活函数采用sigmoid函数,数据集为mnist手写数字集,训练集包括60000个样本,测试集10000个样本。

    第一部分,创建神将网络模型

    import numpy
    import matplotlib.pyplot
    #%matplotlib inline用在Jupyter notebook中(代替plt.show()),使用%matplotlib命令可以将matplotlib的图表直接嵌入到Notebook之中
    %matplotlib inline 
    #sigmoid函数,在这组函数中,S函数称为expit()
    import scipy.special  
     
    class neuralNetwork:
        def __init__(self,inputnodes,hiddennodes,outputnodes,learningrate):
            self.inodes = inputnodes  #输入节点
            self.hnodes = hiddennodes #隐藏节点
            self.onodes = outputnodes #输出节点
            self.lr = learningrate    #学习率
            
    #         初始化参数
            self.wih=(numpy.random.rand(self.hnodes,self.inodes )-0.5)
            self.woh=(numpy.random.rand(self.onodes,self.hnodes)-0.5)
            
    #        激活函数为sigmoid函数,使用lambda创建函数(匿名函数),方便快捷
            self.activation_function = lambda x:scipy.special.expit(x)
            
            pass
        
    #     训练d代码
        def train(self,input_list,target_list):
    #         将输入转换为numpy数组,dmin指定生成数组的最小维度
            inputs = numpy.array(input_list,ndmin=2).T
            targets = numpy.array(target_list,ndmin=2).T
    #     计算隐藏层
            hidden_inputs = numpy.dot(self.wih,inputs)
    #     调用sigmoid激活函数
            hidden_outputs = self.activation_function(hidden_inputs)
    #      输出层
            final_inputs=numpy.dot(self.woh,hidden_outputs)
            final_outputs = self.activation_function(final_inputs)
            
    #         计算误差
            error = targets-final_outputs
    #     隐藏层误差节点反向传播的误差
            hidden_error = numpy.dot(self.woh.T,error) 
        
    #       优化权重, 正常对应元素相乘,·乘是矩阵点击
    #       transpose()简单来说,就相当于数学中的转置,在矩阵中,转置就是把行与列相互调换位置;
            self.woh += self.lr * numpy.dot((error * final_outputs * (1.0-final_outputs)),numpy.transpose(hidden_outputs)) 
            self.wih += self.lr * numpy.dot((hidden_error*hidden_outputs*(1.0-hidden_outputs)),numpy.transpose(inputs)) 
            
            pass
          
    #     查询函数
        def query(self,inputs):
    
            inputs = numpy.array(inputs,ndmin=2).T
            
            hidden_inputs = numpy.dot(self.wih,inputs)
            hidden_outputs = self.activation_function(hidden_inputs)
            final_inputs=numpy.dot(self.woh,hidden_outputs)
            final_outputs = self.activation_function(final_inputs)
            
            return final_outputs
            pass

    第二部分 训练网络

    inputnodes=28*28
    hiddennodes=100
    outputnodes=10
    learningrate=0.1
    # 创造神经网络实例
    n = neuralNetwork(inputnodes,hiddennodes,outputnodes,learningrate)
    
    # 获取mnist_train数据集
    training_date_file = open("mnist_train.csv","r")
    training_date_list = training_date_file.readlines()
    training_date_file.close()
    
    a=0
    for record in training_date_list:
        
    # 用“,”分割长的字符串值,拆分为单个值
        all_values = record.split(',')
    # 第一个值为标签,忽略, 将剩余784个值转换为28*28数组
    # numpy.asfarray()将文本字符串转换为实数并创建这些数字的数组,
    # 因为文件是用文本读取的,每一条记录仍然是文本,用“,”分割得到的仍然是文本
    # all_values[1:]/255.0*0.99)+0.01 是将输入颜色从0-255缩小到0.01-1.00,最小值为0.01是避免先前观察到的0值输入最终会人为地造成权重更新失败
        inputs =( numpy.asfarray(all_values[1:])/255.0*0.99)+0.01
        
    #     将训练目标标签从字符串形式转换为整数形式,正确元素设置为0.99 标签“0”转换为整数0
        targets = numpy.zeros(outputnodes)+0.01
        targets[int(all_values[0])]=0.99
        n.train(inputs,targets)
        
    #     a用来计数,查看训练进度
        a=a+1
        if(a%10000==0):
            print(a)
            
        pass
    

    网络训练结束

    第三部分 网络测试

    # 测试网络
    
    test_date_file = open("mnist_test.csv","r")
    test_date_list = test_date_file.readlines()
    test_date_file.close()
    
    # 创建空列表,用作积分卡,在测试每条记录之后都会进行更新
    scorecard=[]
    b=0
    for record in test_date_list:
        all_values = record.split(',')
        inputs = (numpy.asfarray(all_values[1:])/255.0*0.99)+0.01
    #     目标标签
        correct_label=int(all_values[0])
        outputs = n.query(inputs)
    #     测试所得标签
        label=numpy.argmax(outputs)
        
    #   如果相等,在记分卡追加1,不相等0
        if(label==correct_label):
            scorecard.append(1)
        else:
            scorecard.append(0)
            
    #    b用来计数,查看测试进度   
        b= b+1
        if(b%1000==0):
            print(b)
            
        pass
    
    #输出正确率
    scorecard_array=numpy.asarray(scorecard)
    print("Accuracy= ",scorecard_array.sum()/scorecard_array.size)
    

    结果:

    模型改进:

    1.调整学习率,变大,变小

    • 当前学习率为0.1,准确率为0.9477
    • 调整学习率为0.2,学习率有所提升.

    • 调整为0.05,学习率有所下降

    2.多次运行,训练一次称为一个世代

    3.改变网络形状,改变隐藏节点的数量等

    展开全文
  • MNIST手写数字识别功能描述Python源代码运行结果 功能描述 基于手写数字的数据集,实现神经网络的训练和推理。 Python源代码 #!/usr/bin/env python # coding: utf-8 # In[1]: import numpy import scipy.special #...

    MNIST手写数字识别

    功能描述

    基于手写数字的数据集,实现神经网络的训练和推理。
    http://pjreddie.com/projects/mnist-in-csv/
    http://www.pjreddie.com/media/files/mnist_train.csv
    http://www.pjreddie.com/media/files/mnist_test.csv

    Python源代码

    #!/usr/bin/env python
    # coding: utf-8
    
    # In[1]:
    import numpy
    import scipy.special # 这个库包含sigmoid函数,叫做expit()
    import matplotlib.pyplot # 导入绘图库
    
    
    # In[2]:
    #创建神经网络类,至少有3个函数 :
    #初始化函数--设定输入层节点、隐藏层节点和输出层节点的数量,学习率设定
    #训练      --学习给定训练集样本后,优化权重
    #查询      --给定输入,从输出节点给出答案
    
    
    # neural network class definition
    class neuralNetwork :
        # initialise the neural network
        def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate) :
            # set number of nodes in each input, hidden, output layer
                self.inodes = inputnodes
                self.hnodes = hiddennodes
                self.onodes = outputnodes
    
                # learning rate
                self.lr = learningrate
    
                # link weight matrices, wih and who
                # weight inside the arrays are w_i_j, where link is from node i to node j in the next layer
                # w11 w21
                # w12 w22 etc
                # 初始化权重值为-0.5 ~ 0.5的随机数,注意行和列不要弄反了
                self.wih = (numpy.random.rand(self.hnodes, self.inodes) - 0.5)
                self.who = (numpy.random.rand(self.onodes, self.hnodes) - 0.5)
    
                # 可选操作:使用正态分布的随机数初始化权重,中心为0.0
                #self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5),(self.hnodes, self.inodes))
                #self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5),(self.onodes, self.hnodes))
    
                # 定义激活函数为sigmoid: 这个函数接收x作为输入,expit(x)为输出
                self.activation_function = lambda x:scipy.special.expit(x)
                pass
        
        # train the neural network
        def train(self, inputs_list, targets_list):
                # convert inputs list to 2d array
                inputs = numpy.array(inputs_list, ndmin=2).T
                targets = numpy.array(targets_list, ndmin=2).T
    
                # calculate signals into hidden layer
                hidden_inputs = numpy.dot(self.wih, inputs)
                # calculate the signals emerging from hidden layer
                hidden_outputs = self.activation_function(hidden_inputs)
    
                # calculate signals into final output layer
                final_inputs = numpy.dot(self.who, hidden_outputs)
                # calculate the signals emerging from final output layer
                final_outputs = self.activation_function(final_inputs)
    
                # output layer error is the (target - actual)
                output_errors = targets - final_outputs
                # hidden layer error is the output_errors, split by weights, recombined at hidden nodes
                # 重点!!反向传播误差
                hidden_errors = numpy.dot(self.who.T, output_errors)
    
                #更新权重:w=w+mu*e(n)*sigmoid(final_inputs)的导数*vector_u;
                # update the weights for the links between the hidden and output layers
                # 其中:*表示对应元素的乘法,dot表示矩阵的点积
                self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)), numpy.transpose(hidden_outputs))
    
                # update the weights for the links between the input and hidden layers
                self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose(inputs))
                pass
    
        # query the neural network
        def query(self, inputs_list) :
                # 转换inputs_list为二维数组,以便于计算
                inputs = numpy.array(inputs_list, ndmin=2).T
                # 矩阵相乘
                hidden_inputs = numpy.dot(self.wih, inputs)
                # 激活
                hidden_outputs = self.activation_function(hidden_inputs)
    
                # 矩阵相乘
                final_inputs = numpy.dot(self.who, hidden_outputs)
                # 激活
                final_outputs = self.activation_function(final_inputs)
    
                return final_outputs
    
    
    # In[3]:
    # number of input, hidden and output nodes
    input_nodes = 784 # 28*28=784
    hidden_nodes = 100
    output_nodes = 10
    
    # learning rate is xxx
    learning_rate = 0.3
    
    # create instance of neural network
    n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
    
    
    # In[4]:
    # 读取训练集文件数据(首先要将数据上传到网站上file-open-upload)
    training_data_file = open("mnist_train_500.csv",'r')
    training_data_list = training_data_file.readlines()# 将所有数据都读入list,也可以每次读一行
    training_data_file.close()
    
    
    # In[5]:
    # 开始训练神经网络
    for record in training_data_list:
            all_values = record.split(',')
            # image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
            # matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')
    
            # 将数据转换为0.01~1.00范围内
            # 选择0.01作为最低点为了避免先前观察到的0值输入会人为地造成权重更新失败
            # 输入值可以是1.0,但是输出值不可以
            inputs = (numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01
    
            # 构建目标输出,使用0.01和0.99分别代替0和1作为目标,防止饱和网络(sigmoid不能输出1和0)
            targets = numpy.zeros(output_nodes) + 0.01 # 目标输出是10个数据
            targets[int(all_values[0])] = 0.99
            n.train(inputs, targets)
            pass
    
    
    # In[6]:
    # 测试神经网络
    test_data_file = open("mnist_test.csv",'r')
    test_data_list = test_data_file.readlines()# 将所有数据都读入list,也可以每次读一行
    test_data_file.close()
    
    all_values = test_data_list[0].split(',')
    print(all_values[0])
    
    image_array = numpy.asfarray(all_values[1:]).reshape((28,28))
    matplotlib.pyplot.imshow(image_array, cmap='Greys', interpolation='None')
    
    n.query((numpy.asfarray(all_values[1:]) / 255.0 * 0.99) + 0.01)
    
    

    运行结果

    通过修改test_data_list数组的编号,可以选择不同的数据进行测试。
    输出一个array,其中最大的数的编号就是得到的数字结果。
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 主要介绍了Python tensorflow实现mnist手写数字识别,结合实例形式分析了基于tensorflow模块使用非卷积与卷积算法实现手写数字识别的具体操作技巧,需要的朋友可以参考下
  • MNIST手写字 Matlab程序,包含BP和CNN程序。不依赖任何库,包含MNIST数据,BP网络可达到98.3%的识别率,CNN可达到99%的识别率。CNN比较耗时,关于CNN的程序介绍:...
  • 西电网信院人工智能课程实验报告,利用遗传算法解决 TSP 问题及可视化程序,基于神经网络的 MNIST 手写数字识别python实现
  • python的numpy实现mnist手写数字识别

    千次阅读 2019-11-22 18:44:30
    用numpy实现mnist手写数字识别(不使用深度学习框架);一万张测试集,以识别正确图片所占的比例作为准确率,准确率达到93%

    完整代码的文章底部(Optimization_mnist.py和lr_utils.py),原理和公式部分可以看前面文章,转载文章请附上本文链接

    学完前面(1到6)文章就完成了吴恩达deeplearning ai 课程前面2门课程的内容了,可以写出下面的代码,可以去参加一些比赛,这里推荐一个kaggle上面的一个mnist手写数字识别的知识竞赛,在没有使用深度学习框架情况下他的评分达到了0.94914,代码我直接给出来,就不解释了。

    kaggle比赛链接
    这下面是我的评分,代码再文章底部,我就不解释了,训练集需要去kaggle平台下载,这个比赛是一直开放的(lr_mnist.py和test_mnist.py)
    在这里插入图片描述

    内容分为三部分:

    • 1.数据准备和处理
    • 2.训练过程
    • 3.测试过程

    一.数据准备和处理:

    我数据集是用tensorflow2.0获取mnist上的7万张手写数字图片(也可以用其他方式获取,不用tensorflow,我是为了方便就用tensorflow获取了),需要先安装tensorflow2.0版本。安装教程可以看前面文章:在win10上安装tensorflow,并且配置编译器

    这部分代码:

    import  tensorflow as tf
    from    tensorflow.keras import datasets
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    def load_dataset():
        (x, y), (x_test, y_test) = datasets.mnist.load_data()#使用tensorflow获取mnist手写数字图片训练集和测试集
        #对图片进行降维,训练集合x有6万张图片,测试集x_test有一万张图片,都是28*28,通道数为1(也就是黑白色),这里就是一个三维元组了
        #标签y是0到9的数字,表示图片是数字几,可以输出看一下。由于x是元组类型,无法用shape(),只能用shape【】
        y = y.reshape(1,-1)
        y_test = y_test.reshape(1, -1)
        print("训练集维度:",x.shape[0],x.shape[1],x.shape[2])#打印训练集维度
        print("测试集维度:",x_test.shape[0],x_test.shape[1],x_test.shape[2])#打印测试集维度
    
        #用独热码处理标签,调用pandas库中Series和get_dummier函数
        y = np.squeeze(y)#使得标签是1维的
        y = pd.Series(y)
        y = pd.get_dummies(y)
        #print(y)这个可以查看矩阵是如何的,y是60000万行,10列
        y = np.array(y).T#y变成10行,60000列,60000列是样本个数
    
        y_test = np.squeeze(y_test)  # 使得标签是1维的
        y_test = pd.Series(y_test)
        y_test = pd.get_dummies(y_test)
        # print(y_test)这个可以查看矩阵是如何的,y_test是10000万行,10列
        y_test = np.array(y_test).T  # y_test变成10行,10000列,10000列是样本个数
    
        train_set_x_orig, train_set_y, test_set_x_orig, test_set_y = x,y,x_test,y_test
        return train_set_x_orig, train_set_y, test_set_x_orig, test_set_y
    load_dataset()
    '''
    train_set_x_orig, train_set_y, test_set_x_orig, test_set_y=load_dataset()
    #可以打印图片看一下,比如训练集中第100张的图片
    plt.imshow(train_set_x_orig[99])  # 打印的图片
    print(train_set_y[0][99])  # 输出图片对应标签
    plt.show()  # 展示需要打印的图片
    '''
    

    获取数据集很简单只需要一行代码:(x, y), (x_test, y_test) = datasets.mnist.load_data()
    由于标签y和y_test是一维数组,我们要做的是把标签化为softmax分类器的类型,需要用独热码(one-hot)处理。
    在这里插入图片描述
    在这里插入图片描述

    用pandas内的函数实现(具体看注释):

    y = pd.Series(y)
    y = pd.get_dummies(y)
    

    不清楚的地方可以print打印看看,我们打印一下训练集第99张图片:
    在这里插入图片描述
    对于图片降维的处理我们在主函数里面进行。

    主函数代码:
    if __name__ == "__main__":
        L = 10#神经网络层数
        dim = 20#隐藏层节点个数
        learning_rate = 0.05#学习率
        loss= []#损失函数
        lambd = 0.01 # L2正则化参数
        beta = 0.9#β值;1/(1-β)表示平均前多少轮的指数加权平均数
        decay_rate = 0.0009#学习率衰减率
        mini_batch = 300#一次的训练量,60000万张图片,要带入200次,全部训练一遍称为一代
        sigma2, mu = 0, 0  # 用于决定将batch正则化拟合进神经网络的均值和方差
        train_set_x_orig, train_set_y, test_set_x_orig, test_set_y = load_dataset()
        train_set_x = train_set_x_orig.reshape((train_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        test_set_x = test_set_x_orig.reshape((test_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        print("训练集降维后的维度: " + str(train_set_x.shape))
        print("训练集_标签的维数 : " + str(train_set_y.shape))
        print("测试集降维后的维度: " + str(test_set_x.shape))
        print("测试集_标签的维数 : " + str(test_set_y.shape))
        print()
        w,b,Vdw,Vdb,Sdw,Sdb = ward(L,train_set_x.shape[1],train_set_x.shape[0],dim)#vdw表示momentum,Sdw表示RMSprop
        for i in range(0,200):
            Sigma2, Mu,J_average = 0,0,0#用于决定将batch正则化拟合进神经网络的均值和方差
            for j in range(0,(train_set_x.shape[1]//mini_batch)):
                #w,b,J,Vdw,Vdb = back_momentum(w,b,train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita,Vdw,Vdb)
                #w,b,J,Vdw,Vdb = back_RMSprop(w, b, train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita, Sdw, Sdb)
                w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu = back_Adam(w,b,((train_set_x.T)[j*mini_batch:(j+1)*mini_batch]).T,((train_set_y.T)[j*mini_batch:(j+1)*mini_batch]).T,learning_rate,mini_batch,L,lambd,beta,Vdw,Vdb, Sdw, Sdb)
                #如果有多个mini_batch应该在此处对返回的sigam2和mu使用指数加权平均数,也是滑动平均数
                Sigma2 = np.multiply(beta,Sigma2) + np.multiply((1-beta),sigma2)
                Mu = np.multiply(beta,Mu) + np.multiply((1-beta),mu)
                J_average = np.multiply(beta,J) + np.multiply((1-beta),J)
            learning_rate = learning_rate * (1 / (1 + i*decay_rate) )#使用学习率衰减
            if i % 10 == 0:
                print("loss:",J_average)
                loss.append(J_average)
        plt.plot(loss)#打印损失函数
        plt.show()
    
        text(test_set_x,test_set_y,w,b,L,test_set_x.shape[1],lambd,Sigma2,Mu)
    

    训练之前我们需要初始化参数w和b,使用ward函数: 顺便把Adam梯度下降法的表示式也一起初始化了,w其实不是三维数组,可以理解为是把多个矩阵放进一个列表里面,当然也可以放字典里面。训练集X是784行,60000列的矩阵,每一列表示的是特征值,60000表示样本个数,所以w1维度:(第一层节点个数,一个样本特征个数784);由于标签是0到9,有10种情况,所以wL维度:(10,L-1层节点个数),节点也就是隐藏单元。

    def ward(L,n,m,dim):#对参数进行初始化
        np.random.seed(1)
        w = []
        b = []
        Vdw, Vdb, Sdw, Sdb = [],[],[],[]#优化算法的值
        for i in range(0, L):
            if i != 0 and i != L - 1:
                #p = np.random.randn(dim, dim) *0.001
                p = np.random.randn(dim, dim) * np.sqrt(2 / dim)
            elif i == 0:
                #p = np.random.randn(dim, m) * 0.001
                p = np.random.randn(dim, m) * np.sqrt(2 / m)
            else:
                #p = np.random.randn(1, dim) * 0.001
                p = np.random.randn(10, dim) * np.sqrt(2 / dim)
            w.append(p)
            b.append(1)
            Vdw.append(0)#初始化为0
            Vdb.append(0)
            Sdw.append(0)
            Sdb.append(0)
    
        return w, b,Vdw,Vdb,Sdw,Sdb
    

    三.训练过程:

    1.我们先看一下前向传播过程:使用的是forward_back函数,前向传播中我使用了归一化输入(σ^2 和μ要缓存下来,用于测试时候的归一化输入;γ和β我是设置成刚好可以和z_norm约了的特殊情况,也就是数据方差为1,平均值为0的情况,你也可以设置成其他情况,还可以对γ和β进行梯度下降,不断跟新γ和β),我还使用了L2正则化,我是将神经网络层数设置为10层(你也可以用dropout正则化)。注意此时的成本函数J要重新定义我们前面的文章中得到的最后一层输出aL(也就是y^)是一个一行多列矩阵,这里是10分类情况,得到的aL是10行60000列的矩阵,具体看代码,使用softmax分类器。不理解地方可以调试看看。
    def forward_back(w,b,a,Y,L,m,lambd):#用于训练的归一化前向传播
        z = []
        add = 0
        sigma2,mu = [],[]
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            #归一化输入z
            muL = (1/m)*np.sum(zl,axis=1,keepdims=True)
            sigmaL = (1/m)*np.sum(np.power(zl-muL,2),axis=1,keepdims=True)
            z_norm = (zl-muL)/(np.sqrt(sigmaL+0.00000001))
            gamma,beta_1 = 1*np.sqrt(sigmaL+0.00000001),muL+0#此时z的方差为1,均值为0
            zl = np.multiply(z_norm,gamma) + beta_1
            mu.append(muL)
            sigma2.append(sigmaL)
            #可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            #因为z = γ*z_norm+β可以看成线性函数,类似于z = wx+b,也可以对γ和β进行梯度下降更新。
    
            add += np.sum((lambd / (2 * m)) * np.dot(w[i], w[i].T))#L2正则化项
            z.append(zl)
            a = relu(zl)
    
        #使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t,axis = 0,keepdims=True)#axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t,ti)#矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        #损失函数也应该重新定义
        J = (-1/m)*np.sum(Y*np.log(a))+ add #注意Y*nu.log(a)计算得到是多行的矩阵,但只有一行是非0行,我们之前定义的损失函数相当于这个特殊情况
    
        # a = sigmoid(zl)
        #J = (-1/m)*np.sum(1 * Y * np.log(a) + (1 - Y) * np.log(1 - a)) + add  # 损失函数
        return z, a, J,sigma2,mu
    
    2.前向传播完成了,我们来看看反向传(播使用的是backward函数和back_Adam函数):反向求导运算,缓存dw和db,然后对w和b进行更新,我使用的是Adam优化器。
    不过有3个细节部分我没有完成:
    • 反向传播也可以用递归写,这样好像会方便,我这样写代码可能比较丑,…嗯就是比较丑
    • momentum优化器和RMSprop优化器里面一些参数我还没加进去,不能直接调用,你需要稍微改改,我比较懒不想改了
    • 还有一个就是Adam通常都是要用偏差修正,虽然说不用好像没多大影响,但我用上就数值就变得很大,比较奇怪;所以我没用,注释了,没用的话多轮训练后是没有什么影响的,也没关系。
    我们训练过程中缓存了σ^2和μ,这个在使用mini_batch时候,需要进行用指数加权平均数重新计算σ ^2和μ,如果mini_batch为整个训练集时候,就不要用指数加权平均数计算了,直接用这个σ ^2和μ就好了。我们还可以使用学习率衰减率,对学习率进行跟新。
    注意:设置mini_batch很重要,我是设置成300,如果你设置成整个训练集的话,也就是60000,不仅是对cpu的考验,训练效果也是非常差。我设置成60000后准确率只有9.8%,和没训练一个样,改成300后准确率就达到了93%,当然你也可以使用其他大小,听说2的指数次方运算速度比较好。
    def backward(w,b,X,Y,m,L,lambd):#反向传播
        z,a,J,sigma2,mu = forward_back(w,b,X,Y,L,m,lambd)
        dw,db = [],[]
        for i in range(L - 1, 0, -1):
            if i == L - 1:
                dz = a - Y
            else:
                dz = np.dot(w[i + 1].T, dz) * relu_1(z[i])
            Dw = 1 / m * (np.dot(dz, relu(z[i - 1]).T)) + (lambd / m) * w[i]
            Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
            dw.append(Dw)
            db.append(Db)
    
        dz = np.dot(w[1].T, dz) * relu_1(z[0])
        Dw = 1 / m * np.dot(dz, X.T) + (lambd / m) * w[0]
        Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
        dw.append(Dw)
        db.append(Db)
        return dw, db, J,sigma2,mu
    
    def back_Adam(w,b,X,Y,learning,m,L,lambd,beta,Vdw,Vdb,Sdw,Sdb):#使用Adam梯度下降的反向传播
        dw, db, J ,sigma2,mu= backward(w,b,X,Y,m,L,lambd)
        # 通常使用偏差修正
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Vdw[i] = beta * Vdw[i] + (1 - beta) * dw[L - i - 1]
            Vdb[i] = beta * Vdb[i] + (1 - beta) * db[L - i - 1]
            Sdw[i] = beta * Sdw[i] + (1 - beta) * np.power(dw[L-i-1],2)
            Sdb[i] = beta * Sdb[i] + (1 - beta) * np.power(db[L-i-1],2)
            '''
            Vdw[i] /= 1 - np.power(beta, t)#t表示代数(所有mini_batch训练一次称为一代)
            Vdb[i] /= 1 - np.power(beta, t)
            Sdw[i] /= 1 - np.power(beta, t)
            Sdb[i] /= 1 - np.power(beta, t)
            '''
            w[i] = w[i] - learning * Vdw[i] / (np.power(Sdw[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
            b[i] = b[i] - learning * Vdb[i] / (np.power(Sdb[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
    
        return w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu
    

    三.测试过程:使用text函数,调用的前向传播函数是forward_test函数

    def forward_test(w, b, a, Y, L, m, lambd,sigma2,mu):  # 用于测试的归一化前向传播
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            # 归一化输入z
            z_norm = (zl - mu[i]) / (np.sqrt(sigma2[i] + 0.00000001))
            gamma, beta_1 = 1 * np.sqrt(sigma2[i] + 0.00000001), mu[i] + 0  # 此时z的方差为1,均值为0
            zl = np.multiply(z_norm, gamma) + beta_1
            # 可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            a = relu(zl)
        # 使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t, axis=0, keepdims=True)  # axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t, ti)  # 矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        # a = sigmoid(zl)
        return a
    

    这个前向传播中归一化使用的σ^2和μ是训练过程中缓存的,其他基本和训练的前向传播一个样。

    def text(x,y,w,b,L,m,lambd,sigma2, mu):#查看测试集准确率
        a = forward_test(w, b, x, y, L, m,lambd,sigma2,mu)
        #得到的a是一个10行,10000列的矩阵,里面数表示概率
        a = a.T#先将a转置
        for i in range(x.shape[1]):
            a[i] = np.where(a[i].max() == a[i], 1, 0)#最大数位置改为存1,不是最大数改为存0,这样就处理好y^了
        a = a.T  # 将a转回去
        lop_1 = np.sum(np.abs(y-a),axis = 0,keepdims=True)/2#这个lop_1中存的是1和0,1表示预测错误,0表示正确
        lop_2 = 1-np.sum(lop_1,axis=1,keepdims=True)/10000#表示正确所占比例,也就是准确率
        lop_2=np.squeeze(lop_2)
    
        print("测试集准确性:{0}%".format(lop_2*100))
        return 0
    
    这个标签处理我用的方式你可能觉得有点怪,嗯…希望你可以理解它。

    我们用训练好的w和b来计算测试集的图片输入数据,得到一个y^,y ^里面是概率,之和为1。
    y^是的维度是:(10,10000),我们将它转置后用np.where()把每一行的数最大的改为1,其他改为0,然后再转置回来。这样aL(也就是y ^)和Y,我们选其第一列来看(也就是第一个样本),aL-Y取绝对值后,由于aL和y ^每一列中只有一个1,其他全部为0,aL如果和Y相等那么相减后这一列应该全为0,否则这一列里面有2个1,经过lop_1 = np.sum(np.abs(y-a),axis = 0,keepdims=True)/2lop_2 = 1-np.sum(lop_1,axis=1,keepdims=True)/10000运算后lop_2就是识别正确的图片所占的比例,将这个作为准确率,当然你也可以自己拍一张照片,替代测试集,将你照片(必须为黑白照,因为训练集就是黑白照,也就是单通道的)数据输入使用训练好的w和b计算,他输出的y^就是你识别的结果(y ^你可能也需要简单的处理一下,我就不写这部分代码了,大家加油)。

    下面这张图片是我的训练结果:训练200轮后,准确率93%,你可以多调试一下,参数多调调,应该会有百分之95%以上准确率在这里插入图片描述

    在这里插入图片描述

    完整代码:

    lr_utils.py:

    import  tensorflow as tf
    from    tensorflow.keras import datasets
    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    def load_dataset():
        (x, y), (x_test, y_test) = datasets.mnist.load_data()#使用tensorflow获取mnist手写数字图片训练集和测试集
        #对图片进行降维,训练集合x有6万张图片,测试集x_test有一万张图片,都是28*28,通道数为1(也就是黑白色),这里就是一个三维元组了
        #标签y是0到9的数字,表示图片是数字几,可以输出看一下。由于x是元组类型,无法用shape(),只能用shape【】
        y = y.reshape(1,-1)
        y_test = y_test.reshape(1, -1)
        print("训练集维度:",x.shape[0],x.shape[1],x.shape[2])#打印训练集维度
        print("测试集维度:",x_test.shape[0],x_test.shape[1],x_test.shape[2])#打印测试集维度
    
        #用独热码处理标签,调用pandas库中Series和get_dummier函数
        y = np.squeeze(y)#使得标签是1维的
        y = pd.Series(y)
        y = pd.get_dummies(y)
        #print(y)这个可以查看矩阵是如何的,y是60000万行,10列
        y = np.array(y).T#y变成10行,60000列,60000列是样本个数
    
        y_test = np.squeeze(y_test)  # 使得标签是1维的
        y_test = pd.Series(y_test)
        y_test = pd.get_dummies(y_test)
        # print(y_test)这个可以查看矩阵是如何的,y_test是10000万行,10列
        y_test = np.array(y_test).T  # y_test变成10行,10000列,10000列是样本个数
    
        train_set_x_orig, train_set_y, test_set_x_orig, test_set_y = x,y,x_test,y_test
        return train_set_x_orig, train_set_y, test_set_x_orig, test_set_y
    load_dataset()
    
    train_set_x_orig, train_set_y, test_set_x_orig, test_set_y=load_dataset()
    #可以打印图片看一下,比如训练集中第100张的图片
    plt.imshow(train_set_x_orig[99])  # 打印的图片
    print(train_set_y[0][99])  # 输出图片对应标签
    plt.show()  # 展示需要打印的图片
    

    Optimization_mnist.py

    # conding:utf-8
    import numpy as np
    import matplotlib.pyplot as plt
    from lr_utils import load_dataset
    
    def tanh(z):#tanh函数
        return (np.exp(z)-np.exp(-z))/(np.exp(z)+np.exp(-z))
    def relu(z):#relu函数
        return np.maximum(0,z)
    def tanh_1(z):#tanh函数的导数
        return 1-tanh(z)**2
    def relu_1(z):#relu函数的导数
        return np.maximum(0, z/np.abs(z))
    def sigmoid(z):
        return 1/(1+np.exp(-z))
    
    def ward(L,n,m,dim):#对参数进行初始化
        np.random.seed(1)
        w = []
        b = []
        Vdw, Vdb, Sdw, Sdb = [],[],[],[]#优化算法的值
        for i in range(0, L):
            if i != 0 and i != L - 1:
                #p = np.random.randn(dim, dim) *0.001
                p = np.random.randn(dim, dim) * np.sqrt(2 / dim)
            elif i == 0:
                #p = np.random.randn(dim, m) * 0.001
                p = np.random.randn(dim, m) * np.sqrt(2 / m)
            else:
                #p = np.random.randn(1, dim) * 0.001
                p = np.random.randn(10, dim) * np.sqrt(2 / dim)
            w.append(p)
            b.append(1)
            Vdw.append(0)#初始化为0
            Vdb.append(0)
            Sdw.append(0)
            Sdb.append(0)
    
        return w, b,Vdw,Vdb,Sdw,Sdb
    
    def forward_back(w,b,a,Y,L,m,lambd):#用于训练的归一化前向传播
        z = []
        add = 0
        sigma2,mu = [],[]
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            #归一化输入z
            muL = (1/m)*np.sum(zl,axis=1,keepdims=True)
            sigmaL = (1/m)*np.sum(np.power(zl-muL,2),axis=1,keepdims=True)
            z_norm = (zl-muL)/(np.sqrt(sigmaL+0.00000001))
            gamma,beta_1 = 1*np.sqrt(sigmaL+0.00000001),muL+0#此时z的方差为1,均值为0
            zl = np.multiply(z_norm,gamma) + beta_1
            mu.append(muL)
            sigma2.append(sigmaL)
            #可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            #因为z = γ*z_norm+β可以看成线性函数,类似于z = wx+b,也可以对γ和β进行梯度下降更新。
    
            add += np.sum((lambd / (2 * m)) * np.dot(w[i], w[i].T))#L2正则化项
            z.append(zl)
            a = relu(zl)
    
        #使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t,axis = 0,keepdims=True)#axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t,ti)#矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        #损失函数也应该重新定义
        J = (-1/m)*np.sum(Y*np.log(a))+ add #注意Y*nu.log(a)计算得到是多行的矩阵,但只有一行是非0行,我们之前定义的损失函数相当于这个特殊情况
    
        # a = sigmoid(zl)
        #J = (-1/m)*np.sum(1 * Y * np.log(a) + (1 - Y) * np.log(1 - a)) + add  # 损失函数
        return z, a, J,sigma2,mu
    
    def forward_test(w, b, a, Y, L, m, lambd,sigma2,mu):  # 用于测试的归一化前向传播
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            # 归一化输入z
            z_norm = (zl - mu[i]) / (np.sqrt(sigma2[i] + 0.00000001))
            gamma, beta_1 = 1 * np.sqrt(sigma2[i] + 0.00000001), mu[i] + 0  # 此时z的方差为1,均值为0
            zl = np.multiply(z_norm, gamma) + beta_1
            # 可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            a = relu(zl)
        # 使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t, axis=0, keepdims=True)  # axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t, ti)  # 矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        # a = sigmoid(zl)
        return a
    
    def backward(w,b,X,Y,m,L,lambd):#反向传播
        z,a,J,sigma2,mu = forward_back(w,b,X,Y,L,m,lambd)
        dw,db = [],[]
        for i in range(L - 1, 0, -1):
            if i == L - 1:
                dz = a - Y
            else:
                dz = np.dot(w[i + 1].T, dz) * relu_1(z[i])
            Dw = 1 / m * (np.dot(dz, relu(z[i - 1]).T)) + (lambd / m) * w[i]
            Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
            dw.append(Dw)
            db.append(Db)
    
        dz = np.dot(w[1].T, dz) * relu_1(z[0])
        Dw = 1 / m * np.dot(dz, X.T) + (lambd / m) * w[0]
        Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
        dw.append(Dw)
        db.append(Db)
        return dw, db, J,sigma2,mu
    def back_momentum(w,b,X,Y,learning,m,L,lambd,beta,Vdw,Vdb):#使用momentum梯度下降的反向传播
        dw, db, J,sigma2,mu = backward(w,b,X,Y,m,L,lambd)
        # 不使用偏差修正不影响最后结果
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Vdw[i] = beta * Vdw[i] + (1 - beta) * dw[L-i-1]
            Vdb[i] = beta * Vdb[i] + (1 - beta) * db[L-i-1]
            w[i] = w[i] - learning * Vdw[i]
            b[i] = b[i] - learning * Vdb[i]
    
        return w,b,J,Vdw,Vdb,sigma2,mu
    def back_RMSprop(w,b,X,Y,learning,m,L,lambd,beta,Sdw,Sdb):#使用RMSprop梯度下降的反向传播
        dw, db, J ,sigma2,mu= backward(w,b,X,Y,m,L,lambd)
        # 不使用偏差修正不影响最后结果
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Sdw[i] = beta * Sdw[i] + (1 - beta) * np.power(dw[L-i-1],2)
            Sdb[i] = beta * Sdb[i] + (1 - beta) * np.power(db[L-i-1],2)
            w[i] = w[i] - learning * dw[L-i-1] / (np.power(Sdw[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
            b[i] = b[i] - learning * db[L-i-1] / (np.power(Sdb[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
    
        return w,b,J,Sdw,Sdb,sigma2,mu
    def back_Adam(w,b,X,Y,learning,m,L,lambd,beta,Vdw,Vdb,Sdw,Sdb):#使用Adam梯度下降的反向传播
        dw, db, J ,sigma2,mu= backward(w,b,X,Y,m,L,lambd)
        # 通常使用偏差修正
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Vdw[i] = beta * Vdw[i] + (1 - beta) * dw[L - i - 1]
            Vdb[i] = beta * Vdb[i] + (1 - beta) * db[L - i - 1]
            Sdw[i] = beta * Sdw[i] + (1 - beta) * np.power(dw[L-i-1],2)
            Sdb[i] = beta * Sdb[i] + (1 - beta) * np.power(db[L-i-1],2)
            '''
            Vdw[i] /= 1 - np.power(beta, t)#t表示代数(所有mini_batch训练一次称为一代)
            Vdb[i] /= 1 - np.power(beta, t)
            Sdw[i] /= 1 - np.power(beta, t)
            Sdb[i] /= 1 - np.power(beta, t)
            '''
            w[i] = w[i] - learning * Vdw[i] / (np.power(Sdw[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
            b[i] = b[i] - learning * Vdb[i] / (np.power(Sdb[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
    
        return w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu
    
    def text(x,y,w,b,L,m,lambd,sigma2, mu):#查看测试集准确率
        a = forward_test(w, b, x, y, L, m,lambd,sigma2,mu)
        #得到的a是一个10行,10000列的矩阵,里面数表示概率
        a = a.T#先将a转置
        for i in range(x.shape[1]):
            a[i] = np.where(a[i].max() == a[i], 1, 0)#最大数位置改为存1,不是最大数改为存0,这样就处理好y^了
        a = a.T  # 将a转回去
        lop_1 = np.sum(np.abs(y-a),axis = 0,keepdims=True)/2#这个lop_1中存的是1和0,1表示预测错误,0表示正确
        lop_2 = 1-np.sum(lop_1,axis=1,keepdims=True)/10000#表示正确所占比例,也就是准确率
        lop_2=np.squeeze(lop_2)
    
        print("测试集准确性:{0}%".format(lop_2*100))
    
        return 0
    
    if __name__ == "__main__":
        L = 10#神经网络层数
        dim = 20#隐藏层节点个数
        learning_rate = 0.05#学习率
        loss= []#损失函数
        lambd = 0.01 # L2正则化参数
        beta = 0.9#β值;1/(1-β)表示平均前多少轮的指数加权平均数
        decay_rate = 0.0009#学习率衰减率
        mini_batch = 300#一次的训练量,60000万张图片,要带入200次,全部训练一遍称为一代
        sigma2, mu = 0, 0  # 用于决定将batch正则化拟合进神经网络的均值和方差
        train_set_x_orig, train_set_y, test_set_x_orig, test_set_y = load_dataset()
        train_set_x = train_set_x_orig.reshape((train_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        test_set_x = test_set_x_orig.reshape((test_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        print("训练集降维后的维度: " + str(train_set_x.shape))
        print("训练集_标签的维数 : " + str(train_set_y.shape))
        print("测试集降维后的维度: " + str(test_set_x.shape))
        print("测试集_标签的维数 : " + str(test_set_y.shape))
        print()
        w,b,Vdw,Vdb,Sdw,Sdb = ward(L,train_set_x.shape[1],train_set_x.shape[0],dim)#vdw表示momentum,Sdw表示RMSprop
        for i in range(0,200):
            Sigma2, Mu,J_average = 0,0,0#用于决定将batch正则化拟合进神经网络的均值和方差
            for j in range(0,(train_set_x.shape[1]//mini_batch)):
                #w,b,J,Vdw,Vdb = back_momentum(w,b,train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita,Vdw,Vdb)
                #w,b,J,Vdw,Vdb = back_RMSprop(w, b, train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita, Sdw, Sdb)
                w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu = back_Adam(w,b,((train_set_x.T)[j*mini_batch:(j+1)*mini_batch]).T,((train_set_y.T)[j*mini_batch:(j+1)*mini_batch]).T,learning_rate,mini_batch,L,lambd,beta,Vdw,Vdb, Sdw, Sdb)
                #如果有多个mini_batch应该在此处对返回的sigam2和mu使用指数加权平均数,也是滑动平均数
                Sigma2 = np.multiply(beta,Sigma2) + np.multiply((1-beta),sigma2)
                Mu = np.multiply(beta,Mu) + np.multiply((1-beta),mu)
                J_average = np.multiply(beta,J) + np.multiply((1-beta),J)
            learning_rate = learning_rate * (1 / (1 + i*decay_rate) )#使用学习率衰减
            if i % 10 == 0:
                print("loss:",J_average)
                loss.append(J_average)
        plt.plot(loss)#打印损失函数
        plt.show()
    
        text(test_set_x,test_set_y,w,b,L,test_set_x.shape[1],lambd,Sigma2,Mu)
    
    

    lr_mnist.py:

    import pandas as pd
    import numpy as np
    
    def load_dataset1():
        df = pd.read_csv('train.csv')  # 得到的是一个字典集
        f1 = [f"pixel{i}" for i in range(0, 28 * 28)]  # 产生字符串列表,从pixel0到pixel783
        f2 = 'label'
        train_x = np.array(df[f1].values)  # 通过键获取字典数据,并且转化为矩阵
        train_y = np.array(df[f2].values)
        train_y=pd.Series(train_y)
        train_y=np.array(pd.get_dummies(train_y))#独热码实现softmax
        #print(train_y[0:12])
        train_set_y, test_set_y=train_y[0:40000].T,train_y[40000:42000].T
    
        #print(train_x.shape[0], train_x.shape[1])  # 输出维度
        print(train_y.shape[0],train_y.shape[1])  # 输出维度
    
        dp = pd.read_csv('test.csv')  # 得到的是一个字典集
        f = [f"pixel{i}" for i in range(0, 28 * 28)]  # 产生字符串列表,从pixel0到pixel783
        test_x = np.array(dp[f].values)  # 通过键获取字典数据,并且转化为矩阵
        #print(test_x.shape[0], test_x.shape[1])  # 输出维度
    
        train_set_x_orig,  test_set_x_orig = train_x[0:40000],train_x[40000:42000]
        return train_set_x_orig, train_set_y, test_set_x_orig, test_set_y
    
    def load_dataset2():
        df = pd.read_csv('train.csv')  # 得到的是一个字典集
        f1 = [f"pixel{i}" for i in range(0, 28 * 28)]  # 产生字符串列表,从pixel0到pixel783
        f2 = 'label'
        train_x = np.array(df[f1].values)  # 通过键获取字典数据,并且转化为矩阵
        train_y = np.array(df[f2].values)
        train_y=pd.Series(train_y)
        train_y=np.array(pd.get_dummies(train_y))#独热码实现softmax
        #print(train_y[0:12])
        train_set_y=train_y.T
    
        #print(train_x.shape[0], train_x.shape[1])  # 输出维度
        print(train_y.shape[0],train_y.shape[1])  # 输出维度
    
        dp = pd.read_csv('test.csv')  # 得到的是一个字典集
        f = [f"pixel{i}" for i in range(0, 28 * 28)]  # 产生字符串列表,从pixel0到pixel783
        test_x = np.array(dp[f].values)  # 通过键获取字典数据,并且转化为矩阵
        #print(test_x.shape[0], test_x.shape[1])  # 输出维度
    
        train_set_x_orig,  test_set_x_orig = train_x,test_x
        return train_set_x_orig, train_set_y, test_set_x_orig
    
    #train_set_x_orig, train_set_y, test_set_x_orig, test_set_y=load_dataset()
    #print(train_set_y.shape[0],train_set_y.shape[1])
    #print(train_set_x_orig.shape[0],train_set_x_orig.shape[1])
    

    test_mnist.py:

    # conding:utf-8
    import numpy as np
    import csv
    import matplotlib.pyplot as plt
    from lr_mnist import load_dataset2
    
    def tanh(z):#tanh函数
        return (np.exp(z)-np.exp(-z))/(np.exp(z)+np.exp(-z))
    def relu(z):#relu函数
        return np.maximum(0,z)
    def tanh_1(z):#tanh函数的导数
        return 1-tanh(z)**2
    def relu_1(z):#relu函数的导数
        return np.maximum(0, z/np.abs(z))
    def sigmoid(z):
        return 1/(1+np.exp(-z))
    
    def ward(L,n,m,dim):#对参数进行初始化
        np.random.seed(1)
        w = []
        b = []
        Vdw, Vdb, Sdw, Sdb = [],[],[],[]#优化算法的值
        for i in range(0, L):
            if i != 0 and i != L - 1:
                #p = np.random.randn(dim, dim) *0.001
                p = np.random.randn(dim, dim) * np.sqrt(2 / dim)
            elif i == 0:
                #p = np.random.randn(dim, m) * 0.001
                p = np.random.randn(dim, m) * np.sqrt(2 / m)
            else:
                #p = np.random.randn(1, dim) * 0.001
                p = np.random.randn(10, dim) * np.sqrt(2 / dim)
            w.append(p)
            b.append(1)
            Vdw.append(0)#初始化为0
            Vdb.append(0)
            Sdw.append(0)
            Sdb.append(0)
    
        return w, b,Vdw,Vdb,Sdw,Sdb
    
    def forward_back(w,b,a,Y,L,m,lambd):#用于训练的归一化前向传播
        z = []
        add = 0
        sigma2,mu = [],[]
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            #归一化输入z
            muL = (1/m)*np.sum(zl,axis=1,keepdims=True)
            sigmaL = (1/m)*np.sum(np.power(zl-muL,2),axis=1,keepdims=True)
            z_norm = (zl-muL)/(np.sqrt(sigmaL+0.00000001))
            gamma,beta_1 = 1*np.sqrt(sigmaL+0.00000001),muL+0#此时z的方差为1,均值为0
            zl = np.multiply(z_norm,gamma) + beta_1
            mu.append(muL)
            sigma2.append(sigmaL)
            #可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            #因为z = γ*z_norm+β可以看成线性函数,类似于z = wx+b,也可以对γ和β进行梯度下降更新。
    
            add += np.sum((lambd / (2 * m)) * np.dot(w[i], w[i].T))#L2正则化项
            z.append(zl)
            a = relu(zl)
    
        #使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t,axis = 0,keepdims=True)#axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t,ti)#矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        #损失函数也应该重新定义
        J = (-1/m)*np.sum(Y*np.log(a))+ add #注意Y*nu.log(a)计算得到是多行的矩阵,但只有一行是非0行,我们之前定义的损失函数相当于这个特殊情况
    
        # a = sigmoid(zl)
        #J = (-1/m)*np.sum(1 * Y * np.log(a) + (1 - Y) * np.log(1 - a)) + add  # 损失函数
        return z, a, J,sigma2,mu
    
    def forward_test(w, b, a,  L,sigma2,mu):  # 用于测试的归一化前向传播
        for i in range(0, L):
            zl = np.dot(w[i], a) + b[i]
    
            # 归一化输入z
            z_norm = (zl - mu[i]) / (np.sqrt(sigma2[i] + 0.00000001))
            gamma, beta_1 = 1 * np.sqrt(sigma2[i] + 0.00000001), mu[i] + 0  # 此时z的方差为1,均值为0
            zl = np.multiply(z_norm, gamma) + beta_1
            # 可以发现,如果使用zl = z_norm此时平均值为0,方差为1,对于我们这个数据是没有影响的,因为我们图片像素点已经除以了255,也比较均匀,是基本处于这个范围内的数
            a = relu(zl)
        # 使用softmax回归
        t = np.exp(zl)
        ti = np.sum(t, axis=0, keepdims=True)  # axis=0表示对行求和,对输出zl的行求和,这样可以保证最后概率之和为1
        a = np.divide(t, ti)  # 矩阵除法函数,也可以用/。不过我这样用/有时候会提示一些奇怪错误,提示无法进行除法
        # a = sigmoid(zl)
        return a
    
    def backward(w,b,X,Y,m,L,lambd):#反向传播
        z,a,J,sigma2,mu = forward_back(w,b,X,Y,L,m,lambd)
        dw,db = [],[]
        for i in range(L - 1, 0, -1):
            if i == L - 1:
                dz = a - Y
            else:
                dz = np.dot(w[i + 1].T, dz) * relu_1(z[i])
            Dw = 1 / m * (np.dot(dz, relu(z[i - 1]).T)) + (lambd / m) * w[i]
            Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
            dw.append(Dw)
            db.append(Db)
    
        dz = np.dot(w[1].T, dz) * relu_1(z[0])
        Dw = 1 / m * np.dot(dz, X.T) + (lambd / m) * w[0]
        Db = 1 / m * np.sum(dz, axis=1, keepdims=True)
        dw.append(Dw)
        db.append(Db)
        return dw, db, J,sigma2,mu
    def back_momentum(w,b,X,Y,learning,m,L,lambd,beta,Vdw,Vdb):#使用momentum梯度下降的反向传播
        dw, db, J,sigma2,mu = backward(w,b,X,Y,m,L,lambd)
        # 不使用偏差修正不影响最后结果
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Vdw[i] = beta * Vdw[i] + (1 - beta) * dw[L-i-1]
            Vdb[i] = beta * Vdb[i] + (1 - beta) * db[L-i-1]
            w[i] = w[i] - learning * Vdw[i]
            b[i] = b[i] - learning * Vdb[i]
    
        return w,b,J,Vdw,Vdb,sigma2,mu
    def back_RMSprop(w,b,X,Y,learning,m,L,lambd,beta,Sdw,Sdb):#使用RMSprop梯度下降的反向传播
        dw, db, J ,sigma2,mu= backward(w,b,X,Y,m,L,lambd)
        # 不使用偏差修正不影响最后结果
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Sdw[i] = beta * Sdw[i] + (1 - beta) * np.power(dw[L-i-1],2)
            Sdb[i] = beta * Sdb[i] + (1 - beta) * np.power(db[L-i-1],2)
            w[i] = w[i] - learning * dw[L-i-1] / (np.power(Sdw[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
            b[i] = b[i] - learning * db[L-i-1] / (np.power(Sdb[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
    
        return w,b,J,Sdw,Sdb,sigma2,mu
    def back_Adam(w,b,X,Y,learning,m,L,lambd,beta,Vdw,Vdb,Sdw,Sdb):#使用Adam梯度下降的反向传播
        dw, db, J ,sigma2,mu= backward(w,b,X,Y,m,L,lambd)
        # 通常使用偏差修正
        for i in range(0,L):#注意dw和db是由后往前存的,位置与w和b相反
            Vdw[i] = beta * Vdw[i] + (1 - beta) * dw[L - i - 1]
            Vdb[i] = beta * Vdb[i] + (1 - beta) * db[L - i - 1]
            Sdw[i] = beta * Sdw[i] + (1 - beta) * np.power(dw[L-i-1],2)
            Sdb[i] = beta * Sdb[i] + (1 - beta) * np.power(db[L-i-1],2)
            '''
            Vdw[i] /= 1 - np.power(beta, t)#t表示代数(所有mini_batch训练一次称为一代)
            Vdb[i] /= 1 - np.power(beta, t)
            Sdw[i] /= 1 - np.power(beta, t)
            Sdb[i] /= 1 - np.power(beta, t)
            '''
            w[i] = w[i] - learning * Vdw[i] / (np.power(Sdw[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
            b[i] = b[i] - learning * Vdb[i] / (np.power(Sdb[i],1/2) + 0.00000001)#加上一个较小的值,防止整个值变成无穷大
    
        return w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu
    
    def text(x,w,b,L,m,lambd,sigma2, mu):#查看测试集准确率
        a = forward_test(w, b, x,  L,sigma2,mu)
        #得到的a是一个10行,10000列的矩阵,里面数表示概率
        a = a.T#先将a转置
        y_n=[]#就是预测结果的标签
        for i in range(x.shape[1]):
            y_n.append(np.argmax(a[i]))
        my = open("my.csv", "w")
        my.write("ImageId,Label\n")
        for j in range(0, x.shape[1]):
            my.write(str(j+1) + "," + str(y_n[j]) + "\n")
        return 0
    
    if __name__ == "__main__":
        L = 5#神经网络层数
        dim = 30#隐藏层节点个数
        learning_rate = 0.05#学习率
        loss= []#损失函数
        lambd = 0.1 # L2正则化参数
        beta = 0.9#β值;1/(1-β)表示平均前多少轮的指数加权平均数
        decay_rate = 0.0009#学习率衰减率
        mini_batch = 200#一次的训练量,40000万张图片,要带入200次,全部训练一遍称为一代
        sigma2, mu = 0, 0  # 用于决定将batch正则化拟合进神经网络的均值和方差
        train_set_x_orig, train_set_y, test_set_x_orig = load_dataset2()
        train_set_x = train_set_x_orig.reshape((train_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        test_set_x = test_set_x_orig.reshape((test_set_x_orig.shape[0], -1)).T / 255  # 降维,化为区间(0,1)内的数
        print("训练集降维后的维度: " + str(train_set_x.shape))
        print("训练集_标签的维数 : " + str(train_set_y.shape))
        print("测试集降维后的维度: " + str(test_set_x.shape))
        print()
        w,b,Vdw,Vdb,Sdw,Sdb = ward(L,train_set_x.shape[1],train_set_x.shape[0],dim)#vdw表示momentum,Sdw表示RMSprop
        for i in range(0,250):
            Sigma2, Mu,J_average = 0,0,0#用于决定将batch正则化拟合进神经网络的均值和方差
            for j in range(0,(train_set_x.shape[1]//mini_batch)):
                #w,b,J,Vdw,Vdb = back_momentum(w,b,train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita,Vdw,Vdb)
                #w,b,J,Vdw,Vdb = back_RMSprop(w, b, train_set_x,train_set_y,learning_rate,train_set_x.shape[1],L,lambd,beita, Sdw, Sdb)
                w,b,J,Vdw,Vdb,Sdw,Sdb,sigma2,mu = back_Adam(w,b,((train_set_x.T)[j*mini_batch:(j+1)*mini_batch]).T,((train_set_y.T)[j*mini_batch:(j+1)*mini_batch]).T,learning_rate,mini_batch,L,lambd,beta,Vdw,Vdb, Sdw, Sdb)
                #如果有多个mini_batch应该在此处对返回的sigam2和mu使用指数加权平均数,也是滑动平均数
                Sigma2 = np.multiply(beta,Sigma2) + np.multiply((1-beta),sigma2)
                Mu = np.multiply(beta,Mu) + np.multiply((1-beta),mu)
                J_average = np.multiply(beta,J) + np.multiply((1-beta),J)
            learning_rate = learning_rate * (1 / (1 + i*decay_rate) )#使用学习率衰减
            if i % 10 == 0:
                print("loss:",J_average)
                loss.append(J_average)
        plt.plot(loss)#打印损失函数
        plt.show()
    
        text(test_set_x,w,b,L,test_set_x.shape[1],lambd,Sigma2,Mu)
    
    
    
    
    展开全文
  • 手写数字识别的Tensorflow完整代码,### 1. MNIST机器学习入门 **1.1.1 简介** 下载MNIST数据集,并打印一些基本信息: ``` python download.py ``` **1.1.2 实验:将MNIST数据集保存为图片** ``` ...
  • 注: 本文根据阿卡蒂奥的博客文章进行调整,修复了少量问题,原文地址:https://blog.csdn.net/akadiao/article/details/78175737 1. 运行环境建议 ... 下载MNIST手写数字图像数据集文件 mnist.pkl.gz,这...
  • Pytorch入门——手把手教你MNIST手写数字识别

    千次阅读 多人点赞 2021-01-22 12:35:11
    MNIST手写数字识别教程 要开始带组内的小朋友了,特意出一个Pytorch教程来指导一下 [!] 这里是实战教程,默认读者已经学会了部分深度学习原理,若有不懂的地方可以先停下来查查资料 目录MNIST手写数字识别教程1 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,561
精华内容 5,024
关键字:

mnist手写数字识别python

python 订阅