0

Ziel war es, eine Datenbank von TfRecords zu erstellen. Gegeben: Ich habe 23 Ordner enthalten jeweils 7500 Bild und 23 Textdatei, jede mit 7500 Zeile beschreibt Funktionen für die 7500 Bilder in separaten Ordnern.Erstellen von TfRecords aus einer Liste von Strings und Einspeisen eines Graphen in Tensorflow nach dem Dekodieren

habe ich die Datenbank durch diesen Code:

import tensorflow as tf 
import numpy as np 
from PIL import Image 

def _Float_feature(value): 
    return tf.train.Feature(float_list=tf.train.FloatList(value=[value])) 

def _bytes_feature(value): 
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value])) 

def _int64_feature(value): 
    return tf.train.Feature(int64_list=tf.train.Int64List(value=[value])) 

def create_image_annotation_data(): 
    # Code to read images and features. 
    # images represent a list of numpy array of images, and features_labels represent a list of strings 
    # where each string represent the whole set of features for each image. 
    return images, features_labels 

# This is the starting point of the program. 
# Now I have the images stored as list of numpy array, and the features as list of strings. 
images, annotations = create_image_annotation_data() 

tfrecords_filename = "database.tfrecords" 
writer = tf.python_io.TFRecordWriter(tfrecords_filename) 

for img, ann in zip(images, annotations): 

    # Note that the height and width are needed to reconstruct the original image. 
    height = img.shape[0] 
    width = img.shape[1] 

    # This is how data is converted into binary 
    img_raw = img.tostring() 
    example = tf.train.Example(features=tf.train.Features(feature={ 
     'height': _int64_feature(height), 
     'width': _int64_feature(width), 
     'image_raw': _bytes_feature(img_raw), 
     'annotation_raw': _bytes_feature(tf.compat.as_bytes(ann)) 
    })) 

    writer.write(example.SerializeToString()) 

writer.close() 

reconstructed_images = [] 

record_iterator = tf.python_io.tf_record_iterator(path=tfrecords_filename) 

for string_record in record_iterator: 
    example = tf.train.Example() 
    example.ParseFromString(string_record) 

    height = int(example.features.feature['height'] 
       .int64_list 
       .value[0]) 

    width = int(example.features.feature['width'] 
       .int64_list 
       .value[0]) 

    img_string = (example.features.feature['image_raw'] 
        .bytes_list 
        .value[0]) 

    annotation_string = (example.features.feature['annotation_raw'] 
         .bytes_list 
         .value[0]) 

    img_1d = np.fromstring(img_string, dtype=np.uint8) 
    reconstructed_img = img_1d.reshape((height, width, -1)) 
    annotation_reconstructed = annotation_string.decode('utf-8') 

daher nach ihnen Bildern und Texten in tfRecords und nach in der Lage, die Umwandlung und Konvertieren von Bildern in numpy und dem (Binär-Text) in Zeichenfolge in Python zu lesen Ich versuchte, die Extrameile zu gehen, indem ich eine filename_queue mit einem Lesegerät verwendete (Der Zweck war es, dem Graphen eine Charge von Daten anstatt einer Datenmenge gleichzeitig bereitzustellen. Außerdem war das Ziel, die Warteschlange von Beispielen in die Warteschlange einzureihen und zu entfernen verschiedene Threads, wodurch das Netzwerk schneller trainiert wird)

Daher habe ich die folgenden verwendet aufgrund Code:

import tensorflow as tf 
import numpy as np 
import time 

image_file_list = ["database.tfrecords"] 
batch_size = 16 

# Make a queue of file names including all the JPEG images files in the relative 
# image directory. 
filename_queue = tf.train.string_input_producer(image_file_list, num_epochs=1, shuffle=False) 

reader = tf.TFRecordReader() 

# Read a whole file from the queue, the first returned value in the tuple is the 
# filename which we are ignoring. 
_, serialized_example = reader.read(filename_queue) 

features = tf.parse_single_example(
     serialized_example, 
     # Defaults are not specified since both keys are required. 
     features={ 
      'height': tf.FixedLenFeature([], tf.int64), 
      'width': tf.FixedLenFeature([], tf.int64), 
      'image_raw': tf.FixedLenFeature([], tf.string), 
      'annotation_raw': tf.FixedLenFeature([], tf.string) 
     }) 

image = tf.decode_raw(features['image_raw'], tf.uint8) 
annotation = tf.decode_raw(features['annotation_raw'], tf.float32) 

height = tf.cast(features['height'], tf.int32) 
width = tf.cast(features['width'], tf.int32) 

image = tf.reshape(image, [height, width, 3]) 

# Note that the minimum after dequeue is needed to make sure that the queue is not empty after dequeuing so that 
# we don't run into errors 
''' 
min_after_dequeue = 100 
capacity = min_after_dequeue + 3 * batch_size 
ann, images_batch = tf.train.batch([annotation, image], 
            shapes=[[1], [112, 112, 3]], 
            batch_size=batch_size, 
            capacity=capacity, 
            num_threads=1) 
''' 

# Start a new session to show example output. 
with tf.Session() as sess: 
    merged = tf.summary.merge_all() 
    train_writer = tf.summary.FileWriter('C:/Users/user/Documents/tensorboard_logs/New_Runs', sess.graph) 

    # Required to get the filename matching to run. 
    tf.global_variables_initializer().run() 

    # Coordinate the loading of image files. 
    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(coord=coord) 

    for steps in range(16): 
     t1 = time.time() 
     annotation_string, batch, summary = sess.run([annotation, image, merged]) 
     t2 = time.time() 
     print('time to fetch 16 faces:', (t2 - t1)) 
     print(annotation_string) 
     tf.summary.image("image_batch", image) 
     train_writer.add_summary(summary, steps) 

    # Finish off the filename queue coordinator. 
    coord.request_stop() 
    coord.join(threads) 

Schließlich wird nach dem obigen Code ausgeführt, hat sich die folgenden Fehler: OutOfRangeError (siehe oben für Traceback): FIFOQueue ‚_0_input_producer‘ geschlossen ist, und hat nicht genügend Elemente (1 angefordert, aktuelle Größe 0) [[Knoten: ReaderReadV2 = ReaderReadV2 [_device = "/ Job: localhost/Replik: 0/Aufgabe: 0/cpu: 0"] (TFRecordReaderV2, input_producer)]]

Noch eine Frage:

  1. So dekodieren Sie die Binärdatenbank (tfrecords), um die gespeicherten Funktionen "als Python-String-Datenstruktur" zurück zu erhalten.
  2. Wie Sie die tf.train.batch verwenden, um eine Reihe von Beispielen zu erstellen, um das Netzwerk zu versorgen.

Vielen Dank !! Jede Hilfe wird sehr geschätzt.

Antwort

1

Um dieses Problem zu lösen, mussten die coordinator zusammen mit der queue runner beide innerhalb einer Session initialisiert werden. Da die Anzahl der Epochen intern gesteuert wird, ist es kein global variable, sondern ein local variable. Daher müssen wir diese lokale Variable initialisieren, bevor wir die queue_runner anweisen, die file_names in die Queue einzuschließen. Daher ist hier der folgende Code:

filename_queue = tf.train.string_input_producer(tfrecords_filename, num_epochs=num_epoch, shuffle=False, name='queue') 
reader = tf.TFRecordReader() 

key, serialized_example = reader.read(filename_queue) 
features = tf.parse_single_example(
    serialized_example, 
    # Defaults are not specified since both keys are required. 
    features={ 
     'height': tf.FixedLenFeature([], tf.int64), 
     'width': tf.FixedLenFeature([], tf.int64), 
     'image_raw': tf.FixedLenFeature([], tf.string), 
     'annotation_raw': tf.FixedLenFeature([], tf.string) 
    }) 
... 
init_op = tf.group(tf.local_variables_initializer(), 
       tf.global_variables_initializer()) 
with tf.Session() as sess: 
    sess.run(init_op) 

    coord = tf.train.Coordinator() 
    threads = tf.train.start_queue_runners(coord=coord) 

Und jetzt sollte funktionieren.

Jetzt, um eine Charge von Bildern zu sammeln, bevor Sie sie in das Netzwerk einspeisen, können wir tf.train.shuffle_batch oder tf.train.batch verwenden. Beide Werke. Und der Unterschied ist einfach. Einer mischt die Bilder und der andere nicht. Beachten Sie jedoch, dass beim Definieren einer Nummer in Threads und bei Verwendung von tf.train.batch die Datensamples möglicherweise aufgrund der Rasse gemischt werden, die zwischen den Threads stattfindet, die file_names in die Warteschlange aufnehmen. Wie auch immer, sollte der folgende Code direkt eingesetzt werden, nachdem die Queue Initialisierung wie folgt:

min_after_dequeue = 100 
num_threads = 1 
capacity = min_after_dequeue + num_threads * batch_size 
label_batch, images_batch = tf.train.batch([annotation, image], 
             shapes=[[], [112, 112, 3]], 
             batch_size=batch_size, 
             capacity=capacity, 
             num_threads=num_threads) 

Beachten Sie, dass hier die Form des tensors anders sein könnte.Es kam vor, dass der Leser ein farbiges Bild der Größe [112, 112, 3] dekodierte. Und die Annotation hat eine [] (es gibt keinen Grund, das war ein besonderer Fall).

Schließlich können wir den tf.string-Datentyp als eine Zeichenfolge behandeln. In Wirklichkeit können wir nach der Auswertung des Annotationstensors erkennen, dass der Tensor wie ein binary string behandelt wird (so wird es tatsächlich im Tensorfluss behandelt). Daher war diese Zeichenfolge in meinem Fall nur eine Reihe von Funktionen, die sich auf dieses bestimmte Bild bezogen. Daher, um spezifische Merkmale zu extrahieren, hier ein Beispiel:

# The output of string_split is not a tensor, instead, it is a SparseTensorValue. Therefore, it has a property value that stores the actual values. as a tensor. 
label_batch_splitted = tf.string_split(label_batch, delimiter=', ') 
label_batch_values = tf.reshape(label_batch_splitted.values, [batch_size, -1]) 
# string_to_number will convert the feature's numbers into float32 as I need them. 
label_batch_numbers = tf.string_to_number(label_batch_values, out_type=tf.float32) 
# the tf.slice would extract the necessary feature which I am looking. 
confidences = tf.slice(label_batch_numbers, begin=[0, 3], size=[-1, 1]) 

Hoffe, dass diese Antwort hilft.

Verwandte Themen