ข้อดีของ NumPy ในรายการ Python ทั่วไปคืออะไร


466

ข้อดีของNumPyในรายการ Python ทั่วไปคืออะไร

ฉันมีซีรี่ส์ตลาดการเงินประมาณ 100 ชุดและฉันจะสร้างคิวบ์อาร์เรย์ที่มีขนาด 100x100x100 = 1 ล้านเซลล์ ฉันจะถดถอย (3 ตัวแปร) แต่ละ x ด้วยแต่ละ y และ z เพื่อเติมอาร์เรย์ด้วยข้อผิดพลาดมาตรฐาน

ฉันได้ยินมาว่าสำหรับ "matrices ขนาดใหญ่" ฉันควรใช้ NumPy ซึ่งต่างจากรายการ Python สำหรับเหตุผลด้านประสิทธิภาพและความสามารถในการปรับขยายได้ สิ่งที่ฉันรู้ว่ารายการหลามและพวกเขาดูเหมือนจะทำงานให้ฉัน

ฉันจะได้รับประโยชน์อะไรบ้างหากฉันย้ายไปที่ NumPy

ถ้าฉันมี 1,000 ซีรี่ส์ (นั่นคือเซลล์จุดลอยตัว 1 พันล้านก้อน)

คำตอบ:


727

อาร์เรย์ของ NumPy มีขนาดกะทัดรัดกว่ารายการ Python รายการของรายการตามที่คุณอธิบายใน Python จะใช้เวลาอย่างน้อย 20 MB หรือมากกว่านั้นในขณะที่อาร์เรย์ NumPy 3D ที่มีความแม่นยำเดียวในเซลล์จะพอดีกับ 4 MB การเข้าถึงการอ่านและการเขียนรายการก็เร็วขึ้นด้วย NumPy

บางทีคุณอาจไม่สนใจมากนักสำหรับเซลล์หนึ่งล้านเซลล์ แต่แน่นอนว่าคุณต้องการเซลล์หนึ่งพันล้านเซลล์ - ไม่ว่าจะใช้วิธีใดในสถาปัตยกรรม 32 บิต แต่ด้วย 64 บิตบิวด์ NumPy จะหายไปด้วย 4 GB หรือมากกว่านั้น Python เพียงอย่างเดียวก็ต้องการอย่างน้อยประมาณ 12 GB (จำนวนพอยน์เตอร์ที่มีขนาดใหญ่เป็นสองเท่า) - ฮาร์ดแวร์ที่มีค่าใช้จ่ายสูง!

ความแตกต่างส่วนใหญ่เกิดจาก "ทางอ้อม" - รายการ Python เป็นอาร์เรย์ของพอยน์เตอร์ไปยังวัตถุ Python อย่างน้อย 4 ไบต์ต่อตัวชี้บวก 16 ไบต์สำหรับวัตถุ Python ที่เล็กที่สุด (4 สำหรับประเภทตัวชี้ 4 สำหรับการอ้างอิง 4, 4 สำหรับค่า - และตัวจัดสรรหน่วยความจำปัดได้สูงสุด 16) อาร์เรย์ NumPy เป็นอาร์เรย์ของค่าเครื่องแบบ - ตัวเลขความแม่นยำเดี่ยวใช้เวลา 4 ไบต์แต่ละรายการ, ความแม่นยำสองเท่า, 8 ไบต์ ยืดหยุ่นน้อยลง แต่คุณจ่ายเงินอย่างมากสำหรับความยืดหยุ่นของรายการ Python มาตรฐาน!


ฉันพยายามใช้ "sys.getsizeof ()" เพื่อเปรียบเทียบขนาดของรายการ Python และอาร์เรย์ NumPy ที่มีจำนวนองค์ประกอบเท่ากันและดูเหมือนจะไม่บ่งบอกว่าอาร์เรย์ NumPy นั้นมีขนาดเล็กกว่ามาก นี่เป็นกรณีหรือเป็น sys.getsizeof () มีปัญหาในการหาว่าอาร์เรย์ NumPy ใหญ่แค่ไหน?
Jack Simpson

3
@JackSimpson getsizeofไม่น่าเชื่อถือ เอกสารอธิบายอย่างชัดเจนว่า: มีการบันทึกการใช้หน่วยความจำที่เกี่ยวข้องโดยตรงกับวัตถุเท่านั้นไม่ใช่การใช้หน่วยความจำของวัตถุที่อ้างถึง ซึ่งหมายความว่าหากคุณมีงูหลามซ้อนกันแสดงขนาดขององค์ประกอบที่ไม่ได้นำมาพิจารณา
Bakuriu

4
getsizeofในรายการจะบอกให้คุณทราบว่า RAM ของวัตถุรายการนั้นใช้งานเท่าใดและ RAM ที่ใช้โดยพอยน์เตอร์ในอาเรย์ข้อมูลของมันจะไม่บอกคุณว่า RAM นั้นถูกใช้งานโดยออบเจ็กต์ที่พอยน์เตอร์เหล่านั้นอ้างถึง
PM 2Ring

@AlexMartelli คุณช่วยบอกฉันทีว่าคุณรับเบอร์เหล่านี้มาจากไหน?
lmiguelvargasf

เพียงเพิ่มระดับประมาณการของคุณเกี่ยวกับขนาดของรายการ Python ที่เทียบเท่าของรายการที่จะปิด อาร์เรย์ numpy ขนาด 4 GB ของ C floats (4 ไบต์) จะแปลสิ่งที่ใกล้เคียงกับ 32 GB มูลค่าของlists และ Python floats (ซึ่งจริงๆแล้วเป็น C double) ไม่ใช่ 12 GB; แต่ละfloat64 บิตงูใหญ่ครอง ~ 24 ไบต์ (สมมติว่าไม่มีการสูญเสียการจัดตำแหน่งในการจัดสรร) บวกอีก 8 ไบต์ในlistที่จะถืออ้างอิง (และที่ละเว้น overallocation และวัตถุส่วนหัวสำหรับlists ตัวเองซึ่งอาจจะเพิ่ม GB อีกขึ้นอยู่กับ จำนวนตำแหน่งโดยรวมที่เกิดขึ้น)
ShadowRanger

232

NumPy ไม่เพียงมีประสิทธิภาพมากขึ้นเท่านั้น มันสะดวกกว่าด้วย คุณจะได้เวกเตอร์และเมทริกซ์จำนวนมากฟรีซึ่งบางครั้งก็อนุญาตให้หลีกเลี่ยงงานที่ไม่จำเป็นได้ และพวกเขายังดำเนินการอย่างมีประสิทธิภาพ

ตัวอย่างเช่นคุณสามารถอ่านคิวบ์ของคุณได้โดยตรงจากไฟล์ลงในอาร์เรย์:

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

ผลรวมตามมิติที่สอง:

s = x.sum(axis=1)

ค้นหาเซลล์ที่อยู่เหนือขีด จำกัด :

(x > 0.5).nonzero()

ลบทุกส่วนที่จัดทำดัชนีไว้ในมิติที่สาม:

x[:, :, ::2]

นอกจากนี้ยังมีห้องสมุดที่มีประโยชน์มากมายที่ทำงานกับ NumPy arrays ตัวอย่างเช่นการวิเคราะห์ทางสถิติและห้องสมุดภาพ

แม้ว่าคุณจะไม่มีปัญหาด้านประสิทธิภาพการเรียนรู้ NumPy ก็คุ้มค่ากับความพยายาม


ขอบคุณ - คุณได้ให้เหตุผลที่ดีในตัวอย่างที่สามของคุณอีกครั้งแน่นอนว่าฉันจะค้นหาเมทริกซ์สำหรับเซลล์ที่สูงกว่าเพดาน ยิ่งไปกว่านั้นฉันกำลังโหลดจาก sqlLite วิธีการไฟล์จะมีประสิทธิภาพมากขึ้น
โทมัสบราวน์

112

อเล็กซ์พูดถึงประสิทธิภาพของหน่วยความจำและ Roberto กล่าวถึงความสะดวกสบายและสิ่งเหล่านี้เป็นจุดที่ดี สำหรับความคิดอีกไม่กี่ผมจะพูดถึงความเร็วและการทำงาน

ฟังก์ชั่น: คุณได้รับสิ่งต่างๆมากมายจาก NumPy, FFT, convolutions, การค้นหาที่รวดเร็ว, สถิติพื้นฐาน, พีชคณิตเชิงเส้น, ฮิสโทแกรม ฯลฯ และจริงๆแล้วใครที่สามารถอยู่ได้โดยปราศจาก FFT

ความเร็ว: นี่คือการทดสอบการทำผลรวมผ่านรายการและอาร์เรย์ NumPy ซึ่งแสดงว่าผลรวมของอาร์เรย์ NumPy นั้นเร็วกว่า 10x (ในการทดสอบนี้ - ระยะทางอาจเปลี่ยนแปลง)

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

สิ่งใดในระบบของฉัน (ในขณะที่ฉันกำลังสำรองข้อมูล) ให้:

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

44

นี่คือคำตอบที่ดีจากคำถามที่พบบ่อยในเว็บไซต์ scipy.org :

อาร์เรย์ NumPy มีข้อได้เปรียบอะไรบ้างที่เสนอรายการ Python (ซ้อนกัน)

รายการของไพ ธ อนเป็นภาชนะที่ใช้งานทั่วไปที่มีประสิทธิภาพ พวกเขาสนับสนุนการแทรกการลบการต่อเติมและการต่อข้อมูลที่มีประสิทธิภาพ (อย่างเป็นธรรม) และความเข้าใจในรายการของ Python ทำให้พวกเขาสร้างและจัดการได้ง่าย อย่างไรก็ตามมันมีข้อ จำกัด บางอย่าง: พวกเขาไม่สนับสนุนการดำเนินงาน "vectorized" เช่นการเพิ่มองค์ประกอบและการคูณและความจริงที่ว่าพวกเขาสามารถมีวัตถุประเภทที่แตกต่างกันได้หมายความว่า Python ต้องเก็บข้อมูลประเภทสำหรับทุกองค์ประกอบ เมื่อทำงานกับแต่ละองค์ประกอบ นอกจากนี้ยังหมายความว่าการดำเนินการรายการน้อยมากสามารถทำได้โดยใช้ลูป C ที่มีประสิทธิภาพ - การวนซ้ำแต่ละครั้งจะต้องมีการตรวจสอบประเภทและการทำบัญชี Python API อื่น ๆ


9

ทั้งหมดได้เน้นความแตกต่างที่สำคัญเกือบทั้งหมดระหว่าง numpy array และรายการ python ฉันจะสรุปพวกเขาที่นี่:

  1. อาร์เรย์ Numpy มีขนาดคงที่ที่การสร้างซึ่งแตกต่างจากรายการหลาม (ซึ่งสามารถเติบโตแบบไดนามิก) การเปลี่ยนขนาดของ ndarray จะสร้างอาร์เรย์ใหม่และลบต้นฉบับ

  2. องค์ประกอบในอาร์เรย์ Numpy นั้นจำเป็นต้องมีชนิดข้อมูลเดียวกัน (เราสามารถมีประเภทที่แตกต่างได้เช่นกัน แต่จะไม่อนุญาตให้คุณดำเนินการทางคณิตศาสตร์) และจะมีขนาดเท่ากันในหน่วยความจำ

  3. อาร์เรย์ Numpy ช่วยอำนวยความสะดวกในการดำเนินการทางคณิตศาสตร์และประเภทอื่น ๆ เกี่ยวกับข้อมูลจำนวนมาก โดยทั่วไปการดำเนินการดังกล่าวจะดำเนินการอย่างมีประสิทธิภาพมากขึ้นและมีรหัสน้อยกว่าที่เป็นไปได้โดยใช้ pythons สร้างในลำดับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.