Tensorflow筆記:全連接網絡基礎

轉載於人工智能實踐:Tensorflow筆記

  • mnist 數據集:包含 7 萬張黑底白字手寫數字圖片,其中 55000 張爲訓練集,
    5000 張爲驗證集,10000 張爲測試集。每張圖片大小爲 28*28 像素,圖片中純黑色像素值爲 0,純白色像素值爲 1。數據集的標籤是長度爲 10 的一維數組,數組中每個元素索引號表示對應數字出現的概率。
  • 使用 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 數據集標籤

  • 使用 train.images 函數返回 mnist 數據集圖片像素值

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

  • 實現“Mnist 數據集手寫數字識別”的常用函數:
    ①tf.get_collection(“”)函數表示從 collection 集合中取出全部變量生成一個列表。
    ②tf.add( )函數表示將參數列表中對應元素相加。
    ③tf.cast(x,dtype)函數表示將參數 x 轉換爲指定數據類型。
    ④tf.equal( )函數表示對比兩個矩陣或者向量的元素。若對應元素相等,則返回 True;若對應元素不相等,則返回 False。
    ⑤tf.reduce_mean(x,axis)函數表示求取矩陣或張量指定維度的平均值。若不
    指定第二個參數,則在所有元素中取平均值;若指定第二個參數爲 0,則在第一維元素上取平均值,即每一列求平均值;若指定第二個參數爲 1,則在第二維元素上取平均值,即每一行求平均值。
    ⑥tf.argmax(x,axis)函數表示返回指定維度 axis 下,參數 x 中最大值索引號。
    ⑦os.path.join()函數表示把參數字符串按照路徑命名規則拼接。
    ⑧字符串.split( )函數表示按照指定“拆分符”對字符串拆分,返回拆分列表。
    ⑨tf.Graph( ).as_default( )函數表示將當前圖設置成爲默認圖,並返回一個上下文管理器。該函數一般與 with 關鍵字搭配使用,應用於將已經定義好的神經網絡在計算圖中復現。

  • 神經網絡模型的保存
    在反向傳播過程中,一般會間隔一定輪數保存一次神經網絡模型,併產生三個文件(保存當前圖結構的.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()函數求平均值,最終得到神經網絡模型在本組數據上的準確率。

  • 神經網絡八股:前向傳播過程、反向傳播過程、反向傳播過程中用到的正則化、指數衰減學習率、滑動平均方法的設置、以及測試模塊。

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

#conding:utf-8

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去除警告

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as  plt

gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333) #分配GPU使用防止GPU溢出
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))


# 1前向傳播過程
# 網絡輸入節點爲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],參數滿足截斷正態分佈,並使用正則化,將每個參數的正則化損失加到總損失中。由輸入層到隱藏層的偏置 b1 形狀爲長度爲 500的一維數組,由隱藏層到輸出層的偏置 b2 形狀爲長度爲 10 的一維數組,初始化值爲全 0。前向傳播結構第一層爲輸入 x 與參數 w1 矩陣相乘加上偏置 b1,再經過 relu 函數,得到隱藏層輸出 y1。前向傳播結構第二層爲隱藏層輸出 y1 與參數 w2 矩陣相乘加上偏置 b2,得到輸出 y。由於輸出 y 要經過softmax 函數,使其符合概率分佈,故輸出 y 不經過 relu 函數。

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

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去除警告

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as  plt

gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333) #分配GPU使用防止GPU溢出
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))


# 2反向傳播過程
# 引入input_data、前向傳播mnist_forward
from tensorflow.examples.tutorials.mnist import input_data
import mnist_forward

# 每輪喂入神經網絡的圖片數
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 數據集的識別任務測試傳播過程如下:
#conding:utf-8

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #去除警告

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
import matplotlib.pyplot as  plt

gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.333) #分配GPU使用防止GPU溢出
sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options))


# 驗證網絡的準確性和泛化性
import time
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 函數,進行模型在測試集上的準確率驗證。

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