2016-08-28 47 views
12

我試圖運行tensorflow圖來訓練模型並定期使用單獨的評估數據集進行評估。訓練數據和評估數據均使用排隊運動員來實施。tensorflow:使用隊列運行器有效地提供eval /火車數據

我目前的解決方案是在同一圖形中創建兩個輸入,並使用取決於is_training佔位符的tf.cond。我的問題是由下面的代碼高亮顯示:

import tensorflow as tf 
from tensorflow.models.image.cifar10 import cifar10 
from time import time 


def get_train_inputs(is_training): 
    return cifar10.inputs(False) 


def get_eval_inputs(is_training): 
    return cifar10.inputs(True) 


def get_mixed_inputs(is_training): 
    train_inputs = get_train_inputs(None) 
    eval_inputs = get_eval_inputs(None) 

    return tf.cond(is_training, lambda: train_inputs, lambda: eval_inputs) 


def time_inputs(inputs_fn, n_runs=10): 
    graph = tf.Graph() 
    with graph.as_default(): 
     is_training = tf.placeholder(dtype=tf.bool, shape=(), 
            name='is_training') 
     images, labels = inputs_fn(is_training) 

    with tf.Session(graph=graph) as sess: 
     coordinator = tf.train.Coordinator() 
     threads = tf.train.start_queue_runners(sess=sess, coord=coordinator) 
     t = time() 
     for i in range(n_runs): 
      im, l = sess.run([images, labels], feed_dict={is_training: True}) 
     dt = time() - t 
     coordinator.request_stop() 
     coordinator.join(threads) 

    return dt/n_runs 

print('Train inputs: %.3f' % time_inputs(get_train_inputs)) 
print('Eval inputs: %.3f' % time_inputs(get_eval_inputs)) 
print('Mixed inputs: %.3f' % time_inputs(get_mixed_inputs)) 

我也不得不註釋掉image_summarytensorflow/models/image/cifar10/cifar10_inputs.py133

這得到以下結果:

Train inputs: 0.055 
Eval inputs: 0.050 
Mixed inputs: 0.105 

這似乎在混合情況下,兩個輸入端被讀取/解析,即使只有1被使用。有沒有辦法避免這種冗餘計算?還是有一種更好的方法來切換仍然利用隊列運行器設置的訓練/評估數據?

+0

我試圖阻止,並加入線程後再次啓動隊列亞軍,但我不能得到那個工作。似乎隊列後關閉 – piotr

回答

4

你讀過最後一頁有關多輸入的link的部分? 我認爲你可以添加一個is_training參數到你的輸入函數來區分訓練數據和eval數據。 然後,您可以重新使用共享變量來獲取eval數據的logits併爲eval構建op。 然後在你的圖中,運行valudation_accuracy=sess.run(eval_op)以獲得eval的準確性。


更新:

你好,從我的理解,如果你想爲N筆訓練,評估,培訓,評估,您可以在同一圖表中保持有兩種OPS,沒有必要建立一個新的一個。 假設你已經建立所有需要的功能,那麼代碼應該是這樣的:

#the following two steps will add train and eval input queue to the graph 
train_inputs,train_labels = inputs(is_train=True) 
eval_inputs,eval_labels = inputs(is_train=False) 

with tf.variable_scope("inference") as scope: 
    train_logits = inference(train_inputs) 
    scope.reuse_variables() 
    eval_logits = inference(eval_inputs) 

loss = loss(train_logits,train_labels) 
eval_accuracy = accuracy(eval_logits,eval_labels) 

#...add train op here,start queue runner and train it ... 
+0

從我理解這涉及建立單獨的圖(儘管與共享變量)。如果你做了大量的訓練,然後評估一次,但是如果你想訓練n批次,評估,訓練,評估......每次創建一個新圖形變得昂貴。我想我仍然更喜歡我這裏不雅的解決方案,從一個單獨的小圖中使用'feed_dict',只負責從隊列中生成輸入批次。 – DomJack

+0

更新後的版本在所有框中打勾:)。對於後期更新抱歉。 – DomJack

2

經過一番實驗,我現在最好的解決方案是有一個主要的圖表,具有訓練輸入和一個單獨的圖表,只有評估數據操作。我打開一個單獨的會話來獲取評估數據,並在我想評估時將其提供給訓練圖。高度不雅的(和評估運行需要比理想的時間更長的時間,因爲他們不得不將一個會話只喂到另一個會話),但假設評估運行與培訓運行相比是少見的,這似乎比原始版本更可取...

import tensorflow as tf 
from tensorflow.models.image.cifar10 import cifar10 
from time import time 


class DataSupplier: 
    def __init__(self, tensor_fn): 
     graph = tf.Graph() 
     with graph.as_default(): 
      with graph.device('/cpu:0'): 
       self.tensor = tensor_fn() 
     self.sess = tf.Session(graph=graph) 
     self.coord = tf.train.Coordinator() 
     self.threads = tf.train.start_queue_runners(sess=self.sess, 
                coord=self.coord) 

    def get_tensor_val(self): 
     return self.sess.run(self.tensor) 

    def clean_up(self): 
     self.coord.request_stop() 
     self.coord.join(self.threads) 


eval_batcher = DataSupplier(lambda: cifar10.inputs(True)) 

graph = tf.Graph() 
with graph.as_default(): 
    images, labels = cifar10.inputs(False) 

    out_images = tf.identity(images) 
    out_labels = tf.identity(labels) 

n_runs = 100 

with tf.Session(graph=graph) as sess: 
    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(sess, coord) 
    for i in range(n_runs): 
     sess.run([out_images, out_labels]) 
    t = time() 
    for i in range(n_runs): 
     sess.run([out_images, out_labels]) 
    dt = (time() - t)/n_runs 
    print('Train time: %.3f' % dt) 
    t = time() 
    for i in range(n_runs): 
     eval_images, eval_labels = eval_batcher.get_tensor_val() 
     sess.run([out_images, out_labels], 
       feed_dict={images: eval_images, labels: eval_labels}) 
    dt = (time() - t)/n_runs 
    print('Eval time: %.3f' % dt) 
    coord.request_stop() 
    coord.join(threads) 

eval_batcher.clean_up() 

結果:

Train time: 0.050 
Eval time: 0.064 

更新:使用與tf.contrib.layers和正規化培訓的問題這種方法的時候,我發現了正規化損失趨於無窮,如果DataSupplier圖是在同一設備作爲訓練圖。我不能爲我的生活解釋爲什麼會出現這種情況,但是明確地將DataSupplier的設備設置爲CPU(鑑於訓練圖在我的GPU上)似乎可行......

相關問題