2017-08-10 1 views
0

L'objectif est de fournir de gros volumes de données à Tensorflow. Je suis venu à la mise en œuvre suivante. Cependant, alors que io de HDF5 est supposé être très rapide, ma mise en œuvre est lente. Est-ce dû à la non utilisation de la fonction morceaux? Je ne semble pas avoir les bonnes dimensions pour les morceaux, devrais-je voir cela comme une troisième dimension. Comme; (4096, 7, 1000) pour chunksize 1000?Lecture et écriture par lots, du fichier texte au format HDF5 en python

Veuillez noter que j'aurais pu simplifier mon code plus bas en trouvant une solution pour un seul générateur. Cependant, je pense que la combinaison de données/étiquettes est très commune et utile pour les autres.

J'utilise la fonction suivante pour créer deux générateurs, un pour les données et un pour les étiquettes correspondantes. Ensuite, je souhaite déplacer les données et les étiquettes produites par ces générateurs à HDF5.

def write_h5(data_gen, label_gen, out_file, batch_size, h5_batch_size, data_dtype, label_dtype): 
    # remove existing file 
    if os.path.isfile(out_file): 
     os.remove(out_file) 
    with h5py.File(out_file, 'a') as f: 
     # create a dataset and labelset in the same file 
     d = f.create_dataset('data', (batch_size,data_dim), maxshape=(None,data_dim), dtype=data_dtype) 
     l = f.create_dataset('label', (batch_size,label_dim), maxshape=(None,label_dim), dtype=label_dtype) 
     # use generators to fill both sets 
     for data in data_gen: 
      d.resize(d.shape[0]+batch_size, axis=0) 
      d[-batch_size:] = data 
      l.resize(l.shape[0]+batch_size, axis=0) 
      l[-batch_size:] = next(label_gen) 

Avec les constantes suivantes j'ai combiné les deux fonctions comme si;

batch_size = 4096 
h5_batch_size = 1000 
data_dim = 7 #[NUM_POINT, 9] 
label_dim = 1 #[NUM_POINT] 
data_dtype = 'float32' 
label_dtype = 'uint8' 

for data_file, label_file in data_label_files: 
    print(data_file) 
    with open(data_file, 'r') as data_f, open(label_file, 'r') as label_f: 
     data_gen = read_chunks(data_f, dim=data_dim) 
     label_gen = read_chunks(label_f, dim=label_dim) 
     out_file = data_file[:-4] + '.h5' 
     write_h5(data_gen, label_gen, out_file, batch_size, h5_batch_size, data_dtype, label_dtype) 

Répondre

3

Le problème n'est pas que HDF5 est lent. Le problème est que vous lisez une seule ligne à la fois en utilisant une boucle Python, en appelant genfromtxt() une fois par ligne! Cette fonction est destinée à lire des fichiers entiers. Et puis vous utilisez l'anti-modèle de « tableau = vstack (tableau, Newstuff)` dans la même boucle

En bref, votre problème de performance commence ici.

chunk = np.vstack((chunk, np.genfromtxt(io.BytesIO(line.encode())))) 

Vous devez simplement lire l'intégralité Si vous ne pouvez pas faire cela, lisez la moitié de celui-ci (vous pouvez définir un nombre maximum de lignes à lire chaque fois, par exemple 1 million)

+0

J'ai essayé de lire des morceaux, mais cela indiquerait Laissant moi avec des demi-lignes, pour lesquelles 'np.genfromtxt()' soulève l'erreur d'un nombre différent de colonnes Avez-vous une suggestion pour lire n nombre de lignes? Une autre solution serait de faire une liste simple et d'appliquer 'np.genfromtxt()' à cette liste, ai-je raison? Cependant, cela crée des problèmes avec les '' .BytesIO() 'et' .encode() '. Avez-vous une suggestion sur la façon de mettre en œuvre les deux? –

+1

Pour l'instant, j'ai résolu le problème en écrivant des lignes dans une liste (appelée: chunk) et exécuter 'np.genfromtxt()' dans cette liste. Le problème avec le codage bytes a été résolu en lisant le fichier en mode '' rb ''. –