2017-10-13 2 views
0

Ich habe ein Problem mit der Berechnung des Mittelwerts eines Arrays in numpy, das für RAM (~ 100G) zu groß ist.Berechne den Mittelwert eines großen numpy-Arrays, das aus der hdf5-Datei memmapped ist


Ich habe in schaute np.memmap verwenden, aber leider ist mein Array als Datensatz in einer hdf5-Datei gespeichert. Und basierend auf dem, was ich versucht habe, akzeptiert np.memmap keine hdf5-Datensätze als Eingabe.
TypeError: coercing to Unicode: need string or buffer, Dataset found

Wie kann ich anrufen np.mean auf einem Memory-Mapped-Array von der Festplatte auf eine effiziente Art und Weise? Natürlich könnte ich Teile des Datensatzes durchlaufen, wo jeder Teil in den Speicher passt.
Allerdings fühlt sich das zu sehr wie ein Workaround an und ich bin mir auch nicht sicher, ob es die beste Leistung erzielen würde.


Hier ist ein Beispielcode:

data = np.randint(0, 255, 100000*10*10*10, dtype=np.uint8) 
data.reshape((100000,10,10,10)) # typically lot larger, ~100G 

hdf5_file = h5py.File('data.h5', 'w') 
hdf5_file.create_dataset('x', data=data, dtype='uint8') 

def get_mean_image(filepath): 
    """ 
    Returns the mean_array of a dataset. 
    """ 
    f = h5py.File(filepath, "r") 
    xs_mean = np.mean(f['x'], axis=0) # memory error with large enough array 

    return xs_mean 

xs_mean = get_mean_image('./data.h5') 
+1

ich gehen würde, voraus eine der von der 'h5py'-Datensatz lesen chunked tun. Lass das funktionieren. Dann können Sie testen, ob die Iteration wirklich Zeit kostet. Bei großen Arrays können die Kosten für die Speicherverwaltung die Iterationskosten übersteigen. – hpaulj

+0

Sie haben Recht, es kostet eigentlich nicht so viel. Der einzige Fehler ist die Schleife, die Sie programmieren müssen, also ist es nicht so elegant. Vielen Dank! – 0vbb

Antwort

1

Wie hpaulj in den Kommentaren vorgeschlagen habe ich aufgeteilt nur die Mittelwertberechnung in mehreren Schritten.
Hier ist mein (vereinfacht) Code, wenn es für jemanden nützlich sein kann:

def get_mean_image(filepath): 
    """ 
    Returns the mean_image of a xs dataset. 
    :param str filepath: Filepath of the data upon which the mean_image should be calculated. 
    :return: ndarray xs_mean: mean_image of the x dataset. 
    """ 
    f = h5py.File(filepath, "r") 

    # check available memory and divide the mean calculation in steps 
    total_memory = 0.5 * psutil.virtual_memory() # In bytes. Take 1/2 of what is available, just to make sure. 
    filesize = os.path.getsize(filepath) 
    steps = int(np.ceil(filesize/total_memory)) 
    n_rows = f['x'].shape[0] 
    stepsize = int(n_rows/float(steps)) 

    xs_mean_arr = None 
    for i in xrange(steps): 
     if xs_mean_arr is None: # create xs_mean_arr that stores intermediate mean_temp results 
      xs_mean_arr = np.zeros((steps,) + f['x'].shape[1:], dtype=np.float64) 

     if i == steps-1: # for the last step, calculate mean till the end of the file 
      xs_mean_temp = np.mean(f['x'][i * stepsize: n_rows], axis=0, dtype=np.float64) 
     else: 
      xs_mean_temp = np.mean(f['x'][i*stepsize : (i+1) * stepsize], axis=0, dtype=np.float64) 
     xs_mean_arr[i] = xs_mean_temp 

    xs_mean = np.mean(xs_mean_arr, axis=0, dtype=np.float64).astype(np.float32) 

    return xs_mean 
+0

Der Mittelwert der Mittelwerte ist nur dann gleich dem wahren Mittelwert, wenn alle Buckets die gleiche Größe haben. Dein letzter Eimer ist nicht, also verzerrt er deine Ergebnisse leicht. – pvlkmrv

Verwandte Themen