2009-06-28 49 views
73

NumPy es una biblioteca extremadamente útil, y al usarla he descubierto que es capaz de manejar matrices que son bastante grandes (10000 x 10000) fácilmente, pero comienza a tener problemas con algo mucho más grande (tratando de crear una matriz de 50000 x 50000 falla). Obviamente, esto se debe a los requisitos de memoria masiva.Matrices muy grandes usando Python y NumPy

¿Existe alguna manera de crear enormes matrices de forma nativa en NumPy (digamos 1 millón por 1 millón) de alguna manera (sin tener varios terrabytes de RAM)?

+16

¿Qué está tratando de hacer con ellos (aparte de la creación de ellos)? – Rook

Respuesta

1

Por lo general, cuando trabajamos con matrices grandes las implementamos como Sparse Matrices.

No sé si numpy admite matrices dispersas pero en su lugar encontré this.

1

Por lo que sé sobre numpy, no, pero podría estar equivocado.

Puedo proponerle esta solución alternativa: escriba la matriz en el disco y acceda en trozos. Te sugiero el formato de archivo HDF5. Si lo necesita de forma transparente, puede volver a implementar la interfaz ndarray para paginar la matriz almacenada en el disco en la memoria. Tenga cuidado si modifica los datos para volver a sincronizarlos en el disco.

+0

¿Qué sucede si quiero acceder a una matriz completa de 57600 por 57600? – user3515225

29

Debería poder usar numpy.memmap para mapear en memoria un archivo en el disco. Con la máquina más nueva de python y 64 bits, debe tener el espacio de direcciones necesario, sin cargar todo en la memoria. El sistema operativo debe manejar solo para mantener parte del archivo en la memoria.

+10

¿Puedes darnos un ejemplo de cómo usarlo para hacer algo que no cabe en la memoria? – endolith

24

Para manejar matrices dispersas, se necesita el paquete scipy que se encuentra en la parte superior de numpy - ver here para más detalles acerca de las opciones de escasa-matriz que le da scipy.

4

¿Está preguntando cómo manejar una matriz de elementos de 2,500,000,000 sin terabytes de RAM?

La forma de manejar 2 mil millones de elementos sin 8 mil millones de bytes de RAM es no mantener la matriz en la memoria.

Eso significa algoritmos mucho más sofisticados para obtenerlo del sistema de archivos en piezas.

+6

No es cierto. Si el 99.99% (para un ejemplo realista) de los elementos son cero, entonces todos los datos de la matriz pueden mantenerse en la memoria. No es necesario utilizar hasta 4 bytes por cada cero, cuando solo puede almacenar una lista de '(fila, columna, valor)' para aquellas entradas que sí existen. –

+3

@EricWilson: ¿En qué parte de la pregunta sugería que la matriz era escasa? Eché de menos eso. ¿Puedes proporcionar el presupuesto? –

51

numpy.array s están destinados a vivir en la memoria. Si quieres trabajar con matrices más grandes que tu RAM, tienes que trabajar en eso. Hay al menos dos enfoques que puede seguir:

  1. intenta una representación matricial más eficiente que explota ninguna estructura especial que tienen sus matrices. Por ejemplo, como otros ya han señalado, existen estructuras de datos eficientes para matrices dispersas (matrices con muchos ceros), como scipy.sparse.csc_matrix.
  2. Modifique su algoritmo para trabajar en submatrices. Puede leer desde el disco solo los bloques de matriz que se usan actualmente en los cálculos. Los algoritmos diseñados para ejecutarse en clusters generalmente funcionan en bloque, ya que los datos se distribuyen en diferentes computadoras y se pasan solo cuando es necesario. Por ejemplo, the Fox algorithm for matrix multiplication (PDF file).
+4

3- Ingrese al paradigma de Big Data y estudie soluciones como MapReduce – Medeiros

+0

Para el número 2, ¿cómo decide qué tan grande es para hacer sus trozos? ¿Hay alguna manera de medir la cantidad de memoria libre y dimensionar sus fragmentos según eso? – endolith

11

Stefano Borini's post me hicieron ver hasta qué punto este tipo de cosas ya están hechas.

This is it. Parece que hace básicamente lo que quiere.HDF5 le permitirá almacenar conjuntos de datos muy grandes, y luego acceder a ellos y usarlos de la misma forma que lo hace NumPy.

+9

Una mejor opción podría ser PyTables. Es un nivel más alto que la funcionalidad básica HDF5 (H5Py es poco más que la API de bajo nivel accesible desde Python). Además, la versión 2.2 beta de la semana pasada tiene herramientas para este problema: http://www.pytables.org/moin/ReleaseNotes/Release_2.2b1 Se agregó Expr, una clase [que] puede evaluar expresiones (como '3 * a + 4 * b ') que operan en arreglos grandes arbitrarios mientras optimizan los recursos [...]. Es similar al paquete Numexpr, pero además de los objetos NumPy, también acepta matrices homogéneas basadas en disco, como los objetos Array, CArray, EArray y Columna PyTables. – AFoglia

84

PyTables y NumPy son el camino a seguir.

PyTables almacenará los datos en el disco en formato HDF, con compresión opcional. Mis conjuntos de datos a menudo tienen una compresión de 10x, que es útil cuando se trata de decenas o cientos de millones de filas. También es muy rápido; mi computadora portátil de 5 años de antigüedad puede atravesar los datos haciendo una agregación GROUP BY similar a SQL en 1,000,000 de filas/segundo. ¡No está mal para una solución basada en Python!

Acceso a los datos como un nuevo NumPy recArray es tan simple como:

data = table[row_from:row_to] 

La biblioteca HDF se encarga de la lectura en los trozos de datos relevantes y convertir a NumPy.

+63

¿Desea mostrar un ejemplo de código rápido de este enfoque? – Ivan

+2

¿Entonces todavía tiene que dividir los datos en pedazos para procesarlos? ¿Es solo una forma de simplificar la conversión ay desde los archivos de disco? – endolith

5

Asegúrese de estar utilizando un sistema operativo de 64 bits y una versión de 64 bits de Python/NumPy. Tenga en cuenta que en las arquitecturas de 32 bits puede abordar típicamente 3 GB de memoria (con aproximadamente 1 GB de pérdida de E/S asignadas a la memoria, etc.).

Con arreglos de 64 bits y cosas más grandes que la RAM disponible, puede salirse con la memoria virtual, aunque las cosas se ralentizarán si tiene que cambiar. Además, los mapas de memoria (vea numpy.memmap) son una forma de trabajar con archivos enormes en el disco sin cargarlos en la memoria, pero nuevamente, necesita tener un espacio de direcciones de 64 bits para que esto sea de mucha utilidad. PyTables hará la mayor parte de esto por ti también.

2

A veces, una solución simple es usar un tipo personalizado para los elementos de su matriz. Según el rango de números que necesita, puede usar un manual dtype y especialmente más pequeño para sus artículos. Debido a que Numpy considera el tipo más grande para el objeto por defecto, esta podría ser una buena idea en muchos casos. He aquí un ejemplo:

In [70]: a = np.arange(5) 

In [71]: a[0].dtype 
Out[71]: dtype('int64') 

In [72]: a.nbytes 
Out[72]: 40 

In [73]: a = np.arange(0, 2, 0.5) 

In [74]: a[0].dtype 
Out[74]: dtype('float64') 

In [75]: a.nbytes 
Out[75]: 32 

Y con el tipo de encargo:

In [80]: a = np.arange(5, dtype=np.int8) 

In [81]: a.nbytes 
Out[81]: 5 

In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16) 

In [78]: a.nbytes 
Out[78]: 8 
Cuestiones relacionadas