Ma trận rất lớn sử dụng Python và NumPy


86

NumPy là một thư viện cực kỳ hữu ích và từ việc sử dụng nó, tôi nhận thấy rằng nó có khả năng xử lý các ma trận khá lớn (10000 x 10000) một cách dễ dàng, nhưng bắt đầu gặp khó khăn với bất kỳ thứ gì lớn hơn nhiều (cố gắng tạo ma trận 50000 x 50000 không thành công). Rõ ràng, điều này là do yêu cầu bộ nhớ lớn.

Có cách nào để tạo ma trận khổng lồ nguyên bản trong NumPy (giả sử 1 triệu x 1 triệu) theo một cách nào đó (mà không cần có nhiều bộ nhớ RAM)?

Câu trả lời:


91

PyTables và NumPy là cách để đi.

PyTables sẽ lưu trữ dữ liệu trên đĩa ở định dạng HDF, với tính năng nén tùy chọn. Bộ dữ liệu của tôi thường được nén 10 lần, điều này rất tiện lợi khi xử lý hàng chục hoặc hàng trăm triệu hàng. Nó cũng rất nhanh; máy tính xách tay 5 năm tuổi của tôi có thể xử lý dữ liệu bằng cách tổng hợp GROUP BY giống SQL với tốc độ 1.000.000 hàng / giây. Không tồi cho một giải pháp dựa trên Python!

Truy cập lại dữ liệu dưới dạng tái phân vùng NumPy đơn giản như sau:

data = table[row_from:row_to]

Thư viện HDF quản lý việc đọc các phần dữ liệu có liên quan và chuyển đổi sang NumPy.


4
Vì vậy, bạn vẫn phải tự mình chia nhỏ dữ liệu thành nhiều phần để xử lý? Đó chỉ là một cách để đơn giản hóa việc chuyển đổi sang và từ các tệp đĩa?
endolith

Bất kỳ cơ hội nào bạn có thể mở rộng câu trả lời của mình với một chút rõ ràng hơn và một số ví dụ?
Adam B

56

numpy.arrays có nghĩa là sống trong ký ức. Nếu bạn muốn làm việc với ma trận lớn hơn RAM của mình, bạn phải giải quyết vấn đề đó. Có ít nhất hai cách tiếp cận bạn có thể làm theo:

  1. Hãy thử biểu diễn ma trận hiệu quả hơn khai thác bất kỳ cấu trúc đặc biệt nào mà ma trận của bạn có. Ví dụ, như những người khác đã chỉ ra, có những cấu trúc dữ liệu hiệu quả cho ma trận thưa thớt (ma trận có nhiều số 0), như scipy.sparse.csc_matrix.
  2. Sửa đổi thuật toán của bạn để hoạt động trên ma trận con . Bạn chỉ có thể đọc từ đĩa các khối ma trận hiện đang được sử dụng trong tính toán. Các thuật toán được thiết kế để chạy trên các cụm thường hoạt động theo chiều khối, vì dữ liệu được phân tán trên các máy tính khác nhau và chỉ được chuyển qua khi cần thiết. Ví dụ, thuật toán Fox cho phép nhân ma trận (tệp PDF) .

4
3 Bước trong mô hình và nghiên cứu các giải pháp lớn dữ liệu như MapReduce
Medeiros

Đối với số 2, làm thế nào để bạn quyết định làm thế nào để tạo ra khối của bạn? Có cách nào để đo dung lượng bộ nhớ trống và kích thước các phần của bạn dựa trên đó không?
endolith

30

Bạn sẽ có thể sử dụng numpy.memmap để ánh xạ bộ nhớ một tệp trên đĩa. Với python mới hơn và máy 64-bit, bạn sẽ có không gian địa chỉ cần thiết mà không cần tải mọi thứ vào bộ nhớ. Hệ điều hành sẽ chỉ xử lý giữ một phần của tệp trong bộ nhớ.


18
Bạn có thể cung cấp một ví dụ về cách sử dụng nó để làm điều gì đó không thể phù hợp với bộ nhớ?
endolith

24

Để xử lý ma trận thưa thớt, bạn cần scipygói nằm trên cùng numpy- xem tại đây để biết thêm chi tiết về các tùy chọn ma trận thưa thớt scipycung cấp cho bạn.


11

Bài đăng của Stefano Borini đã giúp tôi xem xét xem loại thứ này đã đi xa đến mức nào.

Đây chính là nó. Nó dường như làm về cơ bản những gì bạn muốn. HDF5 sẽ cho phép bạn lưu trữ các tập dữ liệu rất lớn, sau đó truy cập và sử dụng chúng theo cách giống như NumPy.


9
Sự lựa chọn tốt hơn có thể là PyTables. Đây là cấp cao hơn so với chức năng HDF5 cốt lõi (H5Py nhiều hơn một chút so với API cấp thấp có thể truy cập từ Python). Ngoài ra, bản beta 2.2 của tuần trước cũng có các công cụ cho vấn đề này: pytables.org/moin/ReleaseNotes/Release_2.2b1 Đã thêm Expr , một lớp [mà] có thể đánh giá các biểu thức (như '3 * a + 4 * b') hoạt động trên trong khi tối ưu hóa các tài nguyên [...]. Nó tương tự như gói Numexpr, nhưng ngoài các đối tượng NumPy, nó cũng chấp nhận các mảng đồng nhất dựa trên đĩa, như các đối tượng Array, CArray, EArray và Column PyTables.
AFoglia

5

Đảm bảo rằng bạn đang sử dụng hệ điều hành 64 bit và phiên bản Python / NumPy 64 bit. Lưu ý rằng trên cấu trúc 32-bit, bạn có thể xử lý bộ nhớ thường là 3GB (với khoảng 1GB bị mất vào bộ nhớ được ánh xạ I / O và tương tự).

Với 64-bit và các mảng lớn hơn RAM khả dụng, bạn có thể sử dụng bộ nhớ ảo, mặc dù mọi thứ sẽ chậm hơn nếu bạn phải hoán đổi. Ngoài ra, bản đồ bộ nhớ (xem numpy.memmap) là một cách để làm việc với các tệp lớn trên đĩa mà không cần tải chúng vào bộ nhớ, nhưng một lần nữa, bạn cần phải có không gian địa chỉ 64-bit để làm việc với điều này. PyTables cũng sẽ làm hầu hết điều này cho bạn.



4

Đôi khi, một giải pháp đơn giản là sử dụng kiểu tùy chỉnh cho các mục ma trận của bạn. Dựa trên phạm vi số bạn cần, bạn có thể sử dụng sổ tay hướng dẫn dtypevà đặc biệt nhỏ hơn cho các mặt hàng của mình. Bởi vì Numpy coi kiểu đối tượng lớn nhất theo mặc định, đây có thể là một ý tưởng hữu ích trong nhiều trường hợp. Đây là một ví dụ:

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

Và với loại tùy chỉnh:

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

Bạn đang hỏi làm thế nào để xử lý một ma trận phần tử 2.500.000.000 mà không có hàng terabyte RAM?

Cách để xử lý 2 tỷ mục không có 8 tỷ byte RAM là không giữ ma trận trong bộ nhớ.

Điều đó có nghĩa là các thuật toán phức tạp hơn nhiều để tìm nạp nó từ hệ thống tệp thành từng phần.


7
Không đúng. Nếu 99,99% (ví dụ thực tế) của các phần tử là 0, thì tất cả dữ liệu của ma trận có thể được lưu trong bộ nhớ. Không cần thiết phải sử dụng đến 4 byte cho mọi số 0, khi bạn chỉ có thể lưu trữ danh sách (row, column, value)các mục nhập tồn tại.
Eric Wilson

6
@EricWilson: Nơi nào trong câu hỏi nó gợi ý rằng ma trận thưa thớt? Tôi hoàn toàn bỏ lỡ điều đó. Bạn có thể cung cấp báo giá?
S.Lott

1

Thông thường, khi chúng ta xử lý các ma trận lớn, chúng ta thực hiện chúng dưới dạng Ma trận thưa thớt .

Tôi không biết liệu numpy có hỗ trợ ma trận thưa thớt hay không nhưng tôi đã tìm thấy điều này thay thế.


1

Theo những gì tôi biết về numpy, không, nhưng tôi có thể sai.

Tôi có thể đề xuất cho bạn giải pháp thay thế này: ghi ma trận vào đĩa và truy cập nó theo từng phần. Tôi đề nghị bạn định dạng tệp HDF5. Nếu bạn cần nó một cách rõ ràng, bạn có thể thực hiện lại giao diện ndarray để phân trang ma trận được lưu trữ trên đĩa của bạn vào bộ nhớ. Hãy cẩn thận nếu bạn sửa đổi dữ liệu để đồng bộ hóa chúng trở lại trên đĩa.


Điều gì sẽ xảy ra nếu tôi muốn truy cập toàn bộ ma trận 57600 x 57600?
Gunjan naik
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.