NumPy'nin normal Python listelerine göre avantajları nelerdir?


466

NumPy'nin normal Python listelerine göre avantajları nelerdir ?

Yaklaşık 100 finansal piyasa serim var ve 100x100x100 = 1 milyon hücre içeren bir küp dizisi oluşturacağım. Diziyi standart hatalarla doldurmak için her y ve z ile her bir x'i regrese edeceğim (3 değişkenli).

"Büyük matrisler" için performans ve ölçeklenebilirlik nedenlerinden ötürü Python listelerinin aksine NumPy kullanmam gerektiğini duydum. Şey, Python listelerini biliyorum ve onlar benim için çalışıyor gibi görünüyor.

NumPy'ye geçersem faydaları ne olacak?

1000 serim olsaydı (yani küpte 1 milyar kayan nokta hücresi)?

Yanıtlar:


727

NumPy dizileri Python listelerinden daha kompakttır - açıkladığınız listelerin listesi Python'da en az 20 MB sürerken, hücrelerde tek duyarlıklı kayan bir NumPy 3D dizisi 4 MB'ye sığar. NumPy ile okuma ve yazma öğelerine erişim de daha hızlıdır.

Belki sadece bir milyon hücre için çok fazla umursamıyorsunuz, ama kesinlikle bir milyar hücre için - her iki yaklaşım da 32 bit mimariye sığmaz, ancak 64 bitlik yapılarla NumPy 4 GB veya daha fazla , Python tek başına en az yaklaşık 12 GB'a ihtiyaç duyacaktır (boyut olarak iki katına çıkan çok sayıda işaretçi) - çok daha pahalı bir donanım parçası!

Fark çoğunlukla "dolaylılıktan" kaynaklanmaktadır - Python listesi, Python nesnelerine bir işaretçi dizisidir, en küçük Python nesnesi için işaretçi başına en az 4 bayt artı 16 bayt (tip işaretçisi için 4, referans sayısı için 4, 4 değer - ve bellek ayırıcılar 16'ya kadar yuvarlar). NumPy dizisi, tek biçimli değerlerden oluşan bir dizidir - tek kesinlikli sayılar her biri 4 bayt, çift kesinlikli olanlar, 8 bayt alır. Daha az esnek, ancak standart Python listelerinin esnekliği için önemli ölçüde ödeme yaparsınız!


Ben aynı sayıda eleman ile Python listelerinin ve NumPy dizilerinin boyutunu karşılaştırmak için "sys.getsizeof ()" kullanmaya çalışıyorum ve NumPy dizileri çok daha küçük olduğunu belirtmek gibi görünmüyor. Bu durumda mı yoksa sys.getsizeof () bir NumPy dizisinin ne kadar büyük olduğunu anlamada sorun yaşıyor mu?
Jack Simpson

3
@JackSimpson getsizeofgüvenilir değil. Belgeler açıkça şunu belirtiyor: İlgili nesnelere ait bellek tüketimine değil, yalnızca nesneye doğrudan atfedilen bellek tüketimine bakılıyor. Bu, iç içe geçmiş python listeleriniz varsa, öğelerin boyutunun dikkate alınmadığı anlamına gelir.
Bakuriu

4
getsizeofbir listede yalnızca liste nesnesinin ne kadar RAM tüketdiğini ve veri dizisindeki işaretçiler tarafından tüketilen RAM'i gösterir, bu işaretçilerin başvurduğu nesneler tarafından ne kadar RAM tüketildiğini söylemez.
PM 2Ring

@AlexMartelli, lütfen bu numaraları nereden bulduğunuzu söyleyebilir misiniz?
lmiguelvargasf

Sadece bir kafa yukarı, eşdeğer Python liste listesinin boyutuna ilişkin tahmininiz kapalı. 4 GB numpy dizisi Cs float(4 bayt) 32 GB değerinde lists ve Python floats'ye (aslında C doubles'dir), 12 GB'ye yakın bir şeye dönüşür; float64 bit Python üzerindeki her biri ~ 24 bayt (ayırıcıda hizalama kaybı olmadığı varsayılarak) listve referansı tutmak için 8 bayt daha (ve bu durumun listkendileri için fazla yer ayırma ve nesne başlıklarını yok sayar) tam olarak ne kadar fazla yer değiştirme gerçekleşir).
ShadowRanger

232

NumPy sadece daha verimli değil; ayrıca daha uygundur. Ücretsiz olarak birçok vektör ve matris işlemi elde edersiniz, bu da bazen gereksiz işlerden kaçınmanıza izin verir. Ve ayrıca verimli bir şekilde uygulanırlar.

Örneğin, küpünüzü doğrudan bir dosyadan bir diziye okuyabilirsiniz:

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

İkinci boyut boyunca toplam:

s = x.sum(axis=1)

Hangi hücrelerin eşiğin üzerinde olduğunu bulun:

(x > 0.5).nonzero()

Üçüncü boyut boyunca çift dizinlenmiş her dilimi kaldırın:

x[:, :, ::2]

Ayrıca, birçok yararlı kütüphane NumPy dizileriyle çalışır. Örneğin, istatistiksel analiz ve görselleştirme kütüphaneleri.

Performans problemleriniz olmasa bile, NumPy'yi öğrenmek zahmete değer.


Teşekkürler - üçüncü örneğinizde başka bir iyi sebep daha sağladınız, aslında matrisi eşiğin üzerindeki hücreleri arayacağım. Üstelik sqlLite'den yükleme yapıyordum. Dosya yaklaşımı çok daha verimli olacaktır.
Thomas Browne

112

Alex hafıza verimliliğinden bahsetti ve Roberto kolaylıktan bahsediyor ve bunların ikisi de iyi nokta. Birkaç fikir daha için hız ve işlevsellikten bahsedeceğim .

İşlevsellik: NumPy, FFT'ler, kıvrımlar, hızlı arama, temel istatistikler, doğrusal cebir, histogramlar, vb. İle çok şey inşa edersiniz. Ve gerçekten, kim FFT'ler olmadan yaşayabilir?

Hız: Burada, bir liste ve bir NumPy dizisi üzerinden bir toplam yapma testi, NumPy dizisindeki toplamın 10 kat daha hızlı olduğunu gösterir (bu testte kilometre değişebilir).

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

(bir yedek çalıştırırken) benim sistemleri üzerinde verir:

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

44

İşte scipy.org web sitesindeki SSS bölümünden güzel bir cevap :

NumPy dizileri (iç içe) Python listelerine göre ne gibi avantajlar sunar?

Python'un listeleri verimli genel amaçlı kaplardır. Etkili yerleştirme, silme, ekleme ve birleştirme işlemlerini (oldukça) desteklerler ve Python'un liste kavrayışları onları yapılandırmayı ve manipüle etmeyi kolaylaştırır. Bununla birlikte, belirli sınırlamaları vardır: elementwise toplama ve çarpma gibi “vectorized” işlemleri desteklemezler ve farklı türde nesneler içerebilmeleri, Python'un her öğe için tip bilgisi saklaması ve tip dağıtım kodunu yürütmesi gerektiği anlamına gelir. her eleman üzerinde çalışırken. Bu aynı zamanda çok az liste işleminin verimli C döngüleri tarafından gerçekleştirilebileceği anlamına gelir - her bir yineleme tip kontrolleri ve diğer Python API defter tutma gerektirir.


9

Tüm numpy dizi ve python listesi arasındaki neredeyse tüm büyük farklılıkları vurguladı, ben sadece onları burada özetleyeceğim:

  1. Numpy dizileri, (dinamik olarak büyüyebilen) python listelerinin aksine, oluşturma sırasında sabit bir boyuta sahiptir. Ndarray'ın boyutunu değiştirmek yeni bir dizi oluşturur ve orijinali siler.

  2. Numpy dizisindeki öğelerin hepsinin aynı veri türünde olması gerekir (heterojen türe de sahip olabiliriz, ancak bu size matematiksel işlemlere izin vermeyecektir) ve dolayısıyla bellekte aynı boyutta olacaktır.

  3. Numpy dizileri, çok sayıda veri üzerinde matematiksel ve diğer işlem türlerini geliştirir. Tipik olarak bu tür işlemler, diziler halinde inşa edilen pitonlar kullanılarak mümkün olandan daha verimli ve daha az kodla yürütülür

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.