2015-12-02 16 views
8

Ho una directory di immagini e un file separato che corrisponde ai nomi dei file delle immagini alle etichette. Così la directory di immagini ha i file come 'treno/001.jpg' e il file di etichettatura si presenta come:Accesso al nome file dalla coda file in Tensor Flow

train/001.jpg 1 
train/002.jpg 2 
... 

posso facilmente caricare le immagini dalla directory delle immagini in Tensor flusso creando una filequeue dai nomi dei file:

filequeue = tf.train.string_input_producer(filenames) 
reader = tf.WholeFileReader() 
img = reader.read(filequeue) 

Ma non riesco a collegare questi file con le etichette del file di etichettatura. Sembra che ho bisogno di accedere ai nomi dei file all'interno della coda ad ogni passaggio. C'è un modo per ottenerli? Inoltre, una volta ottenuto il nome file, devo essere in grado di cercare l'etichetta codificata dal nome file. Sembra che un dizionario Python standard non funzioni perché questi calcoli devono avvenire in ogni fase del grafico.

risposta

10

Dato che i tuoi dati non sono troppo grandi per poter fornire l'elenco dei nomi di file come array python, ti suggerisco di eseguire la pre-elaborazione in Python. Crea due liste (stesso ordine) dei nomi dei file e delle etichette, e inseriscile in una randomshufflequeue o in una coda e rimuovi la coda da quella. Se si desidera il comportamento "loop infinitamente" di string_input_producer, è possibile rieseguire l''enqueue' all'inizio di ogni epoca.

Un giocattolo esempio molto:

import tensorflow as tf 

f = ["f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8"] 
l = ["l1", "l2", "l3", "l4", "l5", "l6", "l7", "l8"] 

fv = tf.constant(f) 
lv = tf.constant(l) 

rsq = tf.RandomShuffleQueue(10, 0, [tf.string, tf.string], shapes=[[],[]]) 
do_enqueues = rsq.enqueue_many([fv, lv]) 

gotf, gotl = rsq.dequeue() 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    tf.train.start_queue_runners(sess=sess) 
    sess.run(do_enqueues) 
    for i in xrange(2): 
     one_f, one_l = sess.run([gotf, gotl]) 
     print "F: ", one_f, "L: ", one_l 

La chiave è che si sta effettivamente enqueueing coppie di nomi di file/etichette quando si fa il enqueue, e queste coppie sono restituito dal dequeue.

+0

Ok, va bene, questo è esattamente ciò di cui avevo bisogno! Non avevo pensato di abbinare i due in python e mischiarlo in anticipo - stavo solo cercando di usare il codice dal tutorial CIFAR che carica il file e poi lo rimescola in seguito. – bschreck

+0

In realtà l'ho appena provato e penso che la mia lista di nomi di file sia troppo grande. Usando questo codice si blocca, ma funziona quando riduco il numero di elementi nella mia lista. Ci sono 87.000 file tra l'altro. – bschreck

+0

Interessante - non dovrebbe bloccarsi, davvero. Hai aumentato il valore di randomshufflequeue max per essere abbastanza grande da gestire il numero di cose che stai inserendo? Devo dire che non ho mai provato una coda casuale casuale così grande. :) Se si desidera salvare la memoria, è possibile riscrivere il file come csv, utilizzare un textlinereader collegato a un decodificatore csv e quindi gettare quelli in una coda, con un queuerunner per mantenerlo in esecuzione. Molto lavoro per solo ~ 1 MB di nomi di file, però. – dga

4

Ecco cosa sono riuscito a fare.

ho mescolate i nomi dei file e abbinati i etichette a loro in Python:

np.random.shuffle(filenames) 
labels = [label_dict[f] for f in filenames] 

Poi ha creato uno string_input_producer per i nomi di file con mischiare off, e una FIFO per le etichette:

lv = tf.constant(labels) 
label_fifo = tf.FIFOQueue(len(filenames),tf.int32, shapes=[[]]) 
file_fifo = tf.train.string_input_producer(filenames, shuffle=False, capacity=len(filenames)) 
label_enqueue = label_fifo.enqueue_many([lv]) 

Poi per leggere l'immagine potrei usare un WholeFileReader e per ottenere l'etichetta potrei deselezionare il fifo:

reader = tf.WholeFileReader() 
image = tf.image.decode_jpeg(value, channels=3) 
image.set_shape([128,128,3]) 
result.uint8image = image 
result.label = label_fifo.dequeue() 

e generare il batch come segue:

min_fraction_of_examples_in_queue = 0.4 
min_queue_examples = int(num_examples_per_epoch * 
         min_fraction_of_examples_in_queue) 
num_preprocess_threads = 16 
images, label_batch = tf.train.shuffle_batch(
    [result.uint8image, result.label], 
    batch_size=FLAGS.batch_size, 
    num_threads=num_preprocess_threads, 
    capacity=min_queue_examples + 3 * FLAGS.batch_size, 
    min_after_dequeue=min_queue_examples) 
+0

Questo framework di lettura in etichette si adatta bene al mio codice che usa anche 'tf.WholeFileReader' per leggere nei nomi dei file immagine, tuttavia, gli utenti devono ricordare di eseguire' sess.run (label_enqueue) 'prima di iniziare l'allenamento altrimenti il ​​programma si blocca lì e attende l'operazione di accodamento. –

+0

Stavo cercando di utilizzare le stesse idee del codice, ma non ero in grado di mantenere le etichette sincronizzate con le immagini. http://stackoverflow.com/questions/43567552/tf-slice-input-producer-not-keeping-tensors-in-sync – rasen58

1

C'è tf.py_func() si potrebbe utilizzare per implementare una mappatura da percorso del file da etichettare.

files = gfile.Glob(data_pattern) 
filename_queue = tf.train.string_input_producer(
files, num_epochs=num_epochs, shuffle=True) # list of files to read 

def extract_label(s): 
    # path to label logic for cat&dog dataset 
    return 0 if os.path.basename(str(s)).startswith('cat') else 1 

def read(filename_queue): 
    key, value = reader.read(filename_queue) 
    image = tf.image.decode_jpeg(value, channels=3) 
    image = tf.cast(image, tf.float32) 
    image = tf.image.resize_image_with_crop_or_pad(image, width, height) 
    label = tf.cast(tf.py_func(extract_label, [key], tf.int64), tf.int32) 
    label = tf.reshape(label, []) 

training_data = [read(filename_queue) for _ in range(num_readers)] 

... 

tf.train.shuffle_batch_join(training_data, ...) 
0

ho usato questo:

filename = filename.strip().decode('ascii') 
0

Un altro suggerimento è quello di salvare i dati in formato TFRecord. In questo caso sarai in grado di salvare tutte le immagini e tutte le etichette nello stesso file.Per un gran numero di file che dà un sacco di vantaggi:

  • in grado di memorizzare i dati e le etichette nello stesso luogo
  • dati è allocato in un unico posto (non c'è bisogno di ricordare varie directory)
  • se ci sono molti file (immagini), l'apertura/chiusura di un file richiede molto tempo. Cercare la posizione del file da ssd/hdd richiede anche tempo