Hike News
Hike News

深度學習-tensorflow基礎-讀取數據-隊列與線程

Introduction

在訓練model時最重要的就是數據,數據通常儲存於文件當中,早期在機器學習章程,我們使用pandas讀取數據
但在tensorflow中,提供的各種優化的方式來讀取數據

  • 在計算爭分奪秒的時候,需要去提高IO讀取的速度?
    • 計算(CPU)操作 相比 IO(硬碟讀取)操作 快非常多
    • 如果利用IO操作將1G甚至2G文件一次讀取到記憶體中
      • 內存消耗嚴重
      • 一次性讀取後,在一次性訓練,嚴重影響效率
      • 讀取的速度太慢,訓練的時間嚴重被延後

tensorflow優化文件讀取

  • tensorflow提供多線程讀取的機制
    • 在tensorflow當中的多線程是真正的多線程( 並行(非併發) 的執行任務)
  • 提供隊列(Queue)機制
  • 提供專屬的文件格式
    • tfrecords(非一般文件格式csv或圖片格式png,jpeg等)
      • 提高讀取速度
      • 提高解析文件速度

解決一次性讀取數據的問題

  • 使用多線程開啟多任務:創建並開啟子線程讀取數據
  • 適時的讀取數據並訓練模型:讀取100個數據,拿100個數據訓練模型,再讀取100個
    • placeholder(佔位符)
    • Queue(隊列)

Tensorflow隊列

  • 其與python自帶的隊列庫使用方法大同小異
  • 在訓練樣本時,希望讀入的訓練樣本是有序的
  • tf.FIFOQueue:先進先出隊列,按順序出隊列
  • tf.RandomShuffleQueue:隨機出隊列

FIFOQueue

使用tf.FIFOQueue(capacity,dtypes,name="fifo_queue")創建一個先進先出的順序對元素進行排隊的隊列

  • capacity:整數,能儲存在此隊列中的元素數量的上限
  • dtypes:隊列存儲的數據類型
  • name:隊列的名字

method

  • dequeue(name=None)
    • 返回一個出隊列操作
  • enqueue(vals,name=None)
    • 返回一個入隊列操作
  • enqueue_many(vals,name=None)
    • 多個數據同時入隊列
    • vals列表或者元組
    • 返回一個進隊列操作(op)
  • size(name=None)
    • 返回當前隊列存放多少數據

利用隊列實現同步

同步就是傳統先放完數據,再去取數據訓練

完成一個數據出隊列+1後入隊列操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import tensorflow as tf

#模擬同步流程

# 1.定義一個隊列
Q = tf.FIFOQueue(3,dtypes=tf.float32)

# 2.先放入初始數據到隊列中
enq_many = Q.enqueue_many([[0.1,0.2,0.3],]) #[註2]

# 3. 定義處理數據的邏輯過程(取出數據,+1,重新入隊列)
# 取出數據
de_q = Q.dequeue()
# 對取出的數據+1(因為有重載機制 +1會轉換為tensor類型)
new_data = de_q + 1
# 重新將新數據入隊列
en_q = Q.enqueue(new_data)


with tf.Session() as sess:
# 初始化隊列,運行前面定義好的圖
sess.run(enq_many)

# 模擬訓練過程
for i in range(100):
# 邏輯過程不需要全部執行[註1]
sess.run(en_q)

# 取出數據
for i in range(Q.size().eval()): # Q.size()為op因此須先運行(可用.eval()運行op取值)
print(sess.run(Q.dequeue()))
  1. 在tensorflow當中,運行op是有依賴性的,也就是在運行最後一個操作(op)時,其會回溯到最原始的op將其執行,直到指定的op執行完畢為止
    • 因此定義圖(graph)時要是有流程的依賴性,只要執行最後一個op即可
    • en_q操作含有new_data操作,且new_data操作中又含有de_q操作,因此只要運行en_q前面的op都會一起執行
  2. 在傳入多個數據時應讓其認為是多個數據而非一個張量
    • 使用[[data1,data2,data3],]來確保傳入的為三個數據(二維),而非[data1,data2,data3]一個張量(一維)
    • 如表示元組(tuple)應為(5,)而非(5)

Result

1
2
3
33.2
33.3
34.1