天天看點

Tensorflow筆記(5):MNIST資料集輸出手寫數字識别準确率

本篇博文的内容是:搭建神經網絡,在mnist資料集上訓練模型,輸出手寫數字識别準确率

5.1

√t mnist  資料集 :包含 7 7  萬張 黑底白字手寫數字 圖檔, 其中 55000  張為訓練集 ,5000  張為驗證集,1 10 0000  張 為測試集 。每張圖檔大小為28*28  像素,圖檔中 純 黑色像素值為0 , 純 白色像素值為1 。資料集的标簽是長度為 10  的一維數組,數組中每個元素 索引号表示對應數字出現的機率。

在将 mnist 資料集作為輸入喂入神經網絡時,需先将資料集中每張圖檔變為長度784 一維數組,将該數組作為神經網絡輸入特征喂入神經網絡。

例如:

一張數字手寫體圖檔變成長度為 784 的一維數組[0.0.0.0.0.231 0.235 0.459……0.219 0.0.0.0.]輸入神經網絡。該圖檔對應的标簽為[0.0.0.0.0.0.1.0.0.0],标簽中索引号為 6 的元素為 1,表示是數字 6 出現的機率為 100%,則該圖

片對應的識别結果是 6。

其他廢話就不多說直接上程式,手寫數字識别的程式總共有四個檔案,分别是mnist_forward.py,mnist_backward.py,mnist_test.py,mnist_app.py分别是前向傳播,反向傳播,準确率測試和我們的手寫數字識别這四個檔案。

1.首先看前向傳播:mnist_forward.py

#coding:utf-8

'''BP神經前向傳播'''

import tensorflow as tf

INPUT_NODE = 784#神經網絡的輸入節點是784個,正好是28*28*1

OUTPUT_NODE = 10#輸出點

LAYER1_NODE = 500#隐藏層節點的個數

#得到我們的權值矩陣函數

def get_weight(shape,regularizer):

    w = tf.Variable(tf.truncated_normal(shape,stddev = 0.1))

    '''如果使用正則化,則将每一個w的正則化記錄到總loss中的這一行代碼'''

    if regularizer !=None: tf.add_to_collection('losses',tf.contrib.layers.l2_regularizer(regularizer)(w))

    return w

#得到偏置項函數

def get_bias(shape):

    b = tf.Variable(tf.zeros(shape))

    return b

#定義前向傳播的函數

def forward(x,regularizer):

    w1 = get_weight([INPUT_NODE,LAYER1_NODE],regularizer)

    b1 = get_bias([LAYER1_NODE])

    y1 = tf.nn.relu(tf.matmul(x,w1)+b1)

    w2 = get_weight([LAYER1_NODE,OUTPUT_NODE],regularizer)

    b2 = get_bias([OUTPUT_NODE])

    y = tf.matmul(y1,w2)+b2

    return y

2.反向傳播:mnist_backward.py

#coding:utf-8

#反向傳播

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data  #導入子產品

import mnist_forward

import os

BATCH_SIZE = 200  #一次性喂入神經網絡的資料大小

LEARNING_RATE_BASE = 0.1   #初始的學習率

LEARNING_RATE_DECAY = 0.99  #衰減率

REGULARIZER = 0.0001 #正則化參數

STEPS = 50000

MOVING_AVERAGE_DECAY = 0.99

MODEL_SAVE_PATH = "./MODEL/"

#MODEL_SAVE_PATH = "./home/lyw/eclipse-workspace/testpython1/test"

#MODEL_SAVE_PATH = "./model/"

MODEL_NAME = "mnist_model"#模型的儲存的檔案名

#反向傳播,輸入mnist

def backward(mnist):

    #輸入x,y_進行占位

    x = tf.placeholder(tf.float32,[None,mnist_forward.INPUT_NODE])

    y_ = tf.placeholder(tf.float32,[None,mnist_forward.OUTPUT_NODE])

    #首先進行前向傳播

    y = mnist_forward.forward(x,REGULARIZER)

    '''輪數計數器指派0,設定為不可訓練'''

    global_step = tf.Variable(0,trainable = False)

    '''定義損失函數,将softmax和交叉商協同使用'''

    ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels= tf.argmax(y_,1))

    cem = tf.reduce_mean(ce)#對向量求均值

    loss = cem+tf.add_n(tf.get_collection('losses'))#将參數w的正則化加入到總loss中

    '''函數實作指數衰減學習率'''

    learning_rate = tf.train.exponential_decay(

            LEARNING_RATE_BASE,#初始的學習率

            global_step,

            mnist.train.num_examples/BATCH_SIZE,#訓練這麼多輪之後開始衰減

            LEARNING_RATE_DECAY,#衰減指數

            staircase=True)

    '''訓練函數'''

    train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)

    '''采用滑動平均的方法進行參數的更新'''

    ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)

    ema_op = ema.apply(tf.trainable_variables())

    with tf.control_dependencies([train_step,ema_op]):

        train_op = tf.no_op(name='train')

    '''儲存模型'''

    saver = tf.train.Saver()#執行個體化saver對象

    with tf.Session() as sess:

        init_op = tf.global_variables_initializer()

        sess.run(init_op)

        for i in range(STEPS):

            xs,ys = mnist.train.next_batch(BATCH_SIZE)

            _,loss_value,step = sess.run([train_op,loss,global_step],feed_dict={x:xs,y_:ys})

            if i%1000 ==0:

                #每1000輪列印出目前的loss值

                print("After %d training step(s),loss on training batchis %g" %(step,loss_value))

                #循環1000輪儲存模型到目前會話

                saver.save(sess,os.path.join(MODEL_SAVE_PATH,MODEL_NAME),global_step = global_step)

def main():

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

    backward(mnist)

if __name__ =='__main__':

    main()

3.測試程式:mnist_test.py

# -*- coding: utf-8 -*-

"""

Created on Sat Sep 29 12:46:26 2018

@author: Ad

"""

import time

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data

import mnist_forward

import mnist_backward

TEST_INTERVAL_SECS=5 #定義程式循環的間隔時間為5seconds

def test(mnist):

    with tf.Graph().as_default() as g:

        x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE]) # placeholder占位符,None指可以賦很多組資料,每組有前向傳播中定義的input_node輸入特征的個數

        y_ = tf.placeholder(tf.float32, [None,mnist_forward.OUTPUT_NODE])

        y = mnist_forward.forward(x, None)

        #定義滑動平均

        ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)

        ema_restore = ema.variables_to_restore()

        # 先執行個體化saver()方法   

        saver = tf.train.Saver(ema_restore)

        # 計算正确率方法

        curracy_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))#選取最大值的操作隻在第一個次元進行,傳回每一行最大值所對應的清單索引号

        accuracy = tf.reduce_mean(tf.cast(curracy_prediction, tf.float32))

        while True:

            with tf.Session() as sess:

                #将滑動平均值賦給ckpt

                ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)

                #判斷是否有模型

                if ckpt and ckpt.model_checkpoint_path:# 若有,則恢複模型儲存在目前會話

                    saver.restore(sess, ckpt.model_checkpoint_path)

                    #saver.restore(sess, ckpt.model_checkpoint_path)

                    # 恢複輪數

                    global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]

                    print mnist.test.images.shape

                    print mnist.test.labels.shape

                    accuracy_score = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

                    # 列印準确率

                    print("After %s training steps, test accuracy = %g" %(global_step, accuracy_score))

                    # 若沒找到子產品,則顯示沒找到

                else:

                    print("No checkpoint file found")

                    return

            time.sleep(TEST_INTERVAL_SECS)

def main():

    # main()函數讀取資料集,調用test函數,将讀取的資料集傳入

    mnist = input_data.read_data_sets("./data/", one_hot = True) # read_data_sets()方法

    test(mnist)

if __name__ =='__main__':

    main()

4.應用程式:mnist_app.py

#coding:utf-8

#對于圖檔進行與處理函數

import tensorflow as tf

import numpy as np

from PIL import Image

import mnist_backward

import mnist_forward

def restore_model(testPicArr):

    with tf.Graph().as_default() as tg:

        x = tf.placeholder(tf.float32,[None,mnist_forward.INPUT_NODE])#隻需要給x占位

        y = mnist_forward.forward(x,None)#計算輸出y

        preValue = tf.argmax(y,1)#y的最大值對應的清單索引号就是對以值

        '''執行個體化帶有滑動平均值的saver'''

        variable_averages = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)

        variables_to_restore = variable_averages.variables_to_restore()

        saver = tf.train.Saver(variables_to_restore)

        with tf.Session() as sess :

            '''斷電續訓'''

            ckpt = tf.train.get_checkpoint_state(mnist_backward.MODEL_SAVE_PATH)

            if ckpt and ckpt.model_checkpoint_path:

                saver.restore(sess,ckpt.model_checkpoint_path)

                preValue = sess.run(preValue,feed_dict = {x:testPicArr})

                return preValue

            else:

                print("No checkponit file found")

                return -1

def pre_pic(picName):

    img = Image.open(picName)

    reIm = img.resize((28,28),Image.ANTIALIAS)#用消除鋸齒的方法将圖檔處理成28*28

    im_arr = np.array(reIm.convert('L'))#将reIm以灰階的形式轉換成矩陣

    for i in range(28):

        for j in range(28):

            im_arr[i][j] = 255-im_arr[i][j]

            if (im_arr[i][j]<50):

                im_arr[i][j] = 0

            else:im_arr[i][j] = 255

    nm_arr = im_arr.reshape([1,784])

    nm_arr = nm_arr.astype(np.float32)

    img_ready = np.multiply(nm_arr,1.0/255.0)

    return img_ready   

def application():

    testNum = input("input the number of test picture:")

    for i in range(testNum):

        testPic = raw_input("the path of test picture:")

        '''将圖檔轉換成能夠輸入神經網絡的值'''

        testPicArr = pre_pic(testPic)

        '''将處過後的圖檔輸入神經網絡'''

        preValue = restore_model(testPicArr)

        print "The prediction number is:",preValue

def main():

    application()

if __name__ == '__main__':

    main()

繼續閱讀