Quali sono i vantaggi di NumPy rispetto ai normali elenchi Python?


466

Quali sono i vantaggi di NumPy rispetto ai normali elenchi Python?

Ho circa 100 serie di mercati finanziari e ho intenzione di creare un array cubo di 100x100x100 = 1 milione di celle. Starò regredendo (3 variabili) ogni x con ogni y e z, per riempire l'array con errori standard.

Ho sentito che per "matrici di grandi dimensioni" dovrei usare NumPy in contrapposizione agli elenchi Python, per motivi di prestazioni e scalabilità. Il fatto è che conosco le liste di Python e sembrano funzionare per me.

Quali saranno i vantaggi se passerò a NumPy?

E se avessi 1000 serie (ovvero 1 miliardo di celle in virgola mobile nel cubo)?

Risposte:


727

Gli array di NumPy sono più compatti degli elenchi Python: un elenco di elenchi come descritto in Python richiederebbe almeno 20 MB o giù di lì, mentre un array 3D NumPy con float a precisione singola nelle celle si adatterebbe in 4 MB. Anche l'accesso alla lettura e alla scrittura di elementi è più veloce con NumPy.

Forse non ti interessa così tanto per solo un milione di celle, ma sicuramente lo faresti per un miliardo di celle: nessuno dei due approcci si adatterebbe in un'architettura a 32 bit, ma con build a 64 bit NumPy sarebbe scappare con circa 4 GB Python da solo avrebbe bisogno di almeno circa 12 GB (molti puntatori di dimensioni doppie) - un hardware molto più costoso!

La differenza è dovuta principalmente alla "indirettezza": un elenco Python è un array di puntatori agli oggetti Python, almeno 4 byte per puntatore più 16 byte anche per l'oggetto Python più piccolo (4 per il puntatore del tipo, 4 per il conteggio dei riferimenti, 4 per valore - e gli allocatori di memoria arrotondano a 16). Un array NumPy è un array di valori uniformi: i numeri a precisione singola richiedono 4 byte ciascuno, quelli a precisione doppia, 8 byte. Meno flessibile, ma paghi sostanzialmente per la flessibilità degli elenchi Python standard!


Ho provato a usare "sys.getsizeof ()" per confrontare le dimensioni degli elenchi Python e degli array NumPy con lo stesso numero di elementi e non sembra indicare che gli array NumPy fossero molto più piccoli. È questo il caso o sys.getsizeof () ha problemi a capire quanto è grande un array NumPy?
Jack Simpson,

3
@JackSimpson getsizeofnon è affidabile. La documentazione afferma chiaramente che: viene presa in considerazione solo il consumo di memoria direttamente attribuito all'oggetto, non il consumo di memoria degli oggetti a cui fa riferimento. Ciò significa che se si hanno elenchi python nidificati, la dimensione degli elementi non viene presa in considerazione.
Bakuriu,

4
getsizeofin un elenco ti dice solo quanta RAM consuma l'oggetto elenco stesso e la RAM consumata dai puntatori nel suo array di dati, non ti dice quanta RAM viene consumata dagli oggetti a cui fanno riferimento quei puntatori.
PM 2Ring

@AlexMartelli, potresti farmi sapere dove prendi questi numeri?
lmiguelvargasf,

Solo un avvertimento, la tua stima sulla dimensione dell'elenco Python equivalente dell'elenco di elenchi è disattivata. L'array numpy da 4 GB di C floats (4 byte) si tradurrebbe in qualcosa di più vicino a 32 GB di valore di lists e Python floats (che in realtà sono C doubles), non 12 GB; ognuna floatsu 64 bit Python occupa ~ 24 byte (supponendo che non ci siano perdite di allineamento nell'allocatore), più altri 8 byte listper contenere il riferimento (e che ignora le sovrallocazioni e le intestazioni degli oggetti per gli liststessi, che potrebbero aggiungere un altro GB a seconda di esattamente quanta sovrallocazione si verifica).
ShadowRanger

232

NumPy non è solo più efficiente; è anche più conveniente. Ottieni molte operazioni vettoriali e matrici gratuitamente, che a volte consentono di evitare lavori inutili. E sono anche implementati in modo efficiente.

Ad esempio, è possibile leggere il cubo direttamente da un file in un array:

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

Somma lungo la seconda dimensione:

s = x.sum(axis=1)

Trova quali celle sono al di sopra di una soglia:

(x > 0.5).nonzero()

Rimuovi ogni sezione indicizzata lungo la terza dimensione:

x[:, :, ::2]

Inoltre, molte utili librerie funzionano con gli array NumPy. Ad esempio, librerie di analisi statistica e visualizzazione.

Anche se non hai problemi di prestazioni, vale la pena imparare NumPy.


Grazie - hai fornito un altro buon motivo nel tuo terzo esempio, poiché in effetti cercherò celle sopra la soglia. Inoltre, stavo caricando da sqlLite. L'approccio del file sarà molto più efficiente.
Thomas Browne,

112

Alex ha menzionato l'efficienza della memoria e Roberto menziona la convenienza, e questi sono entrambi aspetti positivi. Per qualche altra idea, menzionerò velocità e funzionalità .

Funzionalità: sei molto integrato con NumPy, FFT, convoluzioni, ricerca veloce, statistiche di base, algebra lineare, istogrammi, ecc. E davvero, chi può vivere senza FFT?

Velocità: ecco un test su come fare una somma su un elenco e un array NumPy, dimostrando che la somma sull'array NumPy è 10 volte più veloce (in questo test - il chilometraggio può variare).

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))

che sui miei sistemi (mentre eseguo un backup) fornisce:

numpy: 3.004e-05
list:  5.363e-04

44

Ecco una bella risposta dalle FAQ sul sito Web di scipy.org :

Quali vantaggi offrono gli array NumPy rispetto agli elenchi Python (nidificati)?

Gli elenchi di Python sono efficienti contenitori per tutti gli usi. Supportano l'inserimento, l'eliminazione, l'aggiunta e la concatenazione (abbastanza) efficienti, e la comprensione dell'elenco di Python li rende facili da costruire e manipolare. Tuttavia, hanno alcune limitazioni: non supportano operazioni "vettorializzate" come addizione e moltiplicazione elementally, e il fatto che possano contenere oggetti di tipi diversi significa che Python deve memorizzare informazioni sul tipo per ogni elemento ed eseguire codice di dispacciamento del tipo quando si opera su ciascun elemento. Ciò significa anche che pochissime operazioni sugli elenchi possono essere eseguite da efficienti cicli C: ogni iterazione richiederebbe controlli del tipo e altri libri contabili dell'API Python.


9

Tutti hanno messo in evidenza quasi tutte le principali differenze tra l'array numpy e l'elenco python, li descriverò qui:

  1. Le matrici Numpy hanno una dimensione fissa al momento della creazione, a differenza delle liste Python (che possono crescere dinamicamente). La modifica delle dimensioni di ndarray creerà un nuovo array ed eliminerà l'originale.

  2. Tutti gli elementi di un array Numpy devono essere dello stesso tipo di dati (possiamo avere anche il tipo eterogeneo ma ciò non ti consentirà operazioni matematiche) e quindi avrà le stesse dimensioni in memoria

  3. Le matrici Numpy sono progressi facilitati matematici e altri tipi di operazioni su un gran numero di dati. In genere, tali operazioni vengono eseguite in modo più efficiente e con meno codice di quanto sia possibile utilizzando sequenze di python

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.