2017-02-09 2 views
1

Я реализую схему подсети для классификации токенов. I необходимо взять строковые данные из TFRecord, перетасовать пакет, а затем выполнить некоторую обработку, которая расширяет данные, и пакет снова. Возможно ли это с двумя операциями batch_shuffle?Двойной ввод данных входного сигнала тензодатчика

Это то, что мне нужно сделать:

  1. Епдиеих имена файлов в filequeue
  2. для каждого сериализованного примера, положить на shuffle_batch
  3. Когда я тяну каждый пример от случайного воспроизведения партии, мне нужно для PAD его, скопируйте его длиной последовательности, конкатенирующим вектором положения, это создает несколько примеров для каждого исходного примера из первой партии. Мне нужно снова заказать его.

Конечно, одним из решений является просто предварительная обработка данных, прежде чем загружать их в TF, но это займет больше дискового пространства, чем это необходимо.

DATA

Вот некоторые выборочные данные. У меня есть два примера. Каждый пример содержит особенности лексических предложений и этикеток для каждых маркеров:

sentences = [ 
      [ 'the', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog' '.'], 
      ['then', 'the', 'lazy', 'dog', 'slept', '.'] 
      ] 
sent_labels = [ 
      ['O', 'O', 'O', 'ANIMAL', 'O', 'O', 'O', 'ANIMAL', 'O'], 
      ['O', 'O', 'O', 'ANIMAL', 'O', 'O'] 
      ] 

Каждого "Пример" Теперь имеют функции, как показано ниже (некоторые reducution для ясности):

features { 
    feature { 
    key: "labels" 
    value { 
     bytes_list { 
     value: "O" 
     value: "O" 
     value: "O" 
     value: "ANIMAL" 
     ... 
     } 
    } 
    } 

    feature { 
    key: "sentence" 
    value { 
     bytes_list { 
     value: "the" 
     value: "quick" 
     value: "brown" 
     value: "fox" 
     ... 
     } 
    } 
    } 
} 

Transformation

После обработки разреженных данных я получаю предложение в виде списка токенов:

['' ',' quick ',' brown ',' fo х», ...]

мне нужно PAD список первого до заданной SEQ_LEN, а затем вставить индексов позиций в каждый пример, вращая позиции таким образом, что затяжки Я хочу, чтобы классифицировать это в позиции 0, и каждый маркер позиции относительно в положение 0:

[ 
['the', 0 , 'quick', 1 , 'brown', 2 , 'fox', 3, 'PAD', 4] # classify 'the' 
['the', -1, 'quick', 0 , 'brown', 1 , 'fox', 2 'PAD', 3 ] # classify 'quick 
['the', -2, 'quick', -1, 'brown', 0 , 'fox', 1 'PAD', 2 ] # classify 'brown 
['the', -3, 'quick', -2, 'brown', -1, 'fox', 0 'PAD', 1 ] # classify 'fox 
] 

Batching и ReBatching The Data

Вот упрощенная версия того, что я пытаюсь сделать:

# Enqueue the Filenames and serialize 
filenames =[outfilepath] 
fq = tf.train.string_input_producer(filenames, num_epochs=num_epochs, shuffle=True, name='FQ') 
reader = tf.TFRecordReader() 
key, serialized_example = reader.read(fq) 

# Dequeue Examples of batch_size == 1. Because all examples are Sparse Tensors, do 1 at a time 
initial_batch = tf.train.shuffle_batch([serialized_example], batch_size=1, capacity, min_after_dequeue) 


# Parse Sparse Tensors, make into single dense Tensor 
# ['the', 'quick', 'brown', 'fox'] 
parsed = tf.parse_example(data_batch, features=feature_mapping) 
dense_tensor_sentence = tf.sparse_tensor_to_dense(parsed['sentence'], default_value='<PAD>') 
sent_len = tf.shape(dense_tensor_sentence)[1] 

SEQ_LEN = 5 
NUM_PADS = SEQ_LEN - sent_len 
#['the', 'quick', 'brown', 'fox', 'PAD'] 
padded_sentence = pad(dense_tensor_sentence, NUM_PADS) 

# make sent_len X SEQ_LEN copy of sentence, position vectors 
#[ 
# ['the', 0 , 'quick', 1 , 'brown', 2 , 'fox', 3, 'PAD', 4 ] 
# ['the', -1, 'quick', 0 , 'brown', 1 , 'fox', 2 'PAD', 3 ] 
# ['the', -2, 'quick', -1, 'brown', 0 , 'fox', 1 'PAD', 2 ] 
# ['the', -3, 'quick', -2, 'brown', -1, 'fox', 0 'PAD', 1 ] 
# NOTE: There is no row where PAD is with a position 0, because I don't 
# want to classify the PAD token 
#] 
examples_with_positions = replicate_and_insert_positions(padded_sentence) 

# While my SEQ_LEN will be constant, the sent_len will not. Therefore, 
#I don't know the number of rows, but I can guarantee the number of 
# columns. shape = (?,SEQ_LEN) 

dynamic_input = final_reshape(examples_with_positions) # shape = (?, SEQ_LEN) 

# Try Random Shuffle Queue: 

# Rebatch <-- This is where the problem is 
#reshape_concat.set_shape((None, SEQ_LEN)) 

random_queue = tf.RandomShuffleQueue(10000, 50, [tf.int64], shapes=(SEQ_LEN,)) 
random_queue.enqueue_many(dynamic_input) 
batch = random_queue.dequeue_many(4) 


init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer(), tf.initialize_all_tables()) 

sess = create_session() 
sess.run(init_op) 

#tf.get_default_graph().finalize() 
coord = tf.train.Coordinator() 
threads = tf.train.start_queue_runners(sess=sess, coord=coord) 

try: 
    i = 0 
    while True: 
    print sess.run(batch) 

    i += 1 
except tf.errors.OutOfRangeError as e: 
    print "No more inputs." 

EDIT

Я сейчас пытаюсь использовать RandomShuffleQueue. В каждом экземпляре я хотел бы заключить пакет с формой (None, SEQ_LEN). Я изменил код выше, чтобы отразить это.

Я больше не получаю жалобы по поводу входных форм, но очереди подвешен на sess.run(batch)

+1

Просто пытаюсь понять. Во второй раз, когда вы выполняете пакетную обработку, вы хотите объединить эти матрицы положения для нескольких предложений, не так ли? Разве они не будут иметь разную длину, и в таком случае их доведение до минимума в плотном тензоре невозможно? –

+0

Извините, я забыл упомянуть, что я PADing каждый вход в константу SEQ_LEN. Я переписал пример кода, надеясь, что он разъяснит тезисы. Я получаю предложение, PAD it, затем плитка и изменяю предложение таким образом, чтобы каждый токен был конкатенирован вектором позитива. Тогда вход во вторую партию будет иметь форму = (sent_len, SEQ_LEN). Но из-за того, что я не знаю send_len, я не могу использовать QueueRunners – Neal

+1

Является ли 'enqueue_many' то, что вы хотите в этом случае? Тогда пакетная обработка будет (sent_len_1 + sent_len_2 + ..., SEQ_LEN). Размер партии для 'enqueue_many' не нуждается в информации о статической форме (просто убедитесь, что остальные размеры имеют статическую информацию о форме). –

ответ

1

Я приближалась всю проблему неправильно.Я ошибочно думал, что мне нужно определить полную форму партии при вставке в tf.batch_shuffle, но мне действительно нужно было определить только форму каждого элемента, который я вводил, и установить enqueue_many=True.

Вот правильный код:

single_batch=1 
input_batch_size = 64 
min_after_dequeue = 10 
capacity = min_after_dequeue + 3 * input_batch_size 
num_epochs=2 
SEQ_LEN = 10 
filenames =[outfilepath] 

fq = tf.train.string_input_producer(filenames, num_epochs=num_epochs, shuffle=True) 
reader = tf.TFRecordReader() 
key, serialized_example = reader.read(fq) 

# Dequeue examples of batch_size == 1. Because all examples are Sparse Tensors, do 1 at a time 
first_batch = tf.train.shuffle_batch([serialized_example], ONE, capacity, min_after_dequeue) 

# Get a single sentence and preprocess it shape=(sent_len) 
single_sentence = tf.parse_example(first_batch, features=feature_mapping) 

# Preprocess Sentence. shape=(sent_len, SEQ_LEN * 2). Each row is example 
processed_inputs = preprocess(single_sentence) 

# Re batch 
input_batch = tf.train.shuffle_batch([processed_inputs], 
       batch_size=input_batch_size, 
       capacity=capacity, min_after_dequeue=min_after_dequeue, 
       shapes=[SEQ_LEN * 2], enqueue_many=True) #<- This is the fix 


init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer(), tf.initialize_all_tables()) 

sess = create_session() 
sess.run(init_op) 

#tf.get_default_graph().finalize() 
coord = tf.train.Coordinator() 
threads = tf.train.start_queue_runners(sess=sess, coord=coord) 

try: 
    i = 0 
    while True: 
    print i  
    print sess.run(input_batch) 
    i += 1 
except tf.errors.OutOfRangeError as e: 
    print "No more inputs." 
Смежные вопросы