2017-04-12 1 views
1

Ich habe einige Trainingsbeispiel für eine Sequenz-zu-Sequenz-Szenario, die als tf.train.SequenceExample in einer (oder mehreren) Datei (en) TFRecordWriter geschrieben werden. Ich würde gerne lesen, sie entschlüsseln und verworrene Chargen davon in mein Netzwerk einspeisen. Ich habe mit der Dokumentation und einigen hier und da gefundenen Tutorials gekämpft, aber aus solchen Sachen konnte ich nichts machen. Ich arbeite an einem eigenständigen Beispiel, hier unten.Batching und Shuffling aufgefüllt tf.train.SequenceExample

import random 

import tensorflow as tf 

from six.moves import xrange 


MIN_LEN = 6 
MAX_LEN = 12 
NUM_EXAMPLES = 20 
BATCH_SIZE = 3 
PATH = 'ciaone.tfrecords' 
MIN_AFTER_DEQUEUE = 10 
NUM_THREADS = 2 
SAFETY_MARGIN = 1 
CAPACITY = MIN_AFTER_DEQUEUE + (NUM_THREADS + SAFETY_MARGIN) * BATCH_SIZE 


def generate_example(): 
    # fake examples which are just useful to have a quick visualization. 
    # The input is a sequence of random numbers. 
    # The output is a sequence made of those numbers from the 
    # input sequence which are greater or equal then the average. 
    length = random.randint(MIN_LEN, MAX_LEN) 
    input_ = [random.randint(0, 10) for _ in xrange(length)] 
    avg = sum([1.0 * item for item in input_])/len(input_) 
    output = [item for item in input_ if item >= avg] 
    return input_, output 


def encode(input_, output): 
    length = len(input_) 
    example = tf.train.SequenceExample(
     context=tf.train.Features(
      feature={ 
       'length': tf.train.Feature(
        int64_list=tf.train.Int64List(value=[length])) 
      }), 
     feature_lists=tf.train.FeatureLists(
      feature_list={ 
       'input': tf.train.FeatureList(
        feature=[ 
         tf.train.Feature(
          int64_list=tf.train.Int64List(value=[item])) 
         for item in input_]), 
       'output': tf.train.FeatureList(
        feature=[ 
         tf.train.Feature(
          int64_list=tf.train.Int64List(value=[item])) 
         for item in output]) 
      } 
     ) 
    ) 
    return example 


def decode(example): 
    context_features = { 
     'length': tf.FixedLenFeature([], tf.int64) 
    } 
    sequence_features = { 
     'input': tf.FixedLenSequenceFeature([], tf.int64), 
     'output': tf.FixedLenSequenceFeature([], tf.int64) 
    } 
    ctx, seq = tf.parse_single_sequence_example(
     example, context_features, sequence_features) 
    input_ = seq['input'] 
    output = seq['output'] 
    return input_, output 

if __name__ == '__main__': 
    # STEP 1. -- generate a dataset. 
    with tf.python_io.TFRecordWriter(PATH) as writer: 
     for _ in xrange(NUM_EXAMPLES): 
      record = encode(*generate_example()) 
      writer.write(record.SerializeToString()) 

    with tf.Session() as sess: 
     queue = tf.train.string_input_producer([PATH]) 
     reader = tf.TFRecordReader() 
     _, value = reader.read(queue) 
     input_, output = decode(value) 

     # HERE I AM STUCK! 

     coord = tf.train.Coordinator() 
     threads = tf.train.start_queue_runners(coord=coord) 
     sess.run(tf.local_variables_initializer()) 
     sess.run(tf.global_variables_initializer()) 
     try: 
      while True: 
       # do something... 
     except tf.errors.OutOfRangeError, e: 
      coord.request_stop(e) 
     finally: 
      coord.request_stop() 
      coord.join(threads) 
     coord.request_stop() 
     coord.join(threads) 

Kann mir jemand vorschlagen, wie ich vorgehen soll? Vielen Dank im Voraus!

P.S. als Nebenanforderung: Jeder Zeiger auf Ressourcen zum besseren Verständnis der Eingabe-Pipeline-APIs von TensorFlow wird geschätzt.

Antwort

1

Wenn Sie mit Example s statt SequenceExample s zu tun, wäre es so einfach, wie ein Anruf zu tf.train.shuffle_batch auf Ihrem dekodiert Tensoren hinzufügen.

Allerdings erfordert shuffle-batch, dass die Tensoren, die Sie übergeben, eine statische Form haben, was hier nicht der Fall ist. Für Tensoren mit variabler Form können Sie stattdessen tf.train.batch mit dynamic_pad=True verwenden. Dies kümmert sich um das Batching (und Padding), mischt aber nicht Ihre Beispiele. Leider nimmt shuffle_batch kein dynamic_pad Argument.

Es gibt eine Abhilfe described here, wo Sie ein RandomShuffleQueue vor dem Aufruf von tf.train.batch hinzufügen:

inputs = decode(value) 
dtypes = list(map(lambda x: x.dtype, inputs)) 
shapes = list(map(lambda x: x.get_shape(), inputs)) 
queue = tf.RandomShuffleQueue(CAPACITY, MIN_AFTER_DEQUEUE, dtypes) 
enqueue_op = queue.enqueue(inputs) 
qr = tf.train.QueueRunner(queue, [enqueue_op] * NUM_THREADS) 
tf.add_to_collection(tf.GraphKeys.QUEUE_RUNNERS, qr) 
inputs = queue.dequeue() 
for tensor, shape in zip(inputs, shapes): 
    tensor.set_shape(shape) 

# Now you can use tf.train.batch with dynamic_pad=True, and the order in which 
# it enqueues elements will be permuted because of RandomShuffleQueue. 
batch_input, batch_output = tf.train.batch(inputs, batch_size, capacity=capacity, 
           dynamic_pad=True, name=name) 

Es ist ein Beispiel für dieses Muster here umgesetzt (in der Google-Magenta-Projekt).

+0

Es ist genau das, was ich mit meinen 'Example's gemacht habe, muss aber noch herausfinden, wie man mit' SequenceExamples' umgeht. Danke, dass du auf das GitHub-Problem hingewiesen hast! – petrux