2009-06-28 42 views
73

NumPy là một thư viện cực kỳ hữu ích, và từ việc sử dụng nó, tôi thấy rằng nó có khả năng xử lý ma trận khá lớn (10000 x 10000) một cách dễ dàng. (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 các yêu cầu bộ nhớ lớn.Các ma trận rất lớn sử dụng Python và NumPy

Có cách nào tạo ra các ma trận khổng lồ trong NumPy (nói 1 triệu 1 triệu) theo cách nào đó (không có nhiều terrabyte RAM) không?

+16

Bạn đang cố gắng để làm với họ (ngoài việc tạo ra chúng)? – Rook

Trả lời

1

Thông thường khi chúng ta đối phó với ma trận lớn chúng ta thực hiện chúng như Sparse Matrices.

Tôi không biết nếu NumPy hỗ trợ các ma trận thưa thớt nhưng tôi thấy this để thay thế.

1

Theo như tôi biết về vón cục, không, nhưng tôi có thể sai.

tôi có thể đề nghị bạn giải pháp thay thế này: viết ma trận trên đĩa và truy cập nó trong khối. Tôi đề nghị bạn định dạng tệp HDF5. Nếu bạn cần nó một cách minh bạch, bạn có thể triển khai lại giao diện ndarray để phân trang ma trận được lưu trữ trên đĩa của bạn thành 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.

+0

Nếu tôi muốn truy cập toàn bộ ma trận 57600 bằng 57600 thì sao? – user3515225

29

Bạn sẽ có thể sử dụng numpy.memmap để bộ nhớ ánh xạ một tệp trên đĩa. Với máy python và 64 bit mới hơn, bạn nên 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 nên xử lý chỉ giữ một phần của tập tin trong bộ nhớ.

+10

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 gói scipy nằm trên đầu trang numpy - xem here để biết thêm chi tiết về các tùy chọn ma trận thưa thớt mà scipy cung cấp cho bạn.

4

Bạn có hỏi cách xử lý ma trận phần tử 2.500.000.000 mà không có terabyte RAM không?

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 để tìm nạp nó từ hệ thống tệp theo từng phần.

+6

Không đúng sự thật. Nếu 99,99% (đối với một ví dụ thực tế) của các phần tử bằng không, thì tất cả dữ liệu của ma trận có thể được giữ trong bộ nhớ. Không cần sử dụng hết 4 byte cho mỗi số không, khi bạn chỉ có thể lưu trữ một danh sách '(hàng, cột, giá trị)' cho những mục nhập tồn tại. –

+3

@EricWilson: Ở đâu trong câu hỏi đã làm cho nó ma trận là thưa thớt? Tôi hoàn toàn bỏ lỡ điều đó. Bạn có thể cung cấp báo giá? –

51

numpy.array s 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 bạn, bạn phải làm việc xung quanh đó. Có ít nhất hai phương pháp bạn có thể làm theo:

  1. Hãy thử một ma trận đại diện hiệu quả hơn rằng khai thác bất kỳ cấu trúc đặc biệt mà các 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 các ma trận thưa thớt (ma trận với nhiều số không), như scipy.sparse.csc_matrix.
  2. Sửa đổi thuật toán của bạn để làm việc trên submatrices. Bạn có thể đọc từ đĩa chỉ 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 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 truyền khi cần. Ví dụ: the Fox algorithm for matrix multiplication (PDF file).
+4

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

+0

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

11

Stefano Borini's post giúp tôi xem xét cách sắp xếp điều này.

This is it. Nó xuất hiện để làm 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ùng một cách mà NumPy thực hiện.

+9

Một lựa chọn tốt hơn có thể là PyTables. Đó là cấp độ cao hơn chức năng HDF5 lõi (H5Py là ít hơn so với API cấp thấp có thể truy cập từ Python). Ngoài ra, phiên bản 2.2 beta của tuần trước có các công cụ cho vấn đề này: http://www.pytables.org/moin/ReleaseNotes/Release_2.2b1 Đã thêm Expr, một lớp [có thể đánh giá các biểu thức (như '3 * a + 4 * b ') hoạt động trên các mảng lớn tùy ý 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

84

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

PyTables sẽ lưu trữ dữ liệu trên đĩa ở định dạng HDF, với nén tùy chọn. Bộ dữ liệu của tôi thường nhận được nén 10x, 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ể khủng hoảng thông qua dữ liệu thực hiện tổng hợp GROUP BY giống SQL ở mức 1.000.000 hàng/giây. Không tệ đối với một giải pháp dựa trên Python!

Truy cập vào dữ liệu như một NumPy recarray lại cũng đơn giản như:

data = table[row_from:row_to] 

Thư viện HDF sẽ chăm sóc của đọc trong các khối có liên quan của dữ liệu và chuyển đổi để NumPy.

+63

Chăm sóc để hiển thị một ví dụ mã nhanh về phương pháp này? – Ivan

+2

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

5

Đảm bảo 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 kiến ​​trúc 32 bit, bạn có thể giải quyết 3GB bộ nhớ thông thường (với khoảng 1GB bị mất đến bộ nhớ ánh xạ I/O và như vậy).

Với mảng 64 bit và mảng lớn hơn RAM sẵn có, bạn có thể thoát khỏi bộ nhớ ảo, mặc dù mọi thứ sẽ chậm hơn nếu bạn phải trao đổi. Ngoài ra, các 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 nạp chúng vào bộ nhớ, nhưng một lần nữa, bạn cần có một không gian địa chỉ 64 bit để làm việc với điều này. PyTables sẽ làm hầu hết điều này cho bạn.

2

Đôi khi một giải pháp đơn giản đang sử dụng loại 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 hướng dẫn sử dụng dtype và đặc biệt nhỏ hơn cho các mục của bạn. Bởi vì Numpy coi loại lớn nhất cho đối tượng theo mặc định, đây có thể là một ý tưởng hữu ích trong nhiều trường hợp. Dưới đâ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 kiểu 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 
Các vấn đề liên quan