Jakie są zalety NumPy w porównaniu ze zwykłymi listami w języku Python?

466

Jakie są zalety NumPy w porównaniu ze zwykłymi listami w języku Python?

Mam około 100 serii rynków finansowych i zamierzam utworzyć tablicę kostek o wymiarach 100 x 100 x 100 = 1 milion komórek. Będę regresował (3-zmienny) każdy x przy każdym y i z, aby wypełnić tablicę standardowymi błędami.

Słyszałem, że w przypadku „dużych macierzy” powinienem używać NumPy w przeciwieństwie do list Pythona, ze względu na wydajność i skalowalność. Rzecz w tym, że znam listy Python i wydają się one dla mnie działać.

Jakie będą korzyści, jeśli przeprowadzę się do NumPy?

Co jeśli miałbym 1000 serii (czyli 1 miliard komórek zmiennoprzecinkowych w sześcianie)?

Thomas Browne
źródło

Odpowiedzi:

727

Tablice NumPy są bardziej kompaktowe niż listy Python - lista, którą opisujesz, w Pythonie zajmuje co najmniej 20 MB, podczas gdy tablica NumPy 3D z pływakami o pojedynczej precyzji w komórkach zmieściłaby się w 4 MB. Dostęp do czytania i pisania przedmiotów jest również szybszy dzięki NumPy.

Być może nie przejmujesz się tak bardzo zaledwie milionem komórek, ale zdecydowanie wolałbyś miliard komórek - żadne podejście nie pasowałoby do architektury 32-bitowej, ale przy 64-bitowych kompilacjach NumPy uciekłby z około 4 GB , Sam Python potrzebowałby co najmniej około 12 GB (wiele wskaźników, które podwajają swój rozmiar) - znacznie droższy sprzęt!

Różnica wynika głównie z „pośredniczości” - lista Python to tablica wskaźników do obiektów Python, co najmniej 4 bajty na wskaźnik plus 16 bajtów nawet dla najmniejszego obiektu Python (4 dla wskaźnika typu, 4 dla liczby referencji, 4 dla wartości - a alokatory pamięci zaokrąglają w górę do 16). Tablica NumPy to tablica jednolitych wartości - liczby o pojedynczej precyzji zajmują 4 bajty, o podwójnej precyzji, 8 bajtów. Mniej elastyczny, ale płacisz znacznie za elastyczność standardowych list w języku Python!

Alex Martelli
źródło
Próbowałem użyć „sys.getsizeof ()” do porównania wielkości list w Pythonie i tablic NumPy z taką samą liczbą elementów i nie wydaje się, aby oznaczało to, że tablice NumPy były znacznie mniejsze. Czy tak jest w przypadku, czy sys.getsizeof () ma problemy z ustaleniem, jak duża jest tablica NumPy?
Jack Simpson
3
@JackSimpson getsizeofnie jest niezawodny. Dokumentacja wyraźnie stwierdza, że: Uwzględnia się tylko zużycie pamięci bezpośrednio przypisane do obiektu, a nie zużycie pamięci obiektów, do których się odnosi. Oznacza to, że jeśli zagnieżdżono listy python, rozmiar elementów nie jest brany pod uwagę.
Bakuriu
4
getsizeofna liście mówi tylko, ile pamięci RAM zużywa sam obiekt listy i pamięć RAM zużyta przez wskaźniki w swojej tablicy danych, nie mówi też, ile pamięci RAM zużywa obiekt, do którego odnoszą się te wskaźniki.
PM 2Ring
@AlexMartelli, czy możesz dać mi znać, skąd bierzesz te liczby?
lmiguelvargasf
Tylko heads-up, twoje oszacowanie wielkości równoważnej listy list w Pythonie jest wyłączone. Tablica numpy o pojemności 4 GB C float(4 bajty) tłumaczyłaby na coś bliższego 32 GB wartości lists i Pythona float(które w rzeczywistości są C doubles), a nie 12 GB; każdy floatna 64-bitowym Pythonie zajmuje ~ 24 bajtów (zakładając brak strat wyrównania w alokatorze), plus kolejne 8 bajtów w listcelu przechowywania referencji (i to ignoruje całkowitą alokację i nagłówki obiektów dla listsamych siebie, co może dodać kolejną GB w zależności od dokładnie ile zachodzi ogólna alokacja).
ShadowRanger,
232

NumPy jest nie tylko bardziej wydajny; jest to również wygodniejsze. Dostajesz za darmo wiele operacji wektorowych i macierzowych, które czasem pozwalają uniknąć niepotrzebnej pracy. I są również skutecznie wdrażane.

Na przykład możesz odczytać swoją kostkę bezpośrednio z pliku do tablicy:

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

Suma wzdłuż drugiego wymiaru:

s = x.sum(axis=1)

Znajdź, które komórki są powyżej progu:

(x > 0.5).nonzero()

Usuń każdy plasterek o indeksie parzystym wzdłuż trzeciego wymiaru:

x[:, :, ::2]

Ponadto wiele przydatnych bibliotek działa z tablicami NumPy. Na przykład biblioteki analizy statystycznej i biblioteki wizualizacji.

Nawet jeśli nie masz problemów z wydajnością, warto nauczyć się NumPy.

Roberto Bonvallet
źródło
Dzięki - podałeś kolejny dobry powód w trzecim przykładzie, ponieważ rzeczywiście będę przeszukiwał macierz w poszukiwaniu komórek powyżej progu. Ponadto ładowałem się z sqlLite. Podejście do plików będzie znacznie wydajniejsze.
Thomas Browne
112

Alex wspomniał o wydajności pamięci, a Roberto wspomniał o wygodzie, i to są dobre zalety. Aby uzyskać więcej pomysłów, wspomnę o szybkości i funkcjonalności .

Funkcjonalność: Masz wiele wbudowanych funkcji NumPy, FFT, zwojów, szybkiego wyszukiwania, podstawowych statystyk, algebry liniowej, histogramów itp. I naprawdę, kto może żyć bez FFT?

Szybkość: Oto test na sumę na liście i tablicy NumPy, pokazujący, że suma na tablicy NumPy jest 10 razy szybsza (w tym teście - przebieg może się różnić).

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,))

co w moich systemach (podczas gdy wykonuję kopię zapasową) daje:

numpy: 3.004e-05
list:  5.363e-04
tom10
źródło
44

Oto ładna odpowiedź z FAQ na stronie scipy.org :

Jakie zalety oferują tablice NumPy w porównaniu z (zagnieżdżonymi) listami w języku Python?

Listy Pythona są wydajnymi kontenerami ogólnego przeznaczenia. Obsługują (dość) wydajne wstawianie, usuwanie, dołączanie i konkatenację, a zrozumienie listy Pythona ułatwia ich konstruowanie i manipulowanie. Mają jednak pewne ograniczenia: nie obsługują „wektoryzowanych” operacji, takich jak dodawanie i mnożenie elementów, a fakt, że mogą one zawierać obiekty różnych typów, oznacza, że ​​Python musi przechowywać informacje o typie dla każdego elementu i musi uruchamiać kod wysyłający typy podczas pracy na każdym elemencie. Oznacza to również, że za pomocą wydajnych pętli C można wykonać bardzo niewiele operacji na liście - każda iteracja wymagałaby sprawdzenia typu i innych operacji księgowych API w języku Python.

Eliezer
źródło
9

Wszystkie podkreślają prawie wszystkie główne różnice między tablicą numpy a listą pythonów, przedstawię je tutaj:

  1. Tablice Numpy mają ustalony rozmiar podczas tworzenia, w przeciwieństwie do list pythonowych (które mogą dynamicznie rosnąć). Zmiana rozmiaru ndarray spowoduje utworzenie nowej tablicy i usunięcie oryginału.

  2. Wszystkie elementy tablicy Numpy muszą mieć ten sam typ danych (możemy mieć również typ heterogeniczny, ale to nie pozwoli na operacje matematyczne), a zatem będą miały ten sam rozmiar w pamięci

  3. Tablice Numpy ułatwiają postępy matematyczne i inne operacje na dużej liczbie danych. Zazwyczaj takie operacje są wykonywane bardziej wydajnie i przy użyciu mniejszego kodu niż jest to możliwe przy użyciu budowania sekwencji w sekwencji

Parvez Khan
źródło