Дуже великі матриці з використанням Python та NumPy


86

NumPy - надзвичайно корисна бібліотека, і, використовуючи її, я виявив, що вона здатна легко обробляти досить великі матриці (10000 x 10000), але починає боротися з чимось набагато більшим (намагається створити матрицю 50000 x 50000 не вдається). Очевидно, це пов’язано з величезними вимогами до пам’яті.

Чи є спосіб створити величезні матриці власним чином у NumPy (скажімо, 1 мільйон на 1 мільйон) якимось чином (не маючи декількох терабайт оперативної пам'яті)?

Відповіді:


91

PyTables і NumPy - це шлях.

PyTables зберігатиме дані на диску у форматі HDF з додатковим стисненням. Мої набори даних часто отримують 10-кратне стиснення, що зручно при роботі з десятками або сотнями мільйонів рядків. Це також дуже швидко; мій 5-річний ноутбук може прокручувати дані, виконуючи SQL-подібне GROUP BY агрегація на 1000000 рядків / секунду. Непогано для рішення на основі Python!

Знову отримати доступ до даних як перезапис NumPy так просто:

data = table[row_from:row_to]

Бібліотека HDF дбає про читання відповідних фрагментів даних та перетворення в NumPy.


4
Тож вам все одно доведеться розбивати дані на шматки для обробки? Це просто спосіб спростити перетворення на та з дискових файлів?
ендоліт

Будь-який шанс, що ви могли б розширити свою відповідь трохи більше наочності та кількох прикладів?
Адам Б

56

numpy.arrays призначені для життя в пам’яті. Якщо ви хочете працювати з матрицями, більшими за вашу оперативну пам’ять, вам доведеться обійти це. Є щонайменше два підходи, якими можна дотримуватися:

  1. Спробуйте більш ефективне представлення матриці, яке використовує будь-яку спеціальну структуру, яку мають ваші матриці. Наприклад, як вже вказували інші, існують ефективні структури даних для розріджених матриць (матриць з великою кількістю нулів), наприклад scipy.sparse.csc_matrix.
  2. Змініть свій алгоритм для роботи з підматрицями . Ви можете читати з диска лише ті матричні блоки, які зараз використовуються в обчисленнях. Алгоритми, призначені для роботи на кластерах, зазвичай працюють блочно, оскільки дані розкидані між різними комп'ютерами і передаються лише за потреби. Наприклад, алгоритм Фокса для множення матриць (файл PDF) .

4
3- Покрокове втілення парадигми великих даних та вивчення таких рішень, як MapReduce
Medeiros

Для числа 2, як ви вирішуєте, наскільки великими будуть ваші шматки? Чи є спосіб виміряти обсяг вільної пам'яті та розмір ваших шматків на основі цього?
ендоліт

30

Ви повинні мати можливість використовувати numpy.memmap для відображення в пам'яті файлу на диску. З новішими python та 64-розрядною машиною ви повинні мати необхідний адресний простір, не завантажуючи все в пам’ять. ОС повинна обробляти лише частину файлу в пам'яті.


18
Чи можете ви навести приклад того, як за його допомогою робити те, що не може поміститися в пам’яті?
ендоліт

24

Щоб обробляти розріджені матриці, вам потрібен scipyпакет, який знаходиться зверху numpy- див. Тут, щоб отримати докладнішу інформацію про варіанти розрідженої матриці scipy.


11

Пост Стефано Боріні змусив мене розібратися в тому, наскільки далеко це вже є.

Це воно. Здається, в основному ви робите те, що хочете. 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-розрядну операційну систему та 64-розрядну версію Python / NumPy. Зверніть увагу, що на 32-розрядних архітектурах ви можете адресувати, як правило, 3 ГБ пам’яті (приблизно 1 ГБ втрачено в пам’яті, що відображається на введення-виведення та ін.).

Завдяки 64-розрядному масиву та масивам речей, більших за доступну оперативну пам’ять, ви можете позбутися віртуальної пам’яті, хоча, якщо вам доведеться помінятися, все стане повільніше. Крім того, карти пам'яті (див. 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 мільярдів елементів без 8 мільярдів байт оперативної пам’яті полягає в недотриманні матриці в пам'яті.

Це означає набагато складніші алгоритми, щоб отримати його з файлової системи по частинах.


7
Неправда. Якщо 99,99% (для реалістичного прикладу) елементів дорівнюють нулю, то всі дані матриці можуть зберігатися в пам'яті. Не потрібно використовувати 4 байти для кожного нуля, коли ви можете просто зберегти список (row, column, value)тих записів, які існують.
Ерік Вілсон,

6
@EricWilson: Де у питанні це передбачало, що матриця була розрідженою? Я цілком скучив за цим. Ви можете надати ціну?
S.Lott,


1

Наскільки я знаю про numpy, ні, але я можу помилятися.

Я можу запропонувати вам таке альтернативне рішення: запишіть матрицю на диск і отримайте доступ до неї шматками. Я пропоную вам формат файлу HDF5. Якщо вам це потрібно прозоро, ви можете повторно застосувати інтерфейс ndarray, щоб перенести вашу матрицю, що зберігається на диску, у пам'ять. Будьте обережні, якщо ви модифікуєте дані, щоб синхронізувати їх назад на диску.


Що робити, якщо я хочу отримати доступ до цілої матриці 57600 на 57600?
Gunjan naik
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.