Um ein Modell zu trainieren, habe ich mein Modell in einer Klasse gekapselt. Ich verwende eine tf.RandomShuffleQueue
, um eine Liste von Dateinamen in die Warteschlange zu stellen. Wenn ich jedoch die Elemente aus der Warteschlange wechsle, werden sie aus der Warteschlange entfernt, aber die Größe der Warteschlange wird nicht reduziert.Die Entfernung aus RandomShuffleQueue reduziert nicht die Größe
Im Folgenden werden spezifischere Fragen durch den Code-Schnipsel gefolgt:
- Wenn ich nur
5
Bilder zum Beispiel, aber Schritte reichen bis zu 100, würde dieses Ergebnis in denaddfilenames
wiederholt automatisch aufgerufen? Es gibt mir keinen Fehler bei der Ausleihe, also denke ich, dass es automatisch aufgerufen wird. Warum ändert sich die Größe der
tf.RandomShuffleQueue
nicht? Es bleibt konstant.import os import time import functools import tensorflow as tf from Read_labelclsloc import readlabel def ReadTrain(traindir): # Returns a list of training images, their labels and a dictionay. # The dictionary maps label names to integer numbers. return trainimgs, trainlbls, classdict def ReadVal(valdir, classdict): # Reads the validation image labels. # Returns a dictionary with filenames as keys and # corresponding labels as values. return valdict def lazy_property(function): # Just a decorator to make sure that on repeated calls to # member functions, ops don't get created repeatedly. # Acknowledgements : https://danijar.com/structuring-your-tensorflow-models/ attribute= '_cache_' + function.__name__ @property @functools.wraps(function) def decorator(self): if not hasattr(self, attribute): setattr(self, attribute, function(self)) return getattr(self, attribute) return decorator class ModelInitial: def __init__(self, traindir, valdir): self.graph self.traindir = traindir self.valdir = valdir self.traininginfo() self.epoch = 0 def traininginfo(self): self.trainimgs, self.trainlbls, self.classdict = ReadTrain(self.traindir) self.valdict = ReadVal(self.valdir, self.classdict) with self.graph.as_default(): self.trainimgs_tensor = tf.constant(self.trainimgs) self.trainlbls_tensor = tf.constant(self.trainlbls, dtype=tf.uint16) self.trainimgs_dict = {} self.trainimgs_dict["ImageFile"] = self.trainimgs_tensor return None @lazy_property def graph(self): g = tf.Graph() with g.as_default(): # Layer definitions go here return g @lazy_property def addfilenames (self): # This is the function where filenames are pushed to a RandomShuffleQueue filename_queue = tf.RandomShuffleQueue(capacity=len(self.trainimgs), min_after_dequeue=0,\ dtypes=[tf.string], names=["ImageFile"],\ seed=0, name="filename_queue") sz_op = filename_queue.size() dq_op = filename_queue.dequeue() enq_op = filename_queue.enqueue_many(self.trainimgs_dict) return filename_queue, enq_op, sz_op, dq_op def Train(self): # The function for training. # I have not written the training part yet. # Still struggling with preprocessing with self.graph.as_default(): filename_q, filename_enqueue_op, sz_op, dq_op= self.addfilenames qr = tf.train.QueueRunner(filename_q, [filename_enqueue_op]) filename_dequeue_op = filename_q.dequeue() init_op = tf.global_variables_initializer() sess = tf.Session(graph=self.graph) sess.run(init_op) coord = tf.train.Coordinator() enq_threads = qr.create_threads(sess, coord=coord, start=True) counter = 0 for step in range(100): print(sess.run(dq_op["ImageFile"])) print("Epoch = %d "%(self.epoch)) print("size = %d"%(sess.run(sz_op))) counter+=1 names = [n.name for n in self.graph.as_graph_def().node] coord.request_stop() coord.join(enq_threads) print("Counter = %d"%(counter)) return None if __name__ == "__main__": modeltrain = ModelInitial(<Path to training images>,\ <Path to validation images>) a = modeltrain.graph print(a) modeltrain.Train() print("Success")
Danke. Ich habe das auch erwartet. Ich finde 'tf.train.QueueRunner' ziemlich restriktiv. Ich bin gezwungen, ein einziges Enqueue_op zu verwenden. Ich kann dort keine allgemeine Funktion einfügen. Ich will in der Lage sein, die bestimmte Epoche genau zu verfolgen, indem ich die Epoche inkrementiere, sobald eine volle "enqueue_many" vorüber ist. Wie kann ich es erreichen? Leider sehe ich noch keine Funktion in 'QueueRunner'. Wenn dies der Fall ist, wird es nicht ordnungsgemäß dokumentiert. Die Handhabung und Vorverarbeitung von Datasets bereitet TensorFlow derzeit größte Sorgen. Irgendwelche Vorschläge ? – Ujjwal
@Ujjwal, queuernunner Logik ist ziemlich klein, ich finde es manchmal nützlich, nicht Warteschlangenläufer zu verwenden und Enqueue-Operationen selbst aus separaten Python-Thread ausführen. Das gibt mehr Kontrolle, siehe https://github.com/yaroslavvb/stuff/tree/master/queues_talk für einige Erklärungen –
Ya. Ich fand schließlich die Lösung mit einer Klassenstruktur und Threading-Modul. Es ist klarer und gibt mehr Kontrolle als QueueRunner. Tatsächlich erweisen sich QueueRunners für eine komplexe Vorverarbeitung als ziemlich nutzlos. Auf Github sah ich, dass eine neue Eingangspipeline für Version 2.0 vorgeschlagen wird. Ernsthaft, Tensorflow benötigt eine Überholung mit Eingangspipeline. – Ujjwal