1. 程式人生 > >Tensorflow學習筆記:變數作用域、模型的載入與儲存、執行緒與佇列實現多執行緒讀取樣本

Tensorflow學習筆記:變數作用域、模型的載入與儲存、執行緒與佇列實現多執行緒讀取樣本

# tensorflow變數作用域
    用上下文語句規定作用域
    with tf.variable_scope("作用域_name")
        ......
    這樣可以使得變數在tensorboard中的顯示更加簡介

# 增加變數顯示
    1、用tf.summary.scalar(name="",tensor)    收集單個值(0維的值)
       用tf.summary.histogram(name="",tensor)  收集高維度的值
        2、合併變數並寫入event檔案
    merged = tf.summary.merge_all()
    summary = sess.run(merged)    #每次迭代都需要執行
    FileWriter.add_summary(summary,i)    #i代表第幾次的值

#模型的儲存與載入
    儲存為checkpoint檔案
    tf.train.Saver(var_list=None,    #用字典或列表傳遞要儲存和還原的變數
            max_to_keep    #保留最近的幾個檔案的最大數目
            )
    返回一個例項saver
    saver.save(sess,'path+name')
    saver.restore(sess,'path+name')
    示例:

saver = tf.train.Saver(var_list=(w,b),max_to_keep = 3)
    with tf.Session() as sess:
        saver.save(sess,'./train_data/model')


    Saver不是op,不用run

    如果需要載入模型,在訓練開始之前進行載入
    if os.path.exists("checkpoint")    #判斷儲存時建立的checkpoint是否存在
    saver.restore(sess,'./trained_data/model')

#執行緒佇列與IO操作
#佇列
    tf.FIFOQueue()佇列,先進先出
    tf.RandomShuffleQueue()隨機出佇列
#主要用到FIFOQueue
    FIFOQueue(capacity,    #最大數量
        dtype,    #資料型別
        name = None)
    方法:
    dequeue()出佇列
    enqueue(vals)進佇列
    enqueue_many(vals)     #vals為包含多組資料的列表或元組
    size()    返回大小

#佇列管理器(可以建立執行緒)
    tf.train.QueueRunner(queue,enqueue_ops = None)
    其中queue是列表物件例項,en    queue_ops = [enqueue_op,dequque_op,...],指定執行緒做什麼操作,[]*2代表指定兩個執行緒
    create_threads(sess,    
            coord=None    #執行緒協調器,後面再說
            start=False    #為True直接啟動執行緒,為False必須呼叫start()來啟動
            )         #執行執行緒進行操作
    返回一個執行緒的例項

    示例:
    

#佇列中加入數,每次取出後加1放入佇列
    import tensorflow as tf
    import os

    #定義佇列
    Q = tf.FIFOQueue(100,tf.float32)

    #定義變數
    var = tf.Variable(0.0,dtype = tf.float32)

    #取出變數自增後放入佇列
    data = tf.assign_add(var,tf.constant(1.0))

    #data放入佇列Q
    enq_op = Q.enqueue(data)

    Q_thread_op = tf.train.QueueRunner(Q,enqueue_ops = [enq_op])

    init_op = tf.global_variables_initializer()

    with tf.Session() as sess:
        sess.run(init_op)
        threads = Q_thread_op.create_threads(sess, start = True)

        for i in range(300):
            print(sess.run(Q.dequeue()),Q.size().eval())

#執行緒協調器tf.train.Coordinator()
    示例:加入執行緒協調器
    

import tensorflow as tf
    import os

    #定義佇列
    Q = tf.FIFOQueue(100,tf.float32)

    #定義變數
    var = tf.Variable(0.0,dtype = tf.float32)

    #取出變數自增後放入佇列
    data = tf.assign_add(var,tf.constant(1.0))

    #data放入佇列Q
    enq_op = Q.enqueue(data)

    Q_thread_op = tf.train.QueueRunner(Q,enqueue_ops = [enq_op])

    init_op = tf.global_variables_initializer()

    with tf.Session() as sess:
        sess.run(init_op)
        coord = tf.train.Coordinator()    #建立執行緒協調器
        threads = Q_thread_op.create_threads(sess,coord = coord, start = True)    #用執行緒協調器開啟執行緒
        for i in range(300):
            print(sess.run(Q.dequeue()),Q.size().eval())
        coord.request_stop()    #請求執行緒結束
        coord.join(threads)    #回收執行緒

#檔案讀取
    1、構造檔案讀取佇列
    tf.train.string_input_producer(string_tensor, num_epochs=None, shuffle=True, capacity=32)
    string_tensor:一維字串張量,儲存要讀取的樣本檔案的字串
    num_epochs:讀取迴圈次數,預設無限次
    shuffle:隨機選擇檔案讀取
    capacity:檔案讀取佇列的容量

    2、檔案閱讀器------讀取佇列內容
    tf.TextLineReader
        閱讀文字檔案(.txt,.CSV等)格式,預設按行讀取
        return:讀取器例項
    tf.FixedLengthRecordReader(record_bytes)
        閱讀二進位制檔案,引數為要讀取的位元組數
        return 讀取器例項
    tf.TFRecordReader()(後面再說)
    
    閱讀器都有一個共同的方法:read(file_queue)    
    return :一個張量,(檔名字,value讀取的內容(行,位元組))    

    3、檔案內容解碼器
    tf.decode_csv(    records,    #即上面的value 
            record_defaults = None    #所返回張量的型別
            field_delim = None #預設分隔符
            name = None)
    tf.decode_raw(bytes,out_type,little_endian = None)
        讀取二進位制檔案

#批處理:在解碼器解碼之後進行,系統將執行多遍讀取操作

    read_result_batch = tf.train.batch(read_result,    #解碼器的解碼結果
                        batch_size = 5,    #每個batch的數量,該大小跟佇列大小,資料個數無關,一般資料可以迴圈讀取,如果batch_size很大,則會重複取
                        num_threads = 1,#利用多少個執行緒處理
                        capacity = 5)    #佇列的大小,沒有關係,只是定義佇列的大小

#例項:讀取CSV檔案
    1、找到檔案構造樣本檔案的目錄+檔名
    2、構造檔案佇列
    3、構造閱讀器,讀取檔案(一行)
    4、構造解碼器,解碼內容
    5、批處理
    

def csvread(filelist):
    
    #1、構造檔案字串列表
    file_queue = tf.train.string_input_producer(filelist)

    #2、構造閱讀器讀取資料
    reader = tf.TextLineReader()
    key, value = reader.read(file_queue)

    #3、構造解碼器進行解碼
    recoders = [[1],[1]]
    read_result = tf.decode_csv(value, record_defaults = recoders)

    #4、批量讀取
    read_result_batch = tf.train.batch(read_result, batch_size = 5, num_threads = 1, capacity = 7)

    return read_result_batch


import tensorflow as tf
import os

if __name__ == "__main__":

    #用os模組查詢存放資料檔案的目錄下是否真的存在資料檔案
    dir_file_list = os.listdir("C:\\Users\\xie\\csv_data")

    #構造資料檔案路徑+檔名的字串列表
    for i in range(len(dir_file_list)):
        dir_file_list[i] = "C:\\Users\\xie\\csv_data\\" + dir_file_list[i]

    #呼叫函式獲得樣本batch
    result_batch = csvread(dir_file_list)

    with tf.Session() as sess:

        #定義執行緒管理器
        coord = tf.train.Coordinator()

        #用tf.train.start_queue_runners方法開啟queue的子執行緒檔案讀取,其機制是:
        #所有關於queue讀取的操作都被放在一個集合內部,當呼叫該函式時,所有的讀取子程序啟動,進行讀取
        thread = tf.train.start_queue_runners(sess, coord = coord)

        print(sess.run(result_batch))

        coord.request_stop()
        coord.join(thread)