Ich habe Caltech101 heruntergeladen. Seine Struktur ist:Schreiben Sie auf HDF5 und mischen Sie große Datenfelder
#Caltech101 dir #class1 dir #images of class1 jpgs #class2 dir #images of class2 jpgs ... #class100 dir #images of class100 jpgs
Mein Problem ist, dass ich nicht im Speicher zwei np Arrays x
und y
der Form (9144, 240, 180, 3)
und (9144)
halten kann. Meine Lösung besteht also darin, ein h5py-Dataset zu verteilen, sie in 2 Chunks zu laden und sie nacheinander in die Datei zu schreiben. Genau:
from __future__ import print_function
import os
import glob
from scipy.misc import imread, imresize
from sklearn.utils import shuffle
import numpy as np
import h5py
from time import time
def load_chunk(images_dset, labels_dset, chunk_of_classes, counter, type_key, prev_chunk_length):
# getting images and processing
xtmp = []
ytmp = []
for label in chunk_of_classes:
img_list = sorted(glob.glob(os.path.join(dir_name, label, "*.jpg")))
for img in img_list:
img = imread(img, mode='RGB')
img = imresize(img, (240, 180))
xtmp.append(img)
ytmp.append(label)
print(label, 'done')
x = np.concatenate([arr[np.newaxis] for arr in xtmp])
y = np.array(ytmp, dtype=type_key)
print('x: ', type(x), np.shape(x), 'y: ', type(y), np.shape(y))
# writing to dataset
a = time()
images_dset[prev_chunk_length:prev_chunk_length+x.shape[0], :, :, :] = x
print(labels_dset.shape)
print(y.shape, y.shape[0])
print(type(y), y.dtype)
print(prev_chunk_length)
labels_dset[prev_chunk_length:prev_chunk_length+y.shape[0]] = y
b = time()
print('Chunk', counter, 'written in', b-a, 'seconds')
return prev_chunk_length+x.shape[0]
def write_to_file(remove_DS_Store):
if os.path.isfile('caltech101.h5'):
print('File exists already')
return
else:
# the name of each dir is the name of a class
classes = os.listdir(dir_name)
if remove_DS_Store:
classes.pop(0) # removes .DS_Store - may not be used on other terminals
# need the dtype of y in order to initialize h5 dataset
s = ''
key_type_y = s.join(['S', str(len(max(classes, key=len)))])
classes = np.array(classes, dtype=key_type_y)
# number of chunks in which the dataset must be divided
nb_chunks = 2
nb_chunks_loaded = 0
prev_chunk_length = 0
# open file and allocating a dataset
f = h5py.File('caltech101.h5', 'a')
imgs = f.create_dataset('images', shape=(9144, 240, 180, 3), dtype='uint8')
labels = f.create_dataset('labels', shape=(9144,), dtype=key_type_y)
for class_sublist in np.array_split(classes, nb_chunks):
# loading chunk by chunk in a function to avoid memory overhead
prev_chunk_length = load_chunk(imgs, labels, class_sublist, nb_chunks_loaded, key_type_y, prev_chunk_length)
nb_chunks_loaded += 1
f.close()
print('Images and labels saved to \'caltech101.h5\'')
return
dir_name = '../Datasets/Caltech101'
write_to_file(remove_DS_Store=True)
Das funktioniert ganz gut, und auch das Lesen ist eigentlich schnell genug. Das Problem ist, dass ich den Datensatz mischen muss.
Beobachtungen:
die Daten-Set Objekte Schlurfen: offensichtlich seeeehr langsam, weil sie auf der Festplatte sind.
Erstellen Sie ein Array von gemischten Indizes und verwenden Sie erweiterte Indexerstellung. Dies bedeutet ein langsameres Lesen der Datei.
Mischen vor dem Schreiben in die Datei wäre nett, Problem: Ich habe immer nur etwa die Hälfte des Datensatzes im Speicher. Ich würde ein falsches Mischen bekommen.
Können Sie sich einen Weg vorstellen, vor dem Schreiben zu mischen? Ich bin auch offen für Lösungen, die den Schreibprozess überdenken, solange sie nicht viel Speicher verbrauchen.
Das Problem dieser Ansatz ist, dass der Name der Verzeichnisse meine Etiketten sind, sollte ich ein Kartenbild erstellen -> Label. Ok, du antwortest mir gleich nach: D – iacolippo
Ich habe ein Beispiel hinzugefügt, wie du die ID und das Label vom Pfad abrufen kannst. Habe gerade gemerkt, dass du die Labels auch (natürlich) speichern willst :) – thertweck
Es funktioniert! Vielen Dank – iacolippo