una tutorial transpuesta que multiplicar matriz matrices espaƱol elementos array agregar python numpy pickle binary-data preserve

python - tutorial - La mejor manera de conservar matrices numpy en el disco



que es un array en python (6)

¡Ahora hay un clon de pickle basado en HDF5 llamado hickle !

https://github.com/telegraphic/hickle

import hickle as hkl data = { ''name'' : ''test'', ''data_arr'' : [1, 2, 3, 4] } # Dump data to file hkl.dump( data, ''new_data_file.hkl'' ) # Load data from file data2 = hkl.load( ''new_data_file.hkl'' ) print( data == data2 )

EDITAR:

También existe la posibilidad de "extraer" directamente en un archivo comprimido haciendo:

import pickle, gzip, lzma, bz2 pickle.dump( data, gzip.open( ''data.pkl.gz'', ''wb'' ) ) pickle.dump( data, lzma.open( ''data.pkl.lzma'', ''wb'' ) ) pickle.dump( data, bz2.open( ''data.pkl.bz2'', ''wb'' ) )

Apéndice

import numpy as np import matplotlib.pyplot as plt import pickle, os, time import gzip, lzma, bz2, h5py compressions = [ ''pickle'', ''h5py'', ''gzip'', ''lzma'', ''bz2'' ] labels = [ ''pickle'', ''h5py'', ''pickle+gzip'', ''pickle+lzma'', ''pickle+bz2'' ] size = 1000 data = {} # Random data data[''random''] = np.random.random((size, size)) # Not that random data data[''semi-random''] = np.zeros((size, size)) for i in range(size): for j in range(size): data[''semi-random''][i,j] = np.sum(data[''random''][i,:]) + np.sum(data[''random''][:,j]) # Not random data data[''not-random''] = np.arange( size*size, dtype=np.float64 ).reshape( (size, size) ) sizes = {} for key in data: sizes[key] = {} for compression in compressions: if compression == ''pickle'': time_start = time.time() pickle.dump( data[key], open( ''data.pkl'', ''wb'' ) ) time_tot = time.time() - time_start sizes[key][''pickle''] = ( os.path.getsize( ''data.pkl'' ) * 10**(-6), time_tot ) os.remove( ''data.pkl'' ) elif compression == ''h5py'': time_start = time.time() with h5py.File( ''data.pkl.{}''.format(compression), ''w'' ) as h5f: h5f.create_dataset(''data'', data=data[key]) time_tot = time.time() - time_start sizes[key][compression] = ( os.path.getsize( ''data.pkl.{}''.format(compression) ) * 10**(-6), time_tot) os.remove( ''data.pkl.{}''.format(compression) ) else: time_start = time.time() pickle.dump( data[key], eval(compression).open( ''data.pkl.{}''.format(compression), ''wb'' ) ) time_tot = time.time() - time_start sizes[key][ labels[ compressions.index(compression) ] ] = ( os.path.getsize( ''data.pkl.{}''.format(compression) ) * 10**(-6), time_tot ) os.remove( ''data.pkl.{}''.format(compression) ) f, ax_size = plt.subplots() ax_time = ax_size.twinx() x_ticks = labels x = np.arange( len(x_ticks) ) y_size = {} y_time = {} for key in data: y_size[key] = [ sizes[key][ x_ticks[i] ][0] for i in x ] y_time[key] = [ sizes[key][ x_ticks[i] ][1] for i in x ] width = .2 viridis = plt.cm.viridis p1 = ax_size.bar( x-width, y_size[''random''] , width, color = viridis(0) ) p2 = ax_size.bar( x , y_size[''semi-random''] , width, color = viridis(.45)) p3 = ax_size.bar( x+width, y_size[''not-random''] , width, color = viridis(.9) ) p4 = ax_time.bar( x-width, y_time[''random''] , .02, color = ''red'') ax_time.bar( x , y_time[''semi-random''] , .02, color = ''red'') ax_time.bar( x+width, y_time[''not-random''] , .02, color = ''red'') ax_size.legend( (p1, p2, p3, p4), (''random'', ''semi-random'', ''not-random'', ''saving time''), loc=''upper center'',bbox_to_anchor=(.5, -.1), ncol=4 ) ax_size.set_xticks( x ) ax_size.set_xticklabels( x_ticks ) f.suptitle( ''Pickle Compression Comparison'' ) ax_size.set_ylabel( ''Size [MB]'' ) ax_time.set_ylabel( ''Time [s]'' ) f.savefig( ''sizes.pdf'', bbox_inches=''tight'' )

Estoy buscando una manera rápida de preservar grandes matrices numpy. Quiero guardarlos en el disco en formato binario, y luego volver a leerlos en la memoria relativamente rápido. cPickle no es lo suficientemente rápido, desafortunadamente.

Encontré numpy.savez y numpy.load . Pero lo extraño es que numpy.load carga un archivo npy en "memory-map". Eso significa que la manipulación regular de matrices realmente es lenta. Por ejemplo, algo como esto sería muy lento:

#!/usr/bin/python import numpy as np; import time; from tempfile import TemporaryFile n = 10000000; a = np.arange(n) b = np.arange(n) * 10 c = np.arange(n) * -0.5 file = TemporaryFile() np.savez(file,a = a, b = b, c = c); file.seek(0) t = time.time() z = np.load(file) print "loading time = ", time.time() - t t = time.time() aa = z[''a''] bb = z[''b''] cc = z[''c''] print "assigning time = ", time.time() - t;

más precisamente, la primera línea será realmente rápida, pero las líneas restantes que asignan las matrices a obj son ridículamente lentas:

loading time = 0.000220775604248 assining time = 2.72940087318

¿Hay alguna forma mejor de preservar las matrices numpy? Idealmente, quiero poder almacenar múltiples matrices en un archivo.


El tiempo de búsqueda es lento porque cuando usa mmap no carga el contenido de la matriz en la memoria cuando invoca load método de load . Los datos se cargan de manera diferida cuando se necesitan datos particulares. Y esto sucede en la búsqueda en tu caso. Pero la segunda búsqueda no será tan lenta.

Esta es una buena característica de mmap cuando tienes una gran matriz, no tienes que cargar datos completos en la memoria.

Para resolverlo puedes usar joblib puedes volcar cualquier objeto que quieras utilizando joblib.dump incluso dos o más numpy arrays , mira el ejemplo

firstArray = np.arange(100) secondArray = np.arange(50) # I will put two arrays in dictionary and save to one file my_dict = {''first'' : firstArray, ''second'' : secondArray} joblib.dump(my_dict, ''file_name.dat'')


He comparado el rendimiento (espacio y tiempo) con varias formas de almacenar matrices numpy. Pocos de ellos admiten matrices múltiples por archivo, pero tal vez sea útil de todos modos.

Los archivos Npy y binarios son realmente rápidos y pequeños para datos densos. Si los datos son escasos o muy estructurados, es posible que desee utilizar npz con compresión, lo que ahorrará mucho espacio pero le costará algo de tiempo de carga.

Si la portabilidad es un problema, el binario es mejor que npy. Si la legibilidad humana es importante, entonces tendrá que sacrificar mucho rendimiento, pero puede lograrse bastante bien usando csv (que también es muy portátil, por supuesto).

Más detalles y el código están disponibles en el repositorio github .


Otra posibilidad de almacenar matrices numpy de manera eficiente es Bloscpack :

#!/usr/bin/python import numpy as np import bloscpack as bp import time n = 10000000 a = np.arange(n) b = np.arange(n) * 10 c = np.arange(n) * -0.5 tsizeMB = sum(i.size*i.itemsize for i in (a,b,c)) / 2**20. blosc_args = bp.DEFAULT_BLOSC_ARGS blosc_args[''clevel''] = 6 t = time.time() bp.pack_ndarray_file(a, ''a.blp'', blosc_args=blosc_args) bp.pack_ndarray_file(b, ''b.blp'', blosc_args=blosc_args) bp.pack_ndarray_file(c, ''c.blp'', blosc_args=blosc_args) t1 = time.time() - t print "store time = %.2f (%.2f MB/s)" % (t1, tsizeMB / t1) t = time.time() a1 = bp.unpack_ndarray_file(''a.blp'') b1 = bp.unpack_ndarray_file(''b.blp'') c1 = bp.unpack_ndarray_file(''c.blp'') t1 = time.time() - t print "loading time = %.2f (%.2f MB/s)" % (t1, tsizeMB / t1)

y la salida para mi computadora portátil (una MacBook Air relativamente vieja con un procesador Core2):

$ python store-blpk.py store time = 0.19 (1216.45 MB/s) loading time = 0.25 (898.08 MB/s)

eso significa que puede almacenar muy rápido, es decir, el cuello de botella suele ser el disco. Sin embargo, como las relaciones de compresión son bastante buenas aquí, la velocidad efectiva se multiplica por las relaciones de compresión. Estos son los tamaños para estas matrices de 76 MB:

$ ll -h *.blp -rw-r--r-- 1 faltet staff 921K Mar 6 13:50 a.blp -rw-r--r-- 1 faltet staff 2.2M Mar 6 13:50 b.blp -rw-r--r-- 1 faltet staff 1.4M Mar 6 13:50 c.blp

Tenga en cuenta que el uso del compresor Blosc es fundamental para lograr esto. El mismo script pero usando ''clevel'' = 0 (es decir, deshabilitando la compresión):

$ python bench/store-blpk.py store time = 3.36 (68.04 MB/s) loading time = 2.61 (87.80 MB/s)

está claramente embotellado por el rendimiento del disco.


Soy un gran admirador de hdf5 para almacenar grandes matrices numpy. Hay dos opciones para tratar con hdf5 en python:

http://www.pytables.org/

http://www.h5py.org/

Ambos están diseñados para trabajar con matrices numpy de manera eficiente.


savez () guarda los datos en un archivo zip, puede tomar algún tiempo para comprimir y descomprimir el archivo. Puede usar la función save () y load ():

f = file("tmp.bin","wb") np.save(f,a) np.save(f,b) np.save(f,c) f.close() f = file("tmp.bin","rb") aa = np.load(f) bb = np.load(f) cc = np.load(f) f.close()

Para guardar varias matrices en un solo archivo, solo necesita abrir el archivo primero, y luego guardar o cargar las matrices en secuencia.