2017-08-30 2 views
8

Pour la formation d'un modèle de LSTM dans tensorflow, j'ai structuré mes données dans un tf.train.SequenceExample le format et stocké dans un fichier TFRecord . Je voudrais maintenant utiliser la nouvelle API DataSet à générer des lots rembourrés pour la formation. Dans the documentation il y a un exemple pour utiliser padded_batch, mais pour mes données je ne peux pas comprendre quelle devrait être la valeur de padded_shapes.Comment créer des lots matelassés dans Tensorflow pour les données tf.train.SequenceExample à l'aide de l'API DataSet?

Pour lire le fichier TFrecord dans les lots que j'ai écrit le code Python suivant:

import math 
import tensorflow as tf 
import numpy as np 
import struct 
import sys 
import array 

if(len(sys.argv) != 2): 
    print "Usage: createbatches.py [RFRecord file]" 
    sys.exit(0) 


vectorSize = 40 
inFile = sys.argv[1] 

def parse_function_dataset(example_proto): 
    sequence_features = { 
     'inputs': tf.FixedLenSequenceFeature(shape=[vectorSize], 
              dtype=tf.float32), 
     'labels': tf.FixedLenSequenceFeature(shape=[], 
              dtype=tf.int64)} 

    _, sequence = tf.parse_single_sequence_example(example_proto, sequence_features=sequence_features) 

    length = tf.shape(sequence['inputs'])[0] 
    return sequence['inputs'], sequence['labels'] 

sess = tf.InteractiveSession() 

filenames = tf.placeholder(tf.string, shape=[None]) 
dataset = tf.contrib.data.TFRecordDataset(filenames) 
dataset = dataset.map(parse_function_dataset) 
# dataset = dataset.batch(1) 
dataset = dataset.padded_batch(4, padded_shapes=[None]) 
iterator = dataset.make_initializable_iterator() 

batch = iterator.get_next() 

# Initialize `iterator` with training data. 
training_filenames = [inFile] 
sess.run(iterator.initializer, feed_dict={filenames: training_filenames}) 

print(sess.run(batch)) 

Le code fonctionne bien si j'utilise dataset = dataset.batch(1) (pas de remplissage nécessaire dans ce cas), mais quand j'utilise le padded_batch variante, je reçois l'erreur suivante:

TypeError: If shallow structure is a sequence, input must also be a sequence. Input has type: .

Pouvez-vous me aider à comprendre ce que je passerais pour le paramètre padded_shapes?

(Je sais qu'il ya beaucoup de code exemple en utilisant le filetage et les files d'attente pour cela, mais je préfère utiliser la nouvelle API DataSet pour ce projet)

+0

Merci Marijn! Vos questions m'ont beaucoup aidé! –

Répondre

6

Vous devez passer un tuple de formes. Dans votre cas, vous devriez passer

dataset = dataset.padded_batch(4, padded_shapes=([vectorSize],[None])) 

ou essayez

dataset = dataset.padded_batch(4, padded_shapes=([None],[None])) 

Cocher cette code pour plus de détails. J'ai dû déboguer cette méthode pour comprendre pourquoi cela ne fonctionnait pas pour moi.

+0

Merci! Cela a du sens. Ce qui suit a fonctionné pour mon exemple: 'padded_shapes = ([None, vectorSize], [None])'. Le premier tenseur est une liste de vecteurs avec la dimension vectorSize et le second est une liste avec des labels entiers. –

+0

Tout comme complément, 'padded_shapes' est sensible au type de la structure imbriquée (si l'ensemble de données retourne un tuple, padded_shapes devrait être aussi un tuple et non une liste) – Conchylicultor

0

Si votre objet Dataset actuel contient un tuple, vous pouvez également spécifier la forme de chaque élément matelassé. Par exemple, j'ai un jeu de données (same_sized_images, Labels) et chaque étiquette a une longueur différente mais le même rang.

def process_label(resized_img, label): 
    # Perfrom some tensor transformations 
    # ...... 

    return resized_img, label 

dataset = dataset.map(process_label) 
dataset = dataset.padded_batch(batch_size, 
           padded_shapes=([None, None, 3], 
               [None, None])) # my label has rank 2