TensorFlow基礎(二)

  • 2019 年 10 月 6 日
  • 筆記

前言

在pandas中也可以讀取數據,但是他存在的問題(僅僅以我們學過的角度來看)有:

1、一次讀取數據,消耗內存

2、一次性進行訓練

而在tensorflow中提供多線程,並行的執行任務,隊列(數據的共享),文件(tfrecords)的方式讀取數據。來提高解析速度。

你可能聽過在Python中沒有真正的多線程,原因是python存在GIL鎖。但是你可能還不知道在numpy中釋放了GIL鎖,而機器學習庫都是基於numpy的。

因此在學習tensorflow讀取數據欠還要了解隊列和線程。

隊列和線程(tensorflow中)

隊列

在tensorflow中對隊列進行了封裝:

tf.FIFOQueue(capacity,dtypes,name='info_queue')

# 前進先出隊列,按順序出隊列

capacity:整數,可能存儲此隊列的元素上限

簡單隊列Demo:

# 1、定義隊列  # 最多放5個數據,類型為float32  Q = tf.FIFOQueue(5,tf.float32)  # 放入一些數據,這裡存放列表寫成[[1,2,3,4,5],],防止認為是張量  e_many = Q.enqueue_many([[1,2,3,4,5],])  # 取出數據,乘以2  out_q = Q.dequeue()  data = out_q*2  # 再放入隊列  en_q = Q.enqueue(data)  with tf.Session() as sess:      # 初始化隊列      sess.run(e_many)      # 處理數據100次,這裡只用運行en_q,就會運行      # 去除數據,*2,放入隊列這三步操作,Tensorflow中操作具有依賴性      # 運行en_q,en_q依賴data,data依賴out_q      for i in range(100):          sess.run(en_q)      # 取數據      for i in range(Q.size().eval()):          print(sess.run(out_q))  

tf.RandomShuffleQueue:隨機出隊列

用到的時候再說。

線程

叫做隊列管理器,但是是創建線程的作用。

tf.train.QueueRunner(queque,enqueue_ops=None)

queue: 一個隊列

enqueue_ops:添加線程的隊列操作列表,[]*2代表創建2個線程,[]中寫操作

在sess中啟動線程

create_threads(sess,coord=None,start=False)

coord:線程協調器,當結束後回收子線程

start:True啟動線程,如果為False,還需要條用start()啟動線程。

Demo實例:

# 模擬實現子線程讀取數據,而主線程進行訓練,二者並行    # 定義一個隊列  Q = tf.FIFOQueue(1000,tf.float32)  # 定義子線程需要做的事情 循環加1 放入隊列  var = tf.Variable(0.0)  # 每次加1,如果不使用assign_add,每次都是0+1會一直是1  data = tf.assign_add(var,1.0)  # 放入隊列  en_q = Q.enqueue(data)  # 定義隊列管理器op,指定線程做什麼  qr = tf.train.QueueRunner(Q,enqueue_ops=[en_q]*2)  # 初始化變量op  init_op = tf.global_variables_initializer()    with tf.Session() as sess:      # 初始化變量      sess.run(init_op)      # 開啟線程協調器,當主線程結束回收子線程      coord = tf.train.Coordinator()      # 開啟子線程      threads = qr.create_threads(sess,coord=coord,start=True)      # 主線程讀取數據,訓練      for i in range(1000):          print(sess.run(Q.dequeue()))      # 回收子線程      coord.request_stop()      coord.join(threads)  

注意:其實以上過程以後都不需要自己寫。但是要了解。

文件讀取

文件讀取流程

1、構建一個文件隊列

2、讀取隊列內容

3、解碼

4、批處理

文件讀取api介紹

構造文件隊列

tf.train.string_input_producer(string_tensor)

string_tensor:含有文件名的1階張量

讀取文件內容(不同文件,讀取api不同)

文本,csv文件讀取:tf.TextLineReader,按行讀取

二進制文件:tf.FixedLengthRecordReader(record_bytes)

record_bytes:整型,指定每次讀取的位元組數

Tfrecords文件:tf.TFrecordReader

解碼

解碼csv文件:tf.decode_csv(records,record_defaults=None,dileld_delim=None)

將csv轉換成張量,和tf.TextLineReader搭配使用。

records:讀取的內容

dileld_delim:分隔符,默認為,

record_defaults:張量類型,設置缺少默認值.

解碼二進制:tf.decode_raw()

csv文件讀取Demo

def csvread(filelist):      # 構造文件隊列,返回的是一個隊列      file_queue = tf.train.string_input_producer(filelist,shuffle=False)      # 構造csv閱讀器讀取隊列數據,默認按照行讀取      reader = tf.TextLineReader()      # 得到讀取的數據key是讀取的文件名,value是讀取的數據      key, value = reader.read(file_queue)      # 解碼      # record_defaults指定讀取的文件每一列的類型      # 比如csv的第一列數據是1,2,3,第二列為python,java,C      # 也就是第一列為float,第二列為string      # record_defaults就是指定每列的類型,和默認值      # 1.0為float,說明數據第一列為float類型,默認值是1      # ,""為string類型,說明第二列為string類型,默認值是None      records = [[1.0],["None"]]      # 返回為每個列的每個值      rad_num,label = tf.decode_csv(value,record_defaults=records)      # 讀取多個數據,批處理      # 參數一:批處理的值      # 參數二:每批次讀取多少數據      # 參數三:開啟多少線程      # 參數四:隊列的大小      rad_num_batch,label_batch = tf.train.batch([rad_num,label],batch_size=9,num_threads=1,capacity=9)      return rad_num_batch,label_batch    if __name__ == "__main__":      # 自己創建csv文件,列數不必太多      # 將文件放入列表      import os      # 去除警告消息      os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'      # os.listdir:返回該目錄下文件名的列表      file_name = os.listdir("./csvdata/")      # 拼接路徑      filelist = [os.path.join("./csvdata",file) for file in file_name]      rad_num_batch,label_batch = csvread(filelist)      # 開啟會話      with tf.Session() as sess:          #  定義線程協調器          coord = tf.train.Coordinator()          # 開啟讀取文件的線程,不用上面那樣麻煩了          threads = tf.train.start_queue_runners(sess, coord=coord)          # 打印讀取的內容          print(sess.run([rad_num_batch,label_batch]))          # 回收線程          coord.request_stop()          coord.join(threads)  

讀取圖像和二進制下篇見。