神經網絡實踐-MNIST數據集上搭建全連接網絡

本節目標:搭建神經網絡,在 mnist 數據集上訓練模型,輸出手寫數字識別準確率。

(內心OS:太難了太難了!!!)

——————————————————————————————————————————————不可視的境界線

mnist 數據集:包含 7 萬張黑底白字手寫數字圖片,其中 55000 張爲訓練集, 5000 張爲驗證集,10000 張爲測試集。每張圖片大小爲 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。

使用 input_data 模塊中的 read_data_sets()函數加載 mnist 數據集:
 

 from tensorflow.examples.tutorials.mnist import input_data 

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


在 read_data_sets()函數中有兩個參數,第一個參數表示數據集存放路徑,第二個參數表示數據集的存取形式。當第二個參數爲 Ture 時,表示以獨熱碼形式存取數據集。read_data_sets()函數運行時,會檢查指定路徑內是否已經有數據集,若指定路徑中沒有數據集,則自動下載,並將mnist數據集分爲訓練集train、 驗證集 validation 和測試集 test 存放。在終端顯示如下內容:

Extracting ./data/train-images-idx3-ubyte.gz 

Extracting ./data/train-labels-idx1-ubyte.gz
Extracting ./data/tl0k-images-idx3-ubyte.gz
Extracting ./data/ tl0k-labels-idx1-ubyte.gz


返回 mnist 數據集中訓練集 train、驗證集 validation 和測試集 test 樣本數:
在 Tensorflow 中用以下函數返回子集樣本數:

①返回訓練集 train 樣本數
print “train data size:”,mnist.train.mun_examples
輸出結果:train data size:55000
②返回驗證集 validation 樣本數
print “validation data size:”,mnist.validation.mun_examples
輸出結果:validation data size:5000
③返回測試集 test 樣本數
print “test data size:”,mnist.test.mun_examples
輸出結果:test data size:10000


使用 train.labels 函數返回 mnist 數據集標籤
例如:
在 mnist 數據集中,若想要查看訓練集中第 0 張圖片的標籤,則使用如下函數
mnist.train.labels[0]
輸出結果:array([0.,0.,0.,0.,0.,0.,1.,0.,0.,0])


使用 train.images 函數返回 mnist 數據集圖片像素值
例如:
在 mnist 數據集中,若想要查看訓練集中第 0 張圖片像素值,則使用如下函數
mnist.train.images[0]
輸出結果:array([0. ,0. ,0. ,0. ,0. ,0. ,0. ,0. ,0. ,… … …])


使用 mnist.train.next_batch()函數將數據輸入神經網絡
例如:

BATCH_SIZE = 200
xs,ys = mnist.train.next_batch(BATCH_SIZE)
print “xs shape:”,xs.shape
print “ys shape:”,ys.shape

輸出結果:xs.shape(200,784)
輸出結果:ys.shape(200,10)
其中,mnist.train.next_batch()函數包含一個參數 BATCH_SIZE,表示隨機從訓練集中抽取 BATCH_SIZE 個樣本輸入神經網絡,並將樣本的像素值和標籤分別賦給 xs 和 ys。在本例中,BATCH_SIZE 設置爲 200,表示一次將 200 個樣本的像素值和標籤分別賦值給 xs 和 ys,故 xs 的形狀爲(200,784),對應的 ys 的形狀爲(200,10)。

實現“Mnist 數據集手寫數字識別”的常用函數:
①tf.get_collection(“”)函數表示從 collection 集合中取出全部變量生成一個列表。
②tf.add( )函數表示將參數列表中對應元素相加。

例如:

x=tf.constant([[1,2],[1,2]])
y=tf.constant([[1,1],[1,2]])
z=tf.add(x,y)
print z

輸出結果:[[2,3],[2,4]]
③tf.cast(x,dtype)函數表示將參數 x 轉換爲指定數據類型。
例如:

A = tf.convert_to_tensor(np.array([[1,1,2,4], [3,4,8,5]]))
print A.dtype
b = tf.cast(A, tf.float32)
print b.dtype

結果輸出:
<dtype: 'int64'>
<dtype: 'float32'>
從輸出結果看出,是將矩陣 A 由整數型變爲 32 位浮點型。
④tf.equal( )函數表示對比兩個矩陣或者向量的元素。若對應元素相等,則返回 True;若對應元素不相等,則返回 False。
例如:

A = [[1,3,4,5,6]]
B = [[1,3,4,3,2]]
with tf.Session( ) as sess:
    print(sess.run(tf.equal(A, B)))

輸出結果:[[ True True True False False]]
在矩陣 A 和 B 中,第 1、2、3 個元素相等,第 4、5 個元素不等,故輸出結果中,第 1、2、3 個元素取值爲 True,第 4、5 個元素取值爲 False。
⑤tf.reduce_mean(x,axis)函數表示求取矩陣或張量指定維度的平均值。若不指定第二個參數,則在所有元素中取平均值;若指定第二個參數爲 0,則在第一維元素上取平均值,即每一列求平均值;若指定第二個參數爲 1,則在第二維元素上取平均值,即每一行求平均值。
例如:

x = [[1., 1.]
       [2., 2.]]
print(tf.reduce_mean(x))
#輸出結果:1.5
print(tf.reduce_mean(x, 0))
#輸出結果:[1.5, 1.5]
print(tf.reduce_mean(x, 1))
#輸出結果:[1., 1.]


⑥tf.argmax(x,axis)函數表示返回指定維度 axis 下,參數 x 中最大值索引號。
例如:
在 tf.argmax([1,0,0],1)函數中,axis 爲 1,參數 x 爲[1,0,0],表示在參數 x的第一個維度取最大值對應的索引號,故返回 0。
⑦os.path.join()函數表示把參數字符串按照路徑命名規則拼接。
例如:

import os
os.path.join('/hello/','good/boy/','doiido')
#輸出結果:'/hello/good/boy/doiido'

⑧字符串.split( )函數表示按照指定“拆分符”對字符串拆分,返回拆分列表。
例如:
'./model/mnist_model-1001'.split('/')[-1].split('-')[-1]
在該例子中,共進行兩次拆分。第一個拆分符爲‘/’,返回拆分列表,並提取列表中索引爲-1 的元素即倒數第一個元素;第二個拆分符爲‘-’,返回拆分列表,並提取列表中索引爲-1 的元素即倒數第一個元素,故函數返回值爲 1001。
⑨tf.Graph( ).as_default( )函數表示將當前圖設置成爲默認圖,並返回一個上下文管理器。該函數一般與 with 關鍵字搭配使用,應用於將已經定義好的神經網絡在計算圖中復現。
例如:
with tf.Graph().as_default() as g,表示將在 Graph()內定義的節點加入到計算圖 g 中。

 

神經網絡模型的保存
在反向傳播過程中,一般會間隔一定輪數保存一次神經網絡模型,併產生三個文件(保存當前圖結構的.meta 文件、保存當前參數名的.index 文件、保存當前參數的.data 文件),在 Tensorflow 中如下表示:

saver = tf.train.Saver() 
with tf.Session() as sess: 
    for i in range(STEPS):
         if i % 輪數 == 0:
             saver.save(sess, os.path.join(MODEL_SAVE_PATH,                 
                         MODEL_NAME),global_step=global_step)

其中,tf.train.Saver()用來實例化 saver 對象。上述代碼表示,神經網絡每循環規定的輪數,將神經網絡模型中所有的參數等信息保存到指定的路徑中,並在存放網絡模型的文件夾名稱中註明保存模型時的訓練輪數。
 

神經網絡模型的加載
在測試網絡效果時,需要將訓練好的神經網絡模型加載,在 Tensorflow 中這樣表示:

with tf.Session() as sess:
    ckpt = tf.train.get_checkpoint_state(存儲路徑)
    if ckpt and ckpt.model_checkpoint_path:
        saver.restore(sess, ckpt.model_checkpoint_path)

在 with 結構中進行加載保存的神經網絡模型,若 ckpt 和保存的模型在指定路徑中存在,則將保存的神經網絡模型加載到當前會話中。

加載模型中參數的滑動平均值
在保存模型時,若模型中採用滑動平均,則參數的滑動平均值會保存在相應文件中。通過實例化 saver 對象,實現參數滑動平均值的加載,在 Tensorflow 中如下表示:

ema = tf.train.ExponentialMovingAverage(滑動平均基數)
ema_restore = ema.variables_to_restore()
saver = tf.train.Saver(ema_restore)

神經網絡模型準確率評估方法
在網絡評估時,一般通過計算在一組數據上的識別準確率,評估神經網絡的效果。在 Tensorflow 中這樣表示:

correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

在上述中,y 表示在一組數據(即 batch_size 個數據)上神經網絡模型的預測結果,y 的形狀爲[batch_size,10],每一行表示一張圖片的識別結果。通過tf.argmax()函數取出每張圖片對應向量中最大值元素對應的索引值,組成長度爲輸入數據 batch_size 個的一維數組。通過 tf.equal()函數判斷預測結果張量和實際標籤張量的每個維度是否相等,若相等則返回 True,不相等則返回 False。通過 tf.cast() 函數將得到的布爾型數值轉化爲實數型,再通過tf.reduce_mean()函數求平均值,最終得到神經網絡模型在本組數據上的準確率。


神經網絡八股包括前向傳播過程、反向傳播過程、反向傳播過程中用到的正則化、指數衰減學習率、滑動平均方法的設置、以及測試模塊。
前向傳播過程(forward.py)
前向傳播過程完成神經網絡的搭建,結構如下:

def forward(x, regularizer):
    w=
    b=
    y=
    return y
def get_weight(shape, regularizer):
def get_bias(shape):

前向傳播過程中,需要定義神經網絡中的參數 w 和偏置 b,定義由輸入到輸出的網絡結構。通過定義函數 get_weight()實現對參數 w 的設置,包括參數 w 的形狀和是否正則化的標誌。同樣,通過定義函數 get_bias()實現對偏置 b 的設置。
反向傳播過程(backword.py)
反向傳播過程完成網絡參數的訓練,結構如下:

def backward( mnist ):
x = tf.placeholder(dtype, shape )
y_ = tf.placeholder(dtype, shape )
#定義前向傳播函數
y = forward( )
global_step =
loss =
train_step = tf.train.GradientDescentOptimizer(learning_rate).
            minimize(loss, global_step=global_step)
#實例化 saver 對象
saver = tf.train.Saver()
with tf.Session() as sess:
    #初始化所有模型參數
tf.initialize_all_variables().run()
#訓練模型
for i in range(STEPS):
    sess.run(train_step, feed_dict={x: , y_: })
    if i % 輪數 == 0:
        print
        saver.save( )


反向傳播過程中,用 tf.placeholder(dtype, shape)函數實現訓練樣本 x 和樣本標籤 y_佔位,函數參數 dtype 表示數據的類型,shape 表示數據的形狀;y 表示定義的前向傳播函數 forward;loss 表示定義的損失函數,一般爲預測值與樣本標籤的交叉熵(或均方誤差)與正則化損失之和;train_step 表示利用優化算法對模型參數進行優化,常用優化算法 GradientDescentOptimizer 、AdamOptimizer、MomentumOptimizer 算法,在上述代碼中使用的 GradientDescentOptimizer 優化算法。接着實例化 saver 對象,其中利用 tf.initialize_all_variables().run()函數實例化所有參數模型,利用 sess.run( )函數實現模型的訓練優化過程,並每間隔一定輪數保存一次模型。

正則化、指數衰減學習率、滑動平均方法的設置
①正則化項 regularization
當在前向傳播過程中即 forward.py 文件中,設置正則化參數 regularization 爲1 時,則表明在反向傳播過程中優化模型參數時,需要在損失函數中加入正則化項。
結構如下:
首先,需要在前向傳播過程即 forward.py 文件中加入
if regularizer != None: tf.add_to_collection('losses',
tf.contrib.layers.l2_regularizer(regularizer)(w))
其次,需要在反向傳播過程即 backword.py 文件中加入
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'))

其中,tf.nn.sparse_softmax_cross_entropy_with_logits()表示 softmax()函數與交叉熵一起使用。
②指數衰減學習率
在訓練模型時,使用指數衰減學習率可以使模型在訓練的前期快速收斂接近較優解,又可以保證模型在訓練後期不會有太大波動。運用指數衰減學習率,需要在反向傳播過程即 backword.py 文件中加入:

learning_rate = tf.train.exponential_decay(
LEARNING_RATE_BASE,
global_step,
LEARNING_RATE_STEP, LEARNING_RATE_DECAY,
staircase=True)

③滑動平均
在模型訓練時引入滑動平均可以使模型在測試數據上表現的更加健壯。
需要在反向傳播過程即 backword.py 文件中加入:

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')

測試過程(test.py)
當神經網絡模型訓練完成後,便可用於測試數據集,驗證神經網絡的性能。結構如下:
首先,制定模型測試函數 test()

def test( mnist ):
    with tf.Graph( ).as_default( ) as g:
        #給 x y_佔位
        x = tf.placeholder(dtype,shape)
        y_ = tf.placeholder(dtype,shape)
    #前向傳播得到預測結果 y
    y = mnist_forward.forward(x, None) #前向傳播得到 y
     #實例化可還原滑動平均的 saver
     ema = tf.train.ExponentialMovingAverage(滑動衰減率)
     ema_restore = ema.variables_to_restore()
     saver = tf.train.Saver(ema_restore)
    #計算正確率
    correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,
                        1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction,
                tf.float32))
    while True:
        with tf.Session() as sess:
            #加載訓練好的模型
            ckpt = tf.train.get_checkpoint_state(存儲路徑)
            #如果已有 ckpt 模型則恢復
            if ckpt and ckpt.model_checkpoint_path:
            #恢復會話
            saver.restore(sess, ckpt.model_checkpoint_path)
            #恢復輪數
            global_ste = ckpt.model_checkpoint_path.split
                        ('/')[-1].split('-')[-1]
            #計算準確率
            accuracy_score = sess.run(accuracy, feed_dict=
                            {x:測試數據, y_:測試數據標籤 })
            # 打印提示
            print("After %s training step(s), test accuracy=
                   %g" % (global_step, accuracy_score))
        #如果沒有模型
        else:
            print('No checkpoint file found') #模型不存在提示
            return
#其次,制定 main()函數
def main():
    #加載測試數據集
    mnist = input_data.read_data_sets("./data/", one_hot=True)
    #調用定義好的測試函數 test()
    test(mnist)
if __name__ == '__main__':
main()

通過對測試數據的預測得到準確率,從而判斷出訓練出的神經網絡模型的性能好壞。當準確率低時,可能原因有模型需要改進,或者是訓練數據量太少導致過擬合。


實現手寫體 mnist 數據集的識別任務,共分爲三個模塊文件,分別是描述網絡結構的前向傳播過程文件(mnist_forward.py)、描述網絡參數優化方法的反向傳播過程文件(mnist_backward.py )、驗證模型準確率的測試過程文件(mnist_test.py)。

前向傳播過程文件(mnist_forward.py)
在前向傳播過程中,需要定義網絡模型輸入層個數、隱藏層節點數、輸出層個數,定義網絡參數 w、偏置 b,定義由輸入到輸出的神經網絡架構。實現手寫體 mnist 數據集的識別任務前向傳播過程如下:

#coding:utf-8
#1前向傳播過程
import tensorflow as tf
 
#網絡輸入節點爲784個(代表每張輸入圖片的像素個數)
INPUT_NODE = 784
#輸出節點爲10個(表示輸出爲數字0-9的十分類)
OUTPUT_NODE = 10
#隱藏層節點500個
LAYER1_NODE = 500
 
 
def get_weight(shape, regularizer):
	#參數滿足截斷正態分佈,並使用正則化,
    w = tf.Variable(tf.truncated_normal(shape,stddev=0.1))
    #w = tf.Variable(tf.random_normal(shape,stddev=0.1))
	#將每個參數的正則化損失加到總損失中
    if regularizer != None: tf.add_to_collection('losses', tf.contrib.layers.l2_regularizer(regularizer)(w))
    return w
 
 
def get_bias(shape):  
	#初始化的一維數組,初始化值爲全 0
    b = tf.Variable(tf.zeros(shape))  
    return b
	
def forward(x, regularizer):
	#由輸入層到隱藏層的參數w1形狀爲[784,500]
    w1 = get_weight([INPUT_NODE, LAYER1_NODE], regularizer)
	#由輸入層到隱藏的偏置b1形狀爲長度500的一維數組,
    b1 = get_bias([LAYER1_NODE])
	#前向傳播結構第一層爲輸入 x與參數 w1矩陣相乘加上偏置 b1 ,再經過relu函數 ,得到隱藏層輸出 y1。
    y1 = tf.nn.relu(tf.matmul(x, w1) + b1)
    #由隱藏層到輸出層的參數w2形狀爲[500,10]
    w2 = get_weight([LAYER1_NODE, OUTPUT_NODE], regularizer)
	#由隱藏層到輸出的偏置b2形狀爲長度10的一維數組
    b2 = get_bias([OUTPUT_NODE])
	#前向傳播結構第二層爲隱藏輸出 y1與參 數 w2 矩陣相乘加上偏置 矩陣相乘加上偏置 b2,得到輸出 y。
	#由於輸出 。由於輸出 y要經過softmax oftmax 函數,使其符合概率分佈,故輸出y不經過 relu函數
    y = tf.matmul(y1, w2) + b2
    return y


由上述代碼可知,在前向傳播過程中,規定網絡輸入結點爲 784 個(代表每張輸入圖片的像素個數),隱藏層節點 500 個,輸出節點 10 個(表示輸出爲數字 0-9的十分類)。由輸入層到隱藏層的參數 w1 形狀爲[784,500],由隱藏層到輸出層的參數 w2 形狀爲[500,10],參數滿足截斷正態分佈,並使用正則化,將每個參11數的正則化損失加到總損失中。由輸入層到隱藏層的偏置 b1 形狀爲長度爲 500的一維數組,由隱藏層到輸出層的偏置 b2 形狀爲長度爲 10 的一維數組,初始化值爲全 0。前向傳播結構第一層爲輸入 x 與參數 w1 矩陣相乘加上偏置 b1,再經過 relu 函數,得到隱藏層輸出 y1。前向傳播結構第二層爲隱藏層輸出 y1 與參數 w2 矩陣相乘加上偏置 b2,得到輸出 y。由於輸出 y 要經過 softmax 函數,使其符合概率分佈,故輸出 y 不經過 relu 函數。


反向傳播過程文件(mnist_backward.py)
反向傳播過程實現利用訓練數據集對神經網絡模型訓練,通過降低損失函數值,實現網絡模型參數的優化,從而得到準確率高且泛化能力強的神經網絡模型。實現手寫體 mnist 數據集的識別任務反向傳播過程如下:

#coding:utf-8
#2反向傳播過程
#引入tensorflow、input_data、前向傳播mnist_forward和os模塊
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_NAME="mnist_model"
 
 
def backward(mnist):
    #用placeholder給訓練數據x和標籤y_佔位
    x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
    y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
    #調用mnist_forward文件中的前向傳播過程forword()函數,並設置正則化,計算訓練數據集上的預測結果y
	y = mnist_forward.forward(x, REGULARIZER)
	#當前計算輪數計數器賦值,設定爲不可訓練類型
    global_step = tf.Variable(0, trainable=False)
 
    #調用包含所有參數正則化損失的損失函數loss
    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'))
    #設定指數衰減學習率learning_rate
    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)
    train_step = tf.train.MomentumOptimizer(learning_rate,0.9).minimize(loss, global_step=global_step)
    #train_step = tf.train.AdamOptimizer(learning_rate).minimize(loss, global_step=global_step)
    #定義參數的滑動平均
    ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
    ema_op = ema.apply(tf.trainable_variables())
	#實例化可還原滑動平均的saver 
	#在模型訓練時引入滑動平均可以使模型在測試數據上表現的更加健壯
    with tf.control_dependencies([train_step,ema_op]):
        train_op = tf.no_op(name='train')
 
    saver = tf.train.Saver()
 
    with tf.Session() as sess:
		#所有參數初始化
        init_op = tf.global_variables_initializer()
        sess.run(init_op)
        #每次喂入batch_size組(即200組)訓練數據和對應標籤,循環迭代steps輪
        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:
                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():
	#讀入mnist
    mnist = input_data.read_data_sets("./data/", one_hot=True)
    #反向傳播
	backward(mnist)
 
if __name__ == '__main__':
    main()


由上述代碼可知,在反向傳播過程中,首先引入 tensorflow、input_data、前向傳播 mnist_forward 和 os 模塊,定義每輪喂入神經網絡的圖片數、初始學習率、學習率衰減率、正則化係數、訓練輪數、模型保存路徑以及模型保存名稱等相關信息。在反向傳播函數 backword 中,首先讀入 mnist,用 placeholder 給訓練數據 x 和標籤 y_佔位,調用 mnist_forward 文件中的前向傳播過程 forword()函數,並設置正則化,計算訓練數據集上的預測結果 y,並給當前計算輪數計數器賦值,設定爲不可訓練類型。接着,調用包含所有參數正則化損失的損失函數loss,並設定指數衰減學習率 learning_rate。然後,使用梯度衰減算法對模型優化,降低損失函數,並定義參數的滑動平均。最後,在 with 結構中,實現所有參數初始化,每次喂入 batch_size 組(即 200 組)訓練數據和對應標籤,循環迭代 steps 輪,並每隔 1000 輪打印出一次損失函數值信息,並將當前會話加載到指定路徑。最後,通過主函數 main(),加載指定路徑下的訓練數據集,並調用規定的 backward()函數訓練模型。


測試過程文件(mnist_test.py)
當訓練完模型後,給神經網絡模型輸入測試集驗證網絡的準確性和泛化性。注意,所用的測試集和訓練集是相互獨立的。實現手寫體 mnist 數據集的識別任務測試傳播過程如下:

#coding:utf-8
#驗證網絡的準確性和泛化性
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward
import mnist_backward
#程序5秒的循環間隔時間
TEST_INTERVAL_SECS = 5
 
def test(mnist):
	#利用tf.Graph()復現之前定義的計算圖
    with tf.Graph().as_default() as g:
		#利用placeholder給訓練數據x和標籤y_佔位
        x = tf.placeholder(tf.float32, [None, mnist_forward.INPUT_NODE])
        y_ = tf.placeholder(tf.float32, [None, mnist_forward.OUTPUT_NODE])
		#調用mnist_forward文件中的前向傳播過程forword()函數
        y = mnist_forward.forward(x, None)
        #實例化具有滑動平均的saver對象,從而在會話被加載時模型中的所有參數被賦值爲各自的滑動平均值,增強模型的穩定性
        ema = tf.train.ExponentialMovingAverage(mnist_backward.MOVING_AVERAGE_DECAY)
        ema_restore = ema.variables_to_restore()
        saver = tf.train.Saver(ema_restore)
		#計算模型在測試集上的準確率
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_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)
                    global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
                    accuracy_score = sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})
                    print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))
				#若模型不存在,則打印出模型不存在的提示,從而test()函數完成
                else:
                    print('No checkpoint file found')
                    return
            time.sleep(TEST_INTERVAL_SECS)
 
def main():
	#加載指定路徑下的測試數據集
    mnist = input_data.read_data_sets("./data/", one_hot=True)
    test(mnist)
 
if __name__ == '__main__':
    main()

在上述代碼中,首先需要引入 time 模塊、tensorflow、input_data、前向傳播mnist_forward、反向傳播 mnist_backward 模塊和 os 模塊,並規定程序 5 秒的循環間隔時間。接着,定義測試函數 test(),讀入 mnist 數據集,利用 tf.Graph()復現之前定義的計算圖,利用 placeholder 給訓練數據 x 和標籤 y_佔位,調用mnist_forward 文件中的前向傳播過程 forword()函數,計算訓練數據集上的預測結果 y。接着,實例化具有滑動平均的 saver 對象,從而在會話被加載時模型中的所有參數被賦值爲各自的滑動平均值,增強模型的穩定性,然後計算模型在測試集上的準確率。在 with 結構中,加載指定路徑下的 ckpt,若模型存在,則加載出模型到當前對話,在測試數據集上進行準確率驗證,並打印出當前輪數下的準確率,若模型不存在,則打印出模型不存在的提示,從而 test()函數完成。通過主函數 main(),加載指定路徑下的測試數據集,並調用規定的 test 函數,進行模型在測試集上的準確率驗證。運行以上三個文件,可得到手寫體 mnist 數據集的識別任務的運行結果:

運行以上三個文件,可得到手寫體 mnist 數據集的識別任務的運行結果:

從終端顯示的運行結果可以看出,隨着訓練輪數的增加,網絡模型的損失函數值在不斷降低,並且在測試集上的準確率在不斷提升,有較好的泛化能力。修改mnist_forward.py中w和b的初始化方法、修改隱藏層節點個數和隱藏層層數,修改mnist_backward.py代碼中的超參數,找出最快提升準確度的“全連接網絡”解決方案。

#這一節內容好多啊,哭

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章