Очень большие матрицы с использованием Python и NumPy - PullRequest
82 голосов
/ 28 июня 2009

NumPy - чрезвычайно полезная библиотека, и благодаря ее использованию я обнаружил, что она способна легко обрабатывать матрицы довольно большого размера (10000 x 10000), но начинает бороться с чем-то гораздо большим ( попытка создать матрицу 50000 х 50000 не удалась). Очевидно, это связано с большими требованиями к памяти.

Есть ли способ каким-то образом создать огромные матрицы в NumPy (скажем, 1 на 1 миллион) (без использования нескольких терабайт ОЗУ)?

Ответы [ 11 ]

89 голосов
/ 30 июня 2009

PyTables и NumPy - путь.

PyTables будет хранить данные на диске в формате HDF с дополнительным сжатием. Мои наборы данных часто получают 10-кратное сжатие, что удобно при работе с десятками или сотнями миллионов строк. Это также очень быстро; мой 5-летний ноутбук может обрабатывать данные, выполняя SQL-подобную агрегацию GROUP BY со скоростью 1 000 000 строк в секунду. Неплохо для решения на основе Python!

Повторный доступ к данным как к массиву NumPy так же прост:

data = table[row_from:row_to]

Библиотека HDF обеспечивает чтение соответствующих фрагментов данных и преобразование их в NumPy.

54 голосов
/ 28 июня 2009

numpy.array с предназначены для жизни в памяти. Если вы хотите работать с матрицами, размер которых превышает объем вашей оперативной памяти, вы должны обойти это. Вы можете следовать как минимум двум подходам:

  1. Попробуйте более эффективное представление матрицы , которое использует любую специальную структуру, которая есть в ваших матрицах. Например, как уже указывали другие, существуют эффективные структуры данных для разреженных матриц (матриц с большим количеством нулей), например scipy.sparse.csc_matrix.
  2. Измените ваш алгоритм для работы с подматрицами . Вы можете читать с диска только те матричные блоки, которые в настоящее время используются в вычислениях. Алгоритмы, предназначенные для работы в кластерах, обычно работают блочно, поскольку данные разбросаны по разным компьютерам и передаются только при необходимости. Например, Алгоритм Фокса для умножения матриц (PDF-файл) .
30 голосов
/ 28 июня 2009

Вы должны быть в состоянии использовать numpy.memmap для отображения в памяти файла на диске. С новым Python и 64-битной машиной у вас должно быть необходимое адресное пространство, без загрузки всего в память. ОС должна обрабатывать только часть файла в памяти.

24 голосов
/ 28 июня 2009

Для обработки разреженных матриц вам понадобится пакет scipy, расположенный поверх numpy - см. здесь для получения дополнительной информации о параметрах разреженной матрицы, которые scipy дает вам.

11 голосов
/ 28 июня 2009

Пост Стефано Борини Пост заставил меня посмотреть, насколько далеко продвинулись подобные вещи.

Вот и все. Похоже, в основном, что вы хотите. HDF5 позволит вам хранить очень большие наборы данных, а затем получать к ним доступ и использовать их так же, как это делает NumPy.

5 голосов
/ 05 февраля 2013

Это немного альфа, но http://blaze.pydata.org/, похоже, работает над решением этой проблемы.

5 голосов
/ 19 августа 2009

Убедитесь, что вы используете 64-битную операционную систему и 64-битную версию Python / NumPy. Обратите внимание, что на 32-разрядных архитектурах вы можете адресовать обычно 3 ГБ памяти (примерно 1 ГБ теряется на ввод-вывод с отображением в памяти и т. Д.).

С 64-битными массивами и массивами вещей, которые больше, чем доступная оперативная память, вы можете обойтись без виртуальной памяти, хотя все будет медленнее, если вам придется поменяться местами. Кроме того, карты памяти (см. Numpy.memmap) - это способ работы с огромными файлами на диске без их загрузки в память, но опять же, вам нужно иметь 64-битное адресное пространство для работы, чтобы это было очень полезным. PyTables сделает большую часть этого для вас.

4 голосов
/ 28 июня 2009

Вы спрашиваете, как обрабатывать 2 500 000 000 элементов матрицы без терабайтов ОЗУ?

Способ обработки 2 миллиардов элементов без 8 миллиардов байтов ОЗУ заключается в отсутствии матрицы в памяти.

Это означает, что гораздо более сложные алгоритмы извлекают его из файловой системы по частям.

3 голосов
/ 04 октября 2016

Иногда одним простым решением является использование пользовательского типа для ваших элементов матрицы. Исходя из диапазона нужных вам чисел, вы можете использовать руководство 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
1 голос
/ 28 июня 2009

Насколько я знаю о numpy, нет, но я могу ошибаться.

Я могу предложить вам альтернативное решение: записать матрицу на диск и получить к ней доступ кусками. Я предлагаю вам формат файла HDF5. Если вам это нужно прозрачно, вы можете переопределить интерфейс ndarray, чтобы разбить вашу сохраненную на диске матрицу в памяти. Будьте осторожны, если вы изменяете данные для их синхронизации на диске.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...