Apa kelebihan NumPy dibandingkan daftar Python biasa?

466

Apa kelebihan NumPy dibandingkan daftar Python biasa?

Saya memiliki sekitar 100 seri pasar keuangan, dan saya akan membuat array kubus 100x100x100 = 1 juta sel. Saya akan melakukan regresi (3-variabel) setiap x dengan masing-masing y dan z, untuk mengisi array dengan kesalahan standar.

Saya telah mendengar bahwa untuk "matriks besar" saya harus menggunakan NumPy sebagai lawan dari daftar Python, untuk alasan kinerja dan skalabilitas. Masalahnya, saya tahu daftar Python dan mereka tampaknya bekerja untuk saya.

Apa manfaatnya jika saya pindah ke NumPy?

Bagaimana jika saya memiliki 1000 seri (yaitu, 1 miliar sel floating point di kubus)?

Thomas Browne
sumber

Jawaban:

727

Array NumPy lebih kompak daripada daftar Python - daftar daftar seperti yang Anda jelaskan, dengan Python, akan membutuhkan setidaknya 20 MB atau lebih, sedangkan array NumPy 3D dengan pelampung presisi tunggal dalam sel akan muat dalam 4 MB. Akses dalam membaca dan menulis item juga lebih cepat dengan NumPy.

Mungkin Anda tidak terlalu peduli hanya untuk satu juta sel, tetapi Anda pasti akan untuk satu miliar sel - tidak ada pendekatan yang cocok dengan arsitektur 32-bit, tetapi dengan build 64-bit NumPy akan lolos dengan 4 GB atau lebih , Python saja membutuhkan setidaknya sekitar 12 GB (banyak pointer yang menggandakan ukuran) - perangkat yang jauh lebih mahal!

Perbedaannya sebagian besar disebabkan oleh "tidak langsung" - daftar Python adalah array pointer ke objek Python, setidaknya 4 byte per pointer ditambah 16 byte untuk objek Python terkecil (4 untuk pointer tipe, 4 untuk jumlah referensi, 4 untuk nilai - dan pengalokasi memori membulatkan hingga 16). Array NumPy adalah array nilai seragam - angka presisi tunggal masing-masing membutuhkan 4 byte, presisi ganda, 8 byte. Kurang fleksibel, tetapi Anda membayar secara substansial untuk fleksibilitas daftar Python standar!

Alex Martelli
sumber
Saya telah mencoba menggunakan "sys.getsizeof ()" untuk membandingkan ukuran daftar Python dan array NumPy dengan jumlah elemen yang sama dan sepertinya tidak menunjukkan bahwa array NumPy jauh lebih kecil. Apakah ini kasusnya atau sys.getsizeof () mengalami masalah untuk mengetahui seberapa besar array NumPy?
Jack Simpson
3
@JackSimpson getsizeoftidak dapat diandalkan. Dokumentasi dengan jelas menyatakan bahwa: Hanya konsumsi memori yang secara langsung dikaitkan dengan objek dipertanggungjawabkan, bukan konsumsi memori objek yang dimaksud. Ini berarti bahwa jika Anda memiliki daftar python bersarang ukuran elemen tidak diperhitungkan.
Bakuriu
4
getsizeofpada daftar hanya memberi tahu Anda berapa banyak RAM yang dikonsumsi oleh objek daftar itu dan RAM yang dikonsumsi oleh pointer dalam larik datanya, ia tidak memberi tahu Anda berapa banyak RAM yang dikonsumsi oleh objek yang dirujuk oleh pointer tersebut.
PM 2Ring
@AlexMartelli, bisakah Anda memberi tahu saya dari mana Anda mendapatkan nomor-nomor ini?
lmiguelvargasf
Hanya kepala, perkiraan Anda pada ukuran daftar daftar Python yang setara dimatikan. Array numpy 4 GB dari Cs float(4 byte) akan diterjemahkan menjadi sesuatu yang lebih dekat dengan 32 GB lists dan Python float(yang sebenarnya adalah C doubles), bukan 12 GB; masing-masing floatpada 64 bit Python menempati ~ 24 byte (dengan asumsi tidak ada kerugian perataan dalam pengalokasi), ditambah 8 byte lainnya di listuntuk menyimpan referensi (dan yang mengabaikan keseluruhan lokasi dan header objek untuk lists sendiri, yang mungkin menambahkan GB lain tergantung pada persis berapa banyak keseluruhan penempatan terjadi).
ShadowRanger
232

NumPy tidak hanya lebih efisien; ini juga lebih nyaman. Anda mendapatkan banyak operasi vektor dan matriks secara gratis, yang terkadang memungkinkan seseorang untuk menghindari pekerjaan yang tidak perlu. Dan mereka juga diimplementasikan secara efisien.

Misalnya, Anda bisa membaca kubus Anda langsung dari file ke dalam array:

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

Jumlahkan sepanjang dimensi kedua:

s = x.sum(axis=1)

Temukan sel mana di atas ambang batas:

(x > 0.5).nonzero()

Hapus setiap irisan genap di sepanjang dimensi ketiga:

x[:, :, ::2]

Juga, banyak pustaka yang berguna bekerja dengan array NumPy. Misalnya, analisis statistik dan visualisasi perpustakaan.

Bahkan jika Anda tidak memiliki masalah kinerja, mempelajari NumPy sepadan dengan usaha.

Roberto Bonvallet
sumber
Terima kasih - Anda telah memberikan alasan bagus lain pada contoh ketiga Anda, karena memang, saya akan mencari matriks untuk sel di atas ambang batas. Selain itu, saya memuat dari sqlLite. Pendekatan file akan jauh lebih efisien.
Thomas Browne
112

Alex menyebutkan efisiensi memori, dan Roberto menyebutkan kenyamanan, dan ini adalah poin bagus. Untuk beberapa ide lagi, saya akan menyebutkan kecepatan dan fungsionalitas .

Fungsionalitas: Anda mendapatkan banyak hal dengan NumPy, FFT, convolutions, pencarian cepat, statistik dasar, aljabar linier, histogram, dll. Dan sungguh, siapa yang dapat hidup tanpa FFT?

Kecepatan: Inilah tes untuk melakukan penjumlahan pada daftar dan larik NumPy, menunjukkan bahwa jumlah pada larik NumPy adalah 10x lebih cepat (dalam tes ini - jarak tempuh dapat bervariasi).

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

yang pada sistem saya (saat saya menjalankan cadangan) memberikan:

numpy: 3.004e-05
list:  5.363e-04
Tom10
sumber
44

Inilah jawaban yang bagus dari FAQ di situs scipy.org :

Apa kelebihan yang ditawarkan array NumPy dibandingkan daftar Python (bersarang)?

Daftar Python adalah wadah serba guna yang efisien. Mereka mendukung (cukup) penyisipan, penghapusan, penambahan, dan penggabungan yang efisien, dan pemahaman daftar Python membuatnya mudah untuk dibangun dan dimanipulasi. Namun, mereka memiliki batasan tertentu: mereka tidak mendukung operasi "vectorized" seperti penambahan dan perkalian elemen, dan fakta bahwa mereka dapat mengandung objek dari tipe yang berbeda berarti bahwa Python harus menyimpan informasi tipe untuk setiap elemen, dan harus mengeksekusi kode pengiriman tipe saat beroperasi pada setiap elemen. Ini juga berarti bahwa sangat sedikit operasi daftar dapat dilakukan dengan loop C efisien - setiap iterasi akan memerlukan pemeriksaan jenis dan pembukuan API Python lainnya.

Eliezer
sumber
9

Semua telah menyoroti hampir semua perbedaan utama antara array numpy dan daftar python, saya hanya akan menjelaskannya di sini:

  1. Array numpy memiliki ukuran tetap pada pembuatan, tidak seperti daftar python (yang dapat tumbuh secara dinamis). Mengubah ukuran ndarray akan membuat array baru dan menghapus yang asli.

  2. Elemen-elemen dalam array Numpy semua harus dari tipe data yang sama (kita bisa memiliki tipe heterogen juga tetapi itu tidak akan mengizinkan Anda operasi matematika) dan dengan demikian akan menjadi ukuran yang sama dalam memori

  3. Array numpy difasilitasi kemajuan matematika dan jenis operasi lainnya pada sejumlah besar data. Biasanya operasi seperti ini dieksekusi lebih efisien dan dengan kode lebih sedikit daripada yang dimungkinkan dengan menggunakan rangkaian ular sanca

Parvez Khan
sumber