Matrices muy grandes usando Python y NumPy

NumPy es una biblioteca extremadamente útil, y al usarla he encontrado que es capaz de manejar matrices que son bastante grandes (10000 x 10000) fácilmente, pero comienza a luchar 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.

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

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 obtienen una compresión 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 puede procesar datos haciendo una agregación de GROUP BY similar a SQL a 1,000,000 de filas / segundo. ¡No está mal para una solución basada en Python!

Acceder a los datos como una nueva versión de NumPy es tan simple como:

data = table[row_from:row_to] 

La biblioteca HDF se encarga de leer los fragmentos de datos relevantes y de convertirlos a NumPy.

numpy.array s están destinados a vivir en la memoria. Si desea trabajar con matrices más grandes que su RAM, debe trabajar alrededor de eso. Hay al menos dos enfoques que puede seguir:

  1. Pruebe una representación matricial más eficiente que explote cualquier estructura especial que tengan sus matrices. Por ejemplo, como ya lo han señalado otros, hay estructuras de datos eficientes para matrices dispersas (matrices con muchos ceros), como scipy.sparse.csc_matrix .
  2. Modifica tu algoritmo para trabajar en submatrices . Puede leer desde el disco solo los bloques de matriz que se están utilizando actualmente en los cálculos. Los algoritmos diseñados para ejecutarse en grupos generalmente funcionan en bloque, ya que los datos se distribuyen en diferentes equipos y se pasan solo cuando se necesitan. Por ejemplo, el algoritmo de Fox para la multiplicación de matrices (archivo PDF) .

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

Para manejar matrices dispersas, necesita el paquete scipy que se encuentra encima de numpy ; consulte aquí para obtener más detalles sobre las opciones de matriz scipy que scipy ofrece scipy .

El post de Stefano Borini me hizo ver qué tan avanzado está este tipo de cosas.

Eso es todo. Parece hacer básicamente lo que quieres. HDF5 te permitirá almacenar conjuntos de datos muy grandes y luego acceder y usarlos de la misma manera que lo hace NumPy.

Asegúrese de utilizar un sistema operativo de 64 bits y una versión de Python / NumPy de 64 bits. Tenga en cuenta que en las architectures de 32 bits puede ocuparse normalmente de 3 GB de memoria (con aproximadamente 1 GB perdidos en la memoria asignada de E / S y tal)

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

Es un poco alfa, pero http://blaze.pydata.org/ parece estar trabajando para resolver esto.

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

La manera 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 obtenerlos del sistema de archivos en partes.

A veces, una solución simple es usar un tipo personalizado para sus elementos de matriz. Según el rango de números que necesita, puede usar un tipo de manual y especialmente más pequeño para sus artículos. Debido a que Numpy considera el tipo más grande de objeto por defecto, esta podría ser una idea útil en muchos casos. Aquí hay 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 tipo personalizado:

 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 

Generalmente cuando tratamos con matrices grandes las implementamos como Matrices dispersas .

No sé si numpy soporta matrices dispersas pero encontré esto en su lugar.

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 a ella en trozos. Te sugiero el formato de archivo HDF5. Si lo necesita de forma transparente, puede volver a implementar la interfaz ndarray para paginar en la memoria la matriz almacenada en el disco. Tenga cuidado si modifica los datos para sincronizarlos nuevamente en el disco.

Puede ejecutar su código en Google Colab . Google Colab es un servicio gratuito en la nube y ahora admite GPU gratis. Podría construir una matriz (870199 * 14425) en Google Colab que no podría ejecutar en mi PC.