Очень большие матрицы с использованием Python и NumPy

86

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

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

Питер
источник

Ответы:

91

PyTables и NumPy - это то, что вам нужно.

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

Получить доступ к данным в виде повторного массива NumPy также просто:

data = table[row_from:row_to]

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

Стивен Симмонс
источник
4
Значит, вам все равно придется самостоятельно разбивать данные на части для обработки? Это просто способ упростить преобразование файлов на диск и обратно?
Эндолит
Есть ли шанс, что вы могли бы расширить свой ответ немного большей ясностью и некоторыми примерами?
Adam B
56

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

  1. Попробуйте более эффективное матричное представление, которое использует любую особую структуру ваших матриц. Например, как уже отмечали другие, существуют эффективные структуры данных для разреженных матриц (матриц с большим количеством нулей), например scipy.sparse.csc_matrix.
  2. Измените свой алгоритм, чтобы он работал с подматрицами . Вы можете читать с диска только те блоки матриц, которые в настоящее время используются в вычислениях. Алгоритмы, разработанные для работы в кластерах, обычно работают поблочно, поскольку данные разбросаны по разным компьютерам и передаются только при необходимости. Например, алгоритм Фокса для умножения матриц (файл PDF) .
Роберто Бонвале
источник
4
3- Вступите в парадигму больших данных и изучите такие решения, как MapReduce
Медейрос
Что касается пункта 2, как вы решаете, насколько большими будут ваши чанки? Есть ли способ измерить объем свободной памяти и размер ваших блоков на основе этого?
endolith
30

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

Доплеровский сдвиг
источник
19
Можете ли вы привести пример того, как с его помощью делать то, что не помещается в памяти?
Эндолит
24

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

Алекс Мартелли
источник
11

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

Это оно. Кажется, он делает в основном то, что вы хотите. HDF5 позволит вам хранить очень большие наборы данных, а затем обращаться к ним и использовать их так же, как NumPy.

SingleNegationElimination
источник
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 также сделает большую часть этого за вас.

DWF
источник
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 разреженные матрицы, но вместо этого я нашел это .

Ник Дандулакис
источник
1

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

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

Стефано Борини
источник
Что, если я хочу получить доступ ко всей матрице 57600 на 57600?
Gunjan naik