Matriks yang sangat besar menggunakan Python dan NumPy


86

NumPy adalah pustaka yang sangat berguna, dan dari penggunaannya saya telah menemukan bahwa ia mampu menangani matriks yang cukup besar (10000 x 10000) dengan mudah, tetapi mulai berjuang dengan sesuatu yang jauh lebih besar (mencoba membuat matriks 50000 x 50000 gagal). Jelas, ini karena kebutuhan memori yang sangat besar.

Apakah ada cara untuk membuat matriks besar secara native di NumPy (katakanlah 1 juta kali 1 juta) dengan cara tertentu (tanpa memiliki beberapa terrabyte RAM)?

Jawaban:


91

PyTables dan NumPy adalah cara terbaik.

PyTables akan menyimpan data pada disk dalam format HDF, dengan kompresi opsional. Set data saya sering mendapatkan kompresi 10x, yang berguna saat menangani puluhan atau ratusan juta baris. Ini juga sangat cepat; laptop saya yang berusia 5 tahun dapat mengolah data dengan melakukan agregasi GROUP BY seperti SQL pada 1.000.000 baris / detik. Lumayan untuk solusi berbasis Python!

Mengakses data sebagai recarray NumPy semudah:

data = table[row_from:row_to]

Pustaka HDF menangani pembacaan di bagian data yang relevan dan mengonversinya ke NumPy.


4
Jadi Anda masih harus memecah data menjadi beberapa bagian untuk diproses? Ini hanya cara untuk menyederhanakan konversi ke dan dari file disk?
endolith

Adakah kemungkinan Anda dapat memperluas jawaban Anda dengan sedikit lebih jelas dan beberapa contoh?
Adam B

56

numpy.arrays dimaksudkan untuk hidup dalam memori. Jika Anda ingin bekerja dengan matriks yang lebih besar dari RAM Anda, Anda harus mengatasinya. Setidaknya ada dua pendekatan yang bisa Anda ikuti:

  1. Coba representasi matriks yang lebih efisien yang mengeksploitasi struktur khusus yang dimiliki matriks Anda. Misalnya, seperti yang telah ditunjukkan orang lain, ada struktur data yang efisien untuk matriks renggang (matriks dengan banyak nol), seperti scipy.sparse.csc_matrix.
  2. Ubah algoritme Anda untuk bekerja pada submatrices . Anda hanya dapat membaca dari disk blok matriks yang saat ini digunakan dalam komputasi. Algoritme yang dirancang untuk berjalan di kluster biasanya bekerja sesuai arah jarum jam, karena data tersebar di berbagai komputer, dan hanya diteruskan saat diperlukan. Misalnya algoritma Fox untuk perkalian matriks (file PDF) .

4
3- Melangkah dalam paradigma Big Data dan mempelajari solusi seperti MapReduce
Medeiros

Untuk nomor 2, bagaimana Anda memutuskan seberapa besar membuat potongan Anda? Adakah cara untuk mengukur jumlah memori bebas dan ukuran potongan Anda berdasarkan itu?
endolith

30

Anda harus dapat menggunakan numpy.memmap untuk memetakan memori file pada disk. Dengan python dan mesin 64-bit yang lebih baru, Anda harus memiliki ruang alamat yang diperlukan, tanpa memuat semuanya ke dalam memori. OS harus menangani hanya menyimpan sebagian dari file di memori.


19
Bisakah Anda memberikan contoh bagaimana menggunakannya untuk melakukan sesuatu yang tidak muat dalam memori?
endolith

24

Untuk menangani matriks renggang, Anda memerlukan scipypaket yang berada di atasnya numpy- lihat di sini untuk detail selengkapnya tentang opsi matriks renggang yang scipymemberi Anda.


11

Posting Stefano Borini membuat saya melihat sejauh mana hal semacam ini sudah terjadi.

Ini dia. Tampaknya pada dasarnya melakukan apa yang Anda inginkan. HDF5 memungkinkan Anda menyimpan kumpulan data yang sangat besar, lalu mengakses dan menggunakannya dengan cara yang sama seperti yang dilakukan NumPy.


9
Pilihan yang lebih baik mungkin PyTables. Ini tingkat yang lebih tinggi daripada fungsionalitas inti HDF5 (H5Py sedikit lebih dari API tingkat rendah yang dapat diakses dari Python). Juga beta 2.2 minggu lalu memiliki alat untuk masalah ini: pytables.org/moin/ReleaseNotes/Release_2.2b1 Ditambahkan Ekspr , kelas [yang] dapat mengevaluasi ekspresi (seperti '3 * a + 4 * b') yang beroperasi pada sembarang besar array sambil mengoptimalkan sumber daya [...]. Ini mirip dengan paket Numexpr, tetapi selain objek NumPy, ia juga menerima array homogen berbasis disk, seperti objek Array, CArray, EArray dan Column PyTables.
AFoglia

5

Pastikan Anda menggunakan sistem operasi 64-bit dan Python / NumPy versi 64-bit. Perhatikan bahwa pada arsitektur 32-bit Anda biasanya dapat menangani memori 3GB (dengan sekitar 1GB hilang ke memori yang dipetakan I / O dan semacamnya).

Dengan 64-bit dan array hal-hal yang lebih besar dari RAM yang tersedia, Anda dapat menggunakan memori virtual, meskipun semuanya akan menjadi lebih lambat jika Anda harus menukar. Selain itu, peta memori (lihat numpy.memmap) adalah cara untuk bekerja dengan file besar pada disk tanpa memuatnya ke memori, tetapi sekali lagi, Anda perlu memiliki ruang alamat 64-bit untuk digunakan agar hal ini banyak berguna. PyTables akan melakukan sebagian besar untuk Anda juga.



4

Terkadang satu solusi sederhana menggunakan tipe kustom untuk item matriks Anda. Berdasarkan kisaran nomor yang Anda butuhkan, Anda dapat menggunakan manual dtypedan khusus lebih kecil untuk item Anda. Karena Numpy menganggap tipe terbesar untuk objek secara default, ini mungkin ide yang berguna dalam banyak kasus. Berikut ini contohnya:

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

Dan dengan tipe khusus:

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

Apakah Anda bertanya bagaimana menangani 2.500.000.000 elemen matriks tanpa terabyte RAM?

Cara menangani 2 miliar item tanpa 8 miliar byte RAM adalah dengan tidak menyimpan matriks di memori.

Itu berarti algoritma yang jauh lebih canggih untuk mengambilnya dari sistem file dalam beberapa bagian.


7
Tidak benar. Jika 99,99% (untuk contoh realistis) dari elemen adalah nol, maka semua data matriks dapat disimpan dalam memori. Tidak perlu menggunakan hingga 4 byte untuk setiap nol, saat Anda bisa menyimpan daftar (row, column, value)entri yang memang ada.
Eric Wilson

6
@EricWilson: Di mana dalam pertanyaan itu menunjukkan bahwa matriks itu jarang? Saya sangat merindukan itu. Bisakah Anda memberikan kutipan?
S. Lotot

1

Biasanya ketika kita berurusan dengan matriks besar, kita menerapkannya sebagai Matriks Renggang .

Saya tidak tahu apakah numpy mendukung matriks jarang tetapi saya menemukan ini sebagai gantinya.


1

Sejauh yang saya tahu tentang numpy, tidak, tapi saya bisa saja salah.

Saya dapat mengusulkan solusi alternatif ini: tulis matriks pada disk dan akses dalam potongan. Saya sarankan Anda format file HDF5. Jika Anda membutuhkannya secara transparan, Anda dapat mengimplementasikan kembali antarmuka ndarray untuk mem-paginasi matriks yang disimpan disk ke dalam memori. Hati-hati jika Anda mengubah data untuk menyinkronkannya kembali ke disk.


Bagaimana jika saya ingin mengakses seluruh matriks 57600 x 57600?
Gunjan naik
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.