【轉載】 tensorflow中 tf.train.slice_input_producer 和 tf.train.batch 函數

原文地址:dom

https://blog.csdn.net/dcrmg/article/details/79776876函數

 

 

 

 

------------------------------------------------------------------------------------------------------------------spa

 

 

tensorflow數據讀取機制

tensorflow中爲了充分利用GPU,減小GPU等待數據的空閒時間,使用了兩個線程分別執行數據讀入和數據計算。.net

具體來講就是使用一個線程源源不斷的將硬盤中的圖片數據讀入到一個內存隊列中,另外一個線程負責計算任務,所需數據直接從內存隊列中獲取。線程

 

 

 

 

tf在內存隊列以前,還設立了一個文件名隊列,文件名隊列存放的是參與訓練的文件名,要訓練 N個epoch,則文件名隊列中就含有N個批次的全部文件名。 示例圖以下:code

圖片來至於 https://zhuanlan.zhihu.com/p/27238630orm

 

 

 

 在N個epoch的文件名最後是一個結束標誌,當tf讀到這個結束標誌的時候,會拋出一個 OutofRange 的異常,外部捕獲到這個異常以後就能夠結束程序了。而建立tf的文件名隊列就須要使用到 tf.train.slice_input_producer 函數。blog

 

 

 

 

 

 

 

 

 

tf.train.slice_input_producer 隊列

 

tf.train.slice_input_producer是一個tensor生成器,做用是按照設定,每次從一個tensor列表中按順序或者隨機抽取出一個tensor放入文件名隊列。圖片

slice_input_producer(tensor_list, num_epochs=None, shuffle=True, seed=None,
                         capacity=32, shared_name=None, name=None)

 

 

  • 第一個參數 tensor_list:包含一系列tensor的列表,表中tensor的第一維度的值必須相等,即個數必須相等,有多少個圖像,就應該有多少個對應的標籤。

 

  • 第二個參數num_epochs: 可選參數,是一個整數值,表明迭代的次數,若是設置 num_epochs=None,生成器能夠無限次遍歷tensor列表,若是設置爲 num_epochs=N,生成器只能遍歷tensor列表N次。

 

  • 第三個參數shuffle: bool類型,設置是否打亂樣本的順序。通常狀況下,若是shuffle=True,生成的樣本順序就被打亂了,在批處理的時候不須要再次打亂樣本,使用 tf.train.batch函數就能夠了;若是shuffle=False,就須要在批處理時候使用 tf.train.shuffle_batch函數打亂樣本。

 

  • 第四個參數seed: 可選的整數,是生成隨機數的種子,在第三個參數設置爲shuffle=True的狀況下才有用。

 

  • 第五個參數capacity:設置tensor列表的容量。

 

  • 第六個參數shared_name:可選參數,若是設置一個‘shared_name’,則在不一樣的上下文環境(Session)中能夠經過這個名字共享生成的tensor。

 

  • 第七個參數name:可選,設置操做的名稱。

 

 

tf.train.slice_input_producer定義了樣本放入文件名隊列的方式,包括迭代次數,是否亂序等,要真正將文件放入文件名隊列,還須要調用tf.train.start_queue_runners 函數來啓動執行文件名隊列填充的線程,以後計算單元才能夠把數據讀出來,不然文件名隊列爲空的,計算單元就會處於一直等待狀態,致使系統阻塞。

 

 

 

 

 

tf.train.slice_input_producer 和 tf.train.start_queue_runners 使用:

import tensorflow as tf
 
images = ['img1', 'img2', 'img3', 'img4', 'img5']
labels= [1,2,3,4,5]
 
epoch_num=8
 
f = tf.train.slice_input_producer([images, labels],num_epochs=None,shuffle=False)
 
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    for i in range(epoch_num):
        k = sess.run(f)
        print ('************************')
        print (i,k)
 
    coord.request_stop()
    coord.join(threads)

 

 

 

 

 

tf.train.slice_input_producer函數中shuffle=False,不對tensor列表亂序,輸出:

 

 

 

 

若是設置shuffle=True,輸出亂序:

 

 

 

 

 

 

 

tf.train.batch

tf.train.batch是一個tensor隊列生成器,做用是按照給定的tensor順序,把batch_size個tensor推送到文件隊列,做爲訓練一個batch的數據,等待tensor出隊執行計算。

batch(tensors, batch_size, num_threads=1, capacity=32,
          enqueue_many=False, shapes=None, dynamic_pad=False,
          allow_smaller_final_batch=False, shared_name=None, name=None)

 

 

  • 第一個參數tensors:tensor序列或tensor字典,能夠是含有單個樣本的序列;

 

  • 第二個參數batch_size: 生成的batch的大小;

 

  • 第三個參數num_threads:執行tensor入隊操做的線程數量,能夠設置使用多個線程同時並行執行,提升運行效率,但也不是數量越多越好;

 

  • 第四個參數capacity: 定義生成的tensor序列的最大容量;

 

  • 第五個參數enqueue_many: 定義第一個傳入參數tensors是多個tensor組成的序列,仍是單個tensor;

 

  • 第六個參數shapes: 可選參數,默認是推測出的傳入的tensor的形狀;

 

  • 第七個參數dynamic_pad: 定義是否容許輸入的tensors具備不一樣的形狀,設置爲True,會把輸入的具備不一樣形狀的tensor歸一化到相同的形狀;

 

  • 第八個參數allow_smaller_final_batch: 設置爲True,表示在tensor隊列中剩下的tensor數量不夠一個batch_size的狀況下,容許最後一個batch的數量少於batch_size, 設置爲False,則無論什麼狀況下,生成的batch都擁有batch_size個樣本;

 

  • 第九個參數shared_name: 可選參數,設置生成的tensor序列在不一樣的Session中的共享名稱;

 

  • 第十個參數name: 操做的名稱;

 

 

 

 

若是tf.train.batch的第一個參數 tensors 傳入的是tenor列表或者字典,返回的是tensor列表或字典,若是傳入的是隻含有一個元素的列表,返回的是單個的tensor,而不是一個列表。

 

 

 

如下舉例: 一共有5個樣本,設置迭代次數是2次,每一個batch中含有3個樣本,不打亂樣本順序:

# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
 
# 樣本個數
sample_num=5

# 設置迭代次數
epoch_num = 2

# 設置一個批次中包含樣本個數
batch_size = 3

# 計算每一輪epoch中含有的batch個數
batch_total = int(sample_num/batch_size)+1

 
# 生成4個數據和標籤
def generate_data(sample_num=sample_num):
    labels = np.asarray(range(0, sample_num))
    images = np.random.random([sample_num, 224, 224, 3])
    print('image size {},label size :{}'.format(images.shape, labels.shape))
 
    return images,labels

 
def get_batch_data(batch_size=batch_size):
    images, label = generate_data()

    # 數據類型轉換爲tf.float32
    images = tf.cast(images, tf.float32)
    label = tf.cast(label, tf.int32)
 
    #從tensor列表中按順序或隨機抽取一個tensor
    input_queue = tf.train.slice_input_producer([images, label], shuffle=False)
 
    image_batch, label_batch = tf.train.batch(input_queue, batch_size=batch_size, num_threads=1, capacity=64)

    return image_batch, label_batch


 
image_batch, label_batch = get_batch_data(batch_size=batch_size)
 
with tf.Session() as sess:
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess, coord)
    try:
        for i in range(epoch_num):  # 每一輪迭代
            print( '************' )
            for j in range(batch_total): #每個batch
                print( '--------' )
                # 獲取每個batch中batch_size個樣本和標籤
                image_batch_v, label_batch_v = sess.run([image_batch, label_batch])
                print(image_batch_v.shape, label_batch_v)
    except tf.errors.OutOfRangeError:
        print("done")
    finally:
        coord.request_stop()
    coord.join(threads)

 

 

 

 

 

輸出:

 

 

 

每次生成的batch中含有3個樣本,不打亂次序,因此生成的tensor序列是按照‘0,1,2,3,4,0,1,2,3……’排列的。

 

 

 


若是設置每一個batch中含有2個樣本,打亂次序,即設置
batch_size = 2, tf.train.slice_input_producer函數中 shuffle=True,輸出爲:

 

 

# -*- coding:utf-8 -*-
import tensorflow as tf
import numpy as np
 
# 樣本個數
sample_num=5

# 設置迭代次數
epoch_num = 2

# 設置一個批次中包含樣本個數
batch_size = 2

# 計算每一輪epoch中含有的batch個數
batch_total = int(sample_num/batch_size)+1

 
# 生成4個數據和標籤
def generate_data(sample_num=sample_num):
    labels = np.asarray(range(0, sample_num))
    images = np.random.random([sample_num, 224, 224, 3])
    print('image size {},label size :{}'.format(images.shape, labels.shape))
 
    return images,labels

 
def get_batch_data(batch_size=batch_size):
    images, label = generate_data()

    # 數據類型轉換爲tf.float32
    images = tf.cast(images, tf.float32)
    label = tf.cast(label, tf.int32)
 
    #從tensor列表中按順序或隨機抽取一個tensor
    input_queue = tf.train.slice_input_producer([images, label], shuffle=True)
 
    image_batch, label_batch = tf.train.batch(input_queue, batch_size=batch_size, num_threads=1, capacity=64)

    return image_batch, label_batch


 
image_batch, label_batch = get_batch_data(batch_size=batch_size)
 
with tf.Session() as sess:
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess, coord)
    try:
        for i in range(epoch_num):  # 每一輪迭代
            print( '************' )
            for j in range(batch_total): #每個batch
                print( '--------' )
                # 獲取每個batch中batch_size個樣本和標籤
                image_batch_v, label_batch_v = sess.run([image_batch, label_batch])
                print(image_batch_v.shape, label_batch_v)
    except tf.errors.OutOfRangeError:
        print("done")
    finally:
        coord.request_stop()
    coord.join(threads)

 

 

 

 

 

 



 

 

 

 

 

 

 

 

 

 

 

 

 

與tf.train.batch函數相對的還有一個tf.train.shuffle_batch函數,兩個函數做用同樣,都是生成必定數量的tensor,  組成訓練一個batch須要的數據集,區別是tf.train.shuffle_batch會打亂樣本順序。

相關文章
相關標籤/搜索