tensorflow1.12.1實現MNIST數據集訓練和識別


1.mnist_train.py

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 23 20:01:39 2019
tensorflow實現Lenet-5網絡,mnist_train.py實現lenet-5訓練過程
@author: zhaoy
"""


##lenet-5訓練過程

import os

import tensorflow as tf

from tensorflow.examples.tutorials.mnist import input_data

import numpy as np

 

import mnist_inference


##配置神經網絡的參數

BATCH_SIZE=100

LEARNING_RATE_BASE=0.01  #基礎學習率

LEARNING_RATE_DECAY=0.99

REGULARAZTION_RATE=0.0001

TRAINING_STEPS=30000

MOVING_AVERAGE_DECAY=0.99

##模型保存的路徑和文件名

MODEL_SAVE_PATH="./model/"

MODEL_NAME="model.ckpt"

##定義訓練過程

def train(mnist):

    #區別與全連接神經網絡的輸入是一個二維[None, mnist_inference.INPUT_NODE],
    #卷積神經網絡的輸入x是一個四維數組
    x=tf.placeholder(tf.float32,[

    BATCH_SIZE,                       # 第一維表示一個batch中樣例的個數

    mnist_inference.IMAGE_SIZE,       # 第二維和第三維表示圖片的尺寸28

    mnist_inference.IMAGE_SIZE,

    mnist_inference.NUM_CHANNELS],    #圖像通道數,黑白圖像賦值1,彩色圖像賦值3

                 name='x-input')

    y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE] , name='y-input')  

    regularizer=tf.contrib.layers.l2_regularizer(REGULARAZTION_RATE)

    y=mnist_inference.inference(x,True,regularizer)

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

    #給定滑動平均衰減率和訓練輪數的變量,初始化滑動平均類

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

    #在所有代表神經網絡參數的變量上使用滑動平均。

    variables_averages_op=variable_averages.apply(tf.trainable_variables())

    #計算交叉熵作為刻畫預測值和真實值之間差距的損失函數

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

    #計算在當前batch中所有樣例的交叉熵平均值

    cross_entropy_mean=tf.reduce_mean(cross_entropy)

    #計算L2正則化損失函數

    #regularizer=tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)

    #計算模型的正則化損失

    #regularization=regularizer(weights1)+regularizer(weights2)

    #總損失等於交叉熵損失和正則化損失的和

    loss=cross_entropy_mean+tf.add_n(tf.get_collection('losses'))                                            #regularization

    #設置指數衰減的學習率

    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)

    #with tf.control_dependencies([train_step,variables_averages_op]):train_op=tf.no_op(name='train')
    train_op=tf.group(train_step, variables_averages_op)
    

    #初始化tensorflow持久化類

    saver=tf.train.Saver()

    ##初始化會話並開始訓練過程

    with tf.Session() as sess:

        tf.global_variables_initializer().run()

        print("****************開始訓練************************")  

       # validate_feed={x:mnist.validation.images,y_:mnist.validation.labels}

 

        #准備測試數據.

        #test_feed={x:mnist.test.images,y_:mnist.test.labels}


        #迭代地訓練神經網絡

        for  i in range(TRAINING_STEPS):

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

            #區別於全連接神經網絡,卷積神經網絡的輸入為四維數組
            reshaped_xs = np.reshape(xs, (BATCH_SIZE,  

                                          mnist_inference.IMAGE_SIZE,  

                                          mnist_inference.IMAGE_SIZE,  

                                          mnist_inference.NUM_CHANNELS))

            train_op_renew,loss_value, step=sess.run([train_op,loss,global_step],

                                       feed_dict={x:reshaped_xs,y_:ys})

 

            if i%1000==0:

                print("After %d training step(s),loss on training batch is %g."%(step,loss_value))

 

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

                           

def main(argv=None):

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

    train(mnist)
    

if __name__=='__main__':

    tf.app.run()

 

2.mnist_inference.py

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 23 19:44:19 2019
Tensorflow實現LeNet-5模型,mnist_inference.py實現神經卷積網絡前向傳播過程
@author: zhaoy
"""
##實現神經卷積網絡的前向傳播過程

import tensorflow as tf

INPUT_NODE=784     
OUTPUT_NODE=10
IMAGE_SIZE=28

NUM_CHANNELS=1
NUM_LABELS=10

#第一層卷積層的尺寸和深度
CONV1_DEEP=32
CONV1_SIZE=5

#第二層卷積層的尺寸和深度
CONV2_DEEP=64
CONV2_SIZE=5

#全連接層的節點個數
FC_SISE=512

tf.reset_default_graph()
#定義卷積神經網絡的前向傳播過程,這里添加了一個新的參數train用以區分訓練過程和測試過程;train為布爾量:
#采用dropout機制防止過擬合,在全連接層layer5-fc1中包含dropout機制,
def inference(input_tensor,train,regularizer):

    ##聲明第一層卷積層的變量並實現前向傳播過程,這一層的輸入為28*28*1的矩陣,由於采取全0填充,所以輸出層為28*28*32的矩陣    
    with tf.variable_scope('layer1-conv1'):

        conv1_weights=tf.get_variable("weights",[CONV1_SIZE,CONV1_SIZE,NUM_CHANNELS,CONV1_DEEP],

                                      initializer=tf.truncated_normal_initializer(stddev=0.1))

        conv1_biases=tf.get_variable("bias",[CONV1_DEEP],initializer=tf.constant_initializer(0.0))

        #使用邊長為5,深度為32的過濾器,過濾器移動的步長為1,且使用全0填充.

        conv1=tf.nn.conv2d(input_tensor,conv1_weights,strides=[1,1,1,1],padding='SAME')

        relu1=tf.nn.relu(tf.nn.bias_add(conv1,conv1_biases))

    ##實現第二層(池化層的前向傳播過程),這里選用最大池化層,池化層的過濾器的邊長為2,所以輸出為14*14*32
    with tf.name_scope('layer2-poll'):

        pool1=tf.nn.max_pool(relu1,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

    ##聲明第三層卷積層的變量並實現前向傳播過程,這一層的輸入為14*14*32的矩陣,輸出為14*14*64
    with tf.variable_scope('layer3-conv2'):

        conv2_weights=tf.get_variable("weights",[CONV2_SIZE,CONV2_SIZE,CONV1_DEEP,CONV2_DEEP],

                                      initializer=tf.truncated_normal_initializer(stddev=0.1))

        conv2_biases=tf.get_variable("bias",[CONV2_DEEP],initializer=tf.constant_initializer(0.0))

 

        #使用邊長為5,深度為64的過濾器,過濾器移動的步長為1,且使用全0填充.

        conv2=tf.nn.conv2d(pool1,conv2_weights,strides=[1,1,1,1],padding='SAME')

        relu2=tf.nn.relu(tf.nn.bias_add(conv2,conv2_biases))

    ##實現第四層池化層的前向傳播過程,輸入為14*14*64的矩陣,輸出為7*7*64的矩陣
    with tf.name_scope('layer4-pool2'):

         pool2=tf.nn.max_pool(relu2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
        
 
    #第四層的輸出為7*7*64,然而第五層全連接層需要的輸入格式為向量,所以這里需要將7*7*64拉伸為一個向量。
    #pool2.get_shape。因為每層網絡的輸入輸出都是一batch,矩陣所以這里的維度也包含batch中數據的個數
    pool_shape=pool2.get_shape().as_list()

    nodes=pool_shape[1]*pool_shape[2]*pool_shape[3]

    #通過tf.reshape函數將第四層的輸出編程一個batch的向量
    reshaped=tf.reshape(pool2,[pool_shape[0],nodes])

    #聲明第五層全連接層的變量並實現前向傳播過程,這一層是一個拉直后的一組向量,向量長度為3136,輸出為為一組長度為512的向量
    #引入dropout機制,droupout在訓練時會隨機將部分節點輸出為0,即使部分節點“死掉”
    with tf.variable_scope('layer5-fc1'):

        fc1_weights=tf.get_variable("weight",[nodes,FC_SISE],

                                    initializer=tf.truncated_normal_initializer(stddev=0.1))

        if regularizer!=None:

            tf.add_to_collection('losses',regularizer(fc1_weights))

        fc1_biases=tf.get_variable("bias",[FC_SISE],initializer=tf.constant_initializer(0.1))

 

        fc1=tf.nn.relu(tf.matmul(reshaped,fc1_weights)+fc1_biases)
        
        #duopout系數為0.5
        if train:fc1=tf.nn.dropout(fc1,0.5)

    ##聲明第六層全連接層的變量並實現前向傳播過程,這一層輸入為長度為512的向量,輸出為一組長度10的向量
    with tf.variable_scope('layer6-fc2'):

        fc2_weights=tf.get_variable("weight",[FC_SISE,NUM_LABELS],

                                    initializer=tf.truncated_normal_initializer(stddev=0.1))

        if regularizer!=None:

            tf.add_to_collection('losses',regularizer(fc2_weights))

        fc2_biases=tf.get_variable("bias",[NUM_LABELS],

                                   initializer=tf.constant_initializer(0.1))

        logit=tf.matmul(fc1,fc2_weights)+fc2_biases

    ##返回第六層的輸出
    return logit

 

3.mnist_test.py

# -*- coding: utf-8 -*-
"""
Created on Mon Dec 23 17:28:07 2019
tensorflow實現神經網絡對mnist手寫字的識別,mnist_test.py評估訓練的神經網絡在mnist測試集的正確率
@author: zhaoy
"""

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

# 加載mnist_inference.py 和mnist_train.py中定義的常量和函數。
import mnist_inference
import mnist_train


def evaluate(mnist):
    with tf.Graph().as_default() as g:
        # 定義輸入輸出的格式。
        x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')
        y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')
        test_feed = {x: mnist.test.images, y_: mnist.test.labels}

        # 直接通過調用封裝好的函數來計算前向傳播的結果。因為測試時不關注ze正則化損失的值
        # 所以這里用於計算正則化損失的函數被設置為None。
        y = mnist_inference.inference(x, None)

        # 使用前向傳播的結果計算正確率。如果需要對未知的樣例進行分類,那么使用
        # tf.argmax(y,1)就可以得到輸入樣例的預測類別了。
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

        # 同訓練模型一樣,定義一個滑動平均類
        variable_averages = tf.train.ExponentialMovingAverage(
            mnist_train.MOVING_AVERAGE_DECAY
        )
        
        #在使用滑動平均進行模型訓練時,模型除了保存網絡參數以外,還會保存相應的滑動平均參數,
        #此時加載模型參數需要聯通滑動參數一起加載模型時,需要用到.variables_to_restore
        variables_to_restore = variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)

        with tf.Session() as sess:
            # tf.train.get_checkpoint_state函數會通過checkpoint文件自動
            # 找到目錄中最新模型的文件名。
            ckpt = tf.train.get_checkpoint_state(mnist_train.MODEL_SAVE_PATH)
            if ckpt and ckpt.model_checkpoint_path:
                # 加載模型。
                saver.restore(sess, ckpt.model_checkpoint_path)
                # 通過文件名得到模型保存時迭代的輪數。
                #split函數:拆分字符串。通過指定分隔符對字符串進行切片,並返回分割后的字符串列表(list)。
                #split函數返回值為:分割后的字符串列表。
                #list[n]:即表示選取第n個分片,n為-1即為末尾倒數第一個分片(分片即為在返回值列表中元素)
                global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
                accuracy_score = sess.run(accuracy, feed_dict=test_feed)
                print("After %s training step(s), test " "accuracy = %g" % (global_step, accuracy_score))
            else:
                print("No checkpoint file found")
                return

def main(argv=None):
    mnist = input_data.read_data_sets("C:/Users/zhaoy/Desktop/Tensorflow/sample/data/MNIST", one_hot=True)  #one_hot表示0-1編碼
    evaluate(mnist)

if __name__ == "__main__":
    tf.app.run()

4.predict.py

# -*- coding: utf-8 -*-
"""
Created on Fri Dec 27 17:35:39 2019

@author: zhaoy
"""
import tensorflow as tf
# 加載mnist_inference.py 和mnist_train.py中定義的常量和函數。
import mnist_inference
import mnist_train
import cv2

def imageprepare(file_name):
    im = cv2.imread(file_name,0)
    print(file_name)
    pixels = []
    h, w = im.shape
    #normalize pixels to 0 and 1. 0 is pure white, 1 is pure black.
    for i in range(h):
        for j in range(w):
            #如果是白底黑字則為:pixels.append((255-im[i,j])*1.0/255.0)
            pixels.append(im[i, j]*1.0/255.0)
    #print(pixels)
    return pixels

# =============================================================================
# def imageprepare(file_name):
#     image = tf.gfile.FastGFile(file_name, 'rb').read()
#     print(file_name)
#     pixels = []
#     image_data = tf.image.decode_jpeg(image)
#     image_data = tf.image.convert_image_dtype(image_data, dtype=tf.float32)
#     
#     pixels.append(image_data)
#     return pixels
# =============================================================================

x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')
y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')

y = mnist_inference.inference(x, None)

variable_averages = tf.train.ExponentialMovingAverage(mnist_train.MOVING_AVERAGE_DECAY)
variables_to_restore = variable_averages.variables_to_restore()
saver = tf.train.Saver(variables_to_restore)

prediction = tf.argmax(y, 1)
probability = tf.nn.softmax(y)

with tf.Session() as sess:
    result = imageprepare('4.jpg')
    tf.global_variables_initializer().run()
    ckpt = tf.train.get_checkpoint_state(mnist_train.MODEL_SAVE_PATH)
    if ckpt and ckpt.model_checkpoint_path:
        # 加載模型。
        saver.restore(sess, ckpt.model_checkpoint_path)        

        pre, prob = sess.run([prediction, probability], feed_dict={x:[result]})
        #pre = prediction.eval(feed_dict={x:[result]}, session=sess)
        #global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
        #accuracy_score = sess.run(accuracy, feed_dict=test_feed)
        print( "recognize result = %d," "the probability is %g " % (pre[0],prob[0][pre]))
    else:
        print("No checkpoint file found")
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM