¿Cómo combinar dos matrices de números grandes si la división no resuelve el error de memoria?

Tengo dos arreglos numpy container1 y container2 donde container1.shape = (900,4000) y container2.shape = (5000,4000) . vstack usando los resultados de vstack en un MemoryError . Después de buscar en las antiguas preguntas publicadas aquí, traté de fusionarlas utilizando el slicing esta manera:

 mergedContainer = numpy.vstack((container1, container2[:1000])) mergedContainer = numpy.vstack((mergedContainer, container[1000:2500])) mergedContainer = numpy.vstack((mergedContainer, container[2500:3000])) 

pero después de esto, incluso si lo hago:

 mergedContainer = numpy.vstack((mergedContainer, container[3000:3100])) 

se traduce en MemoryError .

Estoy usando Python 3.4.3 (32-Bit) y me gustaría resolverlo sin cambiar a 64-Bit .

Cada vez que llama a np.vstack NumPy tiene que asignar espacio para una nueva matriz. Así que si decimos que 1 fila requiere 1 unidad de memoria.

 np.vstack([container, container2]) 

Requiere un adicional de 900+5000 unidades de memoria. Además, antes de que ocurra la asignación, Python necesita mantener espacio para el antiguo mergedContainer (si existe), así como espacio para el nuevo mergedContainer . Así que construir mergedContainer iterativa con segmentos realmente requiere más memoria que intentar comstackrlo con una sola llamada a np.vstack .

Construyéndolo iterativamente:

 | total | mergedContainer | container1 | container2 | temp | | |-------+-----------------+------------+------------+------+----------------------------------------------------------------------| | 7800 | 1900 | 900 | 5000 | 0 | mergedContainer = np.vstack((container1, container2[:1000])) | | 11200 | 3400 | 900 | 5000 | 1900 | mergedContainer = np.vstack((mergedContainer, container[1000:2500])) | | 13200 | 3900 | 900 | 5000 | 3400 | mergedContainer = np.vstack((mergedContainer, container[2500:3000])) | 

Construyéndolo desde una sola llamada a np.vstack:

 | total | mergedContainer | container1 | container2 | temp | | |-------+-----------------+------------+------------+------+-------------------------------------------------------| | 11800 | 5900 | 900 | 5000 | 0 | mergedContainer = np.vstack((container1, container2)) | 

Sin embargo, podemos hacerlo aún mejor. En lugar de llamar a np.vstack repetidamente, asigne todo el espacio que sea necesario desde el principio y escriba en él el contenido de container1 y container2 . En otras palabras, evite asignar dos arreglos dispares container1 y container2 si sabe que eventualmente desea combinarlos.

 container = np.empty((5900, 4000)) 

Tenga en cuenta que los segmentos básicos, como el container[:900] siempre devuelven vistas , y las vistas no requieren esencialmente memoria adicional. Así que podrías definir container1 y container2 así:

 container1 = container[:900] container2 = container[900:] 

y luego asignar valores en su lugar . Esto modifica el container :

 container1[:] = ... container2[:] = ... 

Por lo tanto su requerimiento de memoria se mantendría alrededor de 5900 unidades.


Por ejemplo,

 import numpy as np np.random.seed(2015) container = np.empty((5, 4), dtype='int') container1 = container[:2] container2 = container[2:] container1[:] = np.random.randint(10, size=(2,4)) container2[:] = np.random.randint(1000, size=(3,4)) print(container) 

rendimientos

 [[ 2 2 9 6] [ 8 5 7 8] [112 70 487 124] [859 8 275 936] [317 134 393 909]] 

mientras que solo requiere espacio para una matriz de forma (5, 4), y espacio utilizado temporalmente para las matrices aleatorias.

Por lo tanto, no tendría que cambiar mucho su código para ahorrar memoria. Sólo configúralo con

 container = np.empty((5900, 4000)) container1 = container[:900] container2 = container[900:] 

y luego usar

 container1[:] = ... 

en lugar de

 container1 = ... 

para asignar valores en el lugar . (O, por supuesto, podría escribir directamente en el container ).