Matrici molto grandi che utilizzano Python e NumPy


86

NumPy è una libreria estremamente utile e dal suo utilizzo ho scoperto che è in grado di gestire facilmente matrici abbastanza grandi (10000 x 10000), ma inizia a lottare con qualcosa di molto più grande (cercando di creare una matrice di 50000 x 50000 non riesce). Ovviamente, ciò è dovuto agli enormi requisiti di memoria.

Esiste un modo per creare nativamente enormi matrici in NumPy (diciamo 1 milione per 1 milione) in qualche modo (senza avere diversi terrabyte di RAM)?

Risposte:


91

PyTables e NumPy sono la strada da percorrere.

PyTables memorizzerà i dati su disco in formato HDF, con compressione opzionale. I miei set di dati spesso ottengono una compressione 10x, il che è utile quando si tratta di decine o centinaia di milioni di righe. È anche molto veloce; il mio laptop di 5 anni può analizzare i dati eseguendo l'aggregazione GROUP BY simile a SQL a 1.000.000 di righe / secondo. Non male per una soluzione basata su Python!

Accedere ai dati come ricarray di NumPy è di nuovo semplice come:

data = table[row_from:row_to]

La libreria HDF si occupa di leggere i blocchi di dati rilevanti e di convertirli in NumPy.


4
Quindi devi ancora suddividere i dati in blocchi per l'elaborazione? È solo un modo per semplificare la conversione da e verso i file su disco?
endolith

C'è qualche possibilità che potresti espandere la tua risposta con un po 'più di chiarezza e alcuni esempi?
Adam B

56

numpy.arraysono destinati a vivere nella memoria. Se vuoi lavorare con matrici più grandi della tua RAM, devi aggirare questo. Ci sono almeno due approcci che puoi seguire:

  1. Prova una rappresentazione a matrice più efficiente che sfrutti qualsiasi struttura speciale delle tue matrici. Ad esempio, come altri hanno già sottolineato, esistono strutture dati efficienti per matrici sparse (matrici con molti zeri), come scipy.sparse.csc_matrix.
  2. Modifica il tuo algoritmo per lavorare sulle sottomatrici . È possibile leggere dal disco solo i blocchi della matrice attualmente utilizzati nei calcoli. Gli algoritmi progettati per essere eseguiti su cluster di solito funzionano a blocchi, poiché i dati vengono diffusi su computer diversi e passati solo quando necessario. Ad esempio, l'algoritmo Fox per la moltiplicazione di matrici (file PDF) .

4
3- Entra nel paradigma dei Big Data e studia soluzioni come MapReduce
Medeiros

Per il numero 2, come decidi quanto sono grandi i tuoi pezzi? C'è un modo per misurare la quantità di memoria libera e dimensionare i blocchi in base a questo?
endolith

30

Dovresti essere in grado di utilizzare numpy.memmap per mappare in memoria un file su disco. Con le nuove macchine Python e 64 bit, dovresti avere lo spazio degli indirizzi necessario, senza caricare tutto in memoria. Il sistema operativo dovrebbe gestire solo mantenere una parte del file in memoria.


19
Puoi fornire un esempio di come usarlo per fare qualcosa che non può entrare nella memoria?
endolith

24

Per gestire matrici sparse, è necessario il scipypacchetto che si trova sopra numpy- vedere qui per maggiori dettagli sulle opzioni di matrice sparse che scipyti offre.


11

Il post di Stefano Borini mi ha fatto capire a che punto è già questo genere di cose.

Questo è. Sembra che faccia praticamente quello che vuoi. HDF5 ti consentirà di archiviare set di dati molto grandi, quindi di accedervi e utilizzarli nello stesso modo in cui NumPy fa.


9
Una scelta migliore potrebbe essere PyTables. È di livello superiore rispetto alla funzionalità HDF5 di base (H5Py è poco più dell'API di basso livello accessibile da Python). Anche la versione 2.2 beta della scorsa settimana ha strumenti per questo problema: pytables.org/moin/ReleaseNotes/Release_2.2b1 Aggiunto Expr, una classe [che] può valutare espressioni (come '3 * a + 4 * b') che operano su grandi arbitrari array ottimizzando le risorse [...]. È simile al pacchetto Numexpr, ma oltre agli oggetti NumPy, accetta anche array omogenei basati su disco, come gli oggetti Array, CArray, EArray e Column PyTables.
AFoglia

5

Assicurati di utilizzare un sistema operativo a 64 bit e una versione a 64 bit di Python / NumPy. Si noti che su architetture a 32 bit è possibile indirizzare in genere 3 GB di memoria (con circa 1 GB perso per I / O mappato in memoria e simili).

Con 64 bit e array di oggetti più grandi della RAM disponibile puoi farla franca con la memoria virtuale, anche se le cose diventeranno più lente se devi scambiare. Inoltre, le mappe di memoria (vedere numpy.memmap) sono un modo per lavorare con file enormi su disco senza caricarli in memoria, ma ancora una volta, è necessario disporre di uno spazio di indirizzi a 64 bit con cui lavorare affinché sia ​​di grande utilità. PyTables farà la maggior parte di questo anche per te.



4

A volte una semplice soluzione consiste nell'usare un tipo personalizzato per gli elementi della matrice. In base alla gamma di numeri di cui hai bisogno, puoi utilizzare un manuale dtypee appositamente più piccolo per i tuoi articoli. Poiché Numpy considera il tipo più grande per oggetto per impostazione predefinita, questa potrebbe essere un'idea utile in molti casi. Ecco un esempio:

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

E con il tipo personalizzato:

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

3

Stai chiedendo come gestire una matrice di 2.500.000.000 di elementi senza terabyte di RAM?

Il modo per gestire 2 miliardi di elementi senza 8 miliardi di byte di RAM è non mantenere la matrice in memoria.

Ciò significa algoritmi molto più sofisticati per recuperarlo dal file system in pezzi.


7
Non vero. Se il 99,99% (per un esempio realistico) degli elementi è zero, allora tutti i dati della matrice possono essere conservati in memoria. Non è necessario utilizzare fino a 4 byte per ogni zero, quando puoi semplicemente memorizzare un elenco di (row, column, value)quelle voci che esistono.
Eric Wilson

6
@EricWilson: dove nella domanda suggeriva che la matrice fosse scarsa? Mi mancava totalmente. Potete fornire il preventivo?
S.Lott


1

Per quanto ne so su numpy, no, ma potrei sbagliarmi.

Posso proporvi questa soluzione alternativa: scrivere la matrice sul disco e accedervi in ​​blocchi. Ti suggerisco il formato di file HDF5. Se ne hai bisogno in modo trasparente, puoi reimplementare l'interfaccia ndarray per impaginare la matrice memorizzata su disco. Fai attenzione se modifichi i dati per sincronizzarli di nuovo sul disco.


E se volessi accedere a un'intera matrice di 57600 per 57600?
Gunjan naik
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.