เมทริกซ์ขนาดใหญ่มากโดยใช้ Python และ NumPy


86

NumPyเป็นไลบรารีที่มีประโยชน์อย่างมากและจากการใช้งานฉันพบว่ามันสามารถจัดการเมทริกซ์ที่มีขนาดค่อนข้างใหญ่ (10,000 x 10,000) ได้อย่างง่ายดาย แต่เริ่มที่จะต่อสู้กับสิ่งที่ใหญ่กว่ามาก (พยายามสร้างเมทริกซ์ 50000 x 50000 ล้มเหลว) เห็นได้ชัดว่านี่เป็นเพราะความต้องการหน่วยความจำขนาดใหญ่

มีวิธีสร้างเมทริกซ์ขนาดใหญ่ใน NumPy (พูด 1 ล้านคูณ 1 ล้าน) ด้วยวิธีใดวิธีหนึ่ง (โดยไม่ต้องมี RAM หลายเทอราไบต์)

คำตอบ:


91

PyTables และ NumPy เป็นวิธีที่จะไป

PyTables จะจัดเก็บข้อมูลบนดิสก์ในรูปแบบ HDF พร้อมการบีบอัดเสริม ชุดข้อมูลของฉันมักจะได้รับการบีบอัด 10x ซึ่งมีประโยชน์เมื่อจัดการกับแถวหลายสิบหรือหลายร้อยล้านแถว มันเร็วมากด้วย แล็ปท็อปอายุ 5 ปีของฉันสามารถประมวลผลข้อมูลที่ทำ GROUP เหมือน SQL โดยการรวมที่ 1,000,000 แถว / วินาที ไม่เลวสำหรับโซลูชันที่ใช้ Python!

การเข้าถึงข้อมูลเป็น NumPy recarray อีกครั้งทำได้ง่ายเพียง:

data = table[row_from:row_to]

ไลบรารี HDF ดูแลการอ่านในกลุ่มข้อมูลที่เกี่ยวข้องและแปลงเป็น NumPy


4
คุณยังต้องแบ่งข้อมูลออกเป็นชิ้น ๆ เพื่อประมวลผล? เป็นเพียงวิธีการลดความซับซ้อนของการแปลงไฟล์ดิสก์หรือไม่
endolith

มีโอกาสใดที่คุณสามารถขยายคำตอบของคุณให้ชัดเจนขึ้นและมีตัวอย่างบ้าง
Adam B

56

numpy.arrays หมายถึงการมีชีวิตอยู่ในความทรงจำ หากคุณต้องการทำงานกับเมทริกซ์ที่มีขนาดใหญ่กว่า RAM ของคุณคุณต้องแก้ไขปัญหานั้น มีอย่างน้อยสองวิธีที่คุณสามารถปฏิบัติตาม:

  1. ลองใช้การแสดงเมทริกซ์ที่มีประสิทธิภาพมากขึ้นซึ่งใช้ประโยชน์จากโครงสร้างพิเศษใด ๆ ที่เมทริกซ์ของคุณมี ยกตัวอย่างเช่นเป็นคนอื่นได้ชี้แล้วออกมามีประสิทธิภาพโครงสร้างข้อมูลสำหรับการฝึกอบรมเบาบาง (เมทริกซ์ที่มีจำนวนมากของศูนย์) scipy.sparse.csc_matrixเช่น
  2. ปรับเปลี่ยนขั้นตอนวิธีการของคุณเพื่อการทำงานใน submatrices คุณสามารถอ่านจากดิสก์ได้เฉพาะบล็อกเมทริกซ์ที่กำลังใช้ในการคำนวณ อัลกอริทึมที่ออกแบบมาให้ทำงานบนคลัสเตอร์มักจะทำงานแบบบล็อกเนื่องจากข้อมูลจะกระจายไปทั่วคอมพิวเตอร์เครื่องอื่นและส่งผ่านเมื่อจำเป็นเท่านั้น ยกตัวอย่างเช่นฟ็อกซ์อัลกอริทึมสำหรับการคูณเมทริกซ์ (ไฟล์ PDF)

4
3- ขั้นตอนในกระบวนทัศน์ข้อมูลขนาดใหญ่และศึกษาวิธีแก้ปัญหาเช่น MapReduce
Medeiros

สำหรับหมายเลข 2 คุณจะตัดสินใจได้อย่างไรว่าจะทำชิ้นใหญ่แค่ไหน? มีวิธีวัดจำนวนหน่วยความจำที่ว่างและขนาดชิ้นส่วนของคุณตามนั้นหรือไม่?
endolith

30

คุณควรจะสามารถใช้ numpy.memmap เพื่อแมปหน่วยความจำไฟล์บนดิสก์ได้ ด้วย python และเครื่อง 64 บิตรุ่นใหม่คุณควรมีพื้นที่แอดเดรสที่จำเป็นโดยไม่ต้องโหลดทุกอย่างลงในหน่วยความจำ ระบบปฏิบัติการควรจัดการเฉพาะบางส่วนของไฟล์ในหน่วยความจำ


19
คุณช่วยยกตัวอย่างวิธีใช้เพื่อทำสิ่งที่ไม่สามารถใส่ลงในหน่วยความจำได้หรือไม่?
endolith

24

ในการจัดการฝึกอบรมเบาบางคุณต้องการscipyแพคเกจที่ตั้งอยู่ด้านบนของnumpy- ดูที่นี่สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับตัวเลือกเบาบางเมทริกซ์ที่scipyจะช่วยให้คุณ


11

โพสต์ของ Stefano Borini ทำให้ฉันได้เห็นว่าสิ่งเหล่านี้เป็นอย่างไร

นี่ไง. ดูเหมือนว่าจะทำในสิ่งที่คุณต้องการโดยทั่วไป HDF5 จะช่วยให้คุณจัดเก็บชุดข้อมูลขนาดใหญ่มากจากนั้นเข้าถึงและใช้งานได้ในลักษณะเดียวกับ NumPy


9
ทางเลือกที่ดีกว่าอาจเป็น PyTables เป็นระดับที่สูงกว่าฟังก์ชันการทำงานหลักของ HDF5 (H5Py มากกว่า API ระดับต่ำที่สามารถเข้าถึงได้จาก Python) นอกจากนี้ 2.2 เบต้าของสัปดาห์ที่แล้วยังมีเครื่องมือสำหรับปัญหานี้: pytables.org/moin/ReleaseNotes/Release_2.2b1 ที่เพิ่ม Expr คลาส [ที่] สามารถประเมินนิพจน์ (เช่น '3 * a + 4 * b') ที่ดำเนินการโดยพลการ อาร์เรย์ในขณะที่เพิ่มประสิทธิภาพทรัพยากร [... ] มันคล้ายกับแพ็คเกจ Numexpr แต่นอกเหนือจากอ็อบเจ็กต์ NumPy แล้วยังยอมรับอาร์เรย์ที่เป็นเนื้อเดียวกันบนดิสก์เช่นอ็อบเจ็กต์ Array, CArray, EArray และ Column PyTables
AFoglia

5

ตรวจสอบให้แน่ใจว่าคุณใช้ระบบปฏิบัติการ 64 บิตและ Python / NumPy เวอร์ชัน 64 บิต โปรดทราบว่าในสถาปัตยกรรม 32 บิตคุณสามารถระบุหน่วยความจำได้โดยทั่วไป 3GB (โดยที่ประมาณ 1GB หายไปจาก I / O ที่แมปหน่วยความจำเป็นต้น)

ด้วย 64 บิตและอาร์เรย์สิ่งต่าง ๆ ที่มีขนาดใหญ่กว่า RAM ที่มีอยู่คุณสามารถใช้หน่วยความจำเสมือนได้แม้ว่าสิ่งต่างๆจะช้าลงหากคุณต้องสลับ นอกจากนี้แผนที่หน่วยความจำ (ดู numpy.memmap) เป็นวิธีการทำงานกับไฟล์ขนาดใหญ่บนดิสก์โดยไม่ต้องโหลดลงในหน่วยความจำ แต่อีกครั้งคุณต้องมีพื้นที่ที่อยู่ 64 บิตเพื่อใช้งานได้เพื่อให้สามารถใช้งานได้มาก PyTables จะทำสิ่งนี้ให้คุณมากที่สุดเช่นกัน



4

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

In [70]: a = np.arange(5)

In [71]: a[0].dtype
Out[71]: dtype('int64')

In [72]: a.nbytes
Out[72]: 40

In [73]: a = np.arange(0, 2, 0.5)

In [74]: a[0].dtype
Out[74]: dtype('float64')

In [75]: a.nbytes
Out[75]: 32

และด้วยประเภทที่กำหนดเอง:

In [80]: a = np.arange(5, dtype=np.int8)

In [81]: a.nbytes
Out[81]: 5

In [76]: a = np.arange(0, 2, 0.5, dtype=np.float16)

In [78]: a.nbytes
Out[78]: 8

3

คุณกำลังถามวิธีจัดการเมทริกซ์องค์ประกอบ 2,500,000,000 โดยไม่ใช้แรมเทราไบต์หรือไม่?

วิธีจัดการ 2 พันล้านรายการโดยไม่มี RAM 8 พันล้านไบต์คือการไม่เก็บเมทริกซ์ไว้ในหน่วยความจำ

นั่นหมายถึงอัลกอริทึมที่ซับซ้อนกว่ามากในการดึงข้อมูลจากระบบไฟล์เป็นชิ้น ๆ


7
ไม่จริง. หาก 99.99% (สำหรับตัวอย่างที่เป็นจริง) ขององค์ประกอบเป็นศูนย์ข้อมูลทั้งหมดของเมทริกซ์จะถูกเก็บไว้ในหน่วยความจำ ไม่จำเป็นต้องใช้ 4 ไบต์สำหรับทุกๆศูนย์เมื่อคุณสามารถจัดเก็บรายการ(row, column, value)สำหรับรายการเหล่านั้นที่มีอยู่ได้
Eric Wilson

6
@EricWilson: ในคำถามที่แนะนำว่าเมทริกซ์นั้นเบาบาง? ฉันพลาดสิ่งนั้นโดยสิ้นเชิง คุณสามารถให้ใบเสนอราคาได้หรือไม่?
ล็อ

1

โดยปกติเมื่อเราจัดการกับเมทริกซ์ขนาดใหญ่เราใช้พวกเขาเป็นเบาบางเมทริกซ์

ฉันไม่รู้ว่า numpy รองรับเมทริกซ์แบบเบาบางหรือไม่ แต่ฉันพบสิ่งนี้แทน


1

เท่าที่ฉันรู้เกี่ยวกับ numpy ไม่ แต่ฉันคิดผิด

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


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