В чем преимущества NumPy перед обычными списками Python?

Каковы преимущества NumPy перед обычными списками Python?

У меня около 100 серий финансовых рынков, и я собираюсь создать кубический массив размером 100x100x100 = 1 миллион ячеек. Я буду регрессировать (3-переменные) каждый x с каждым y и z, чтобы заполнить массив стандартными ошибками.

Я слышал, что для «больших матриц» я должен использовать NumPy, а не списки Python из соображений производительности и масштабируемости. Дело в том, что я знаю списки Python, и, похоже, они мне подходят.

Какие будут преимущества, если я перейду на NumPy?

Что, если бы у меня было 1000 серий (то есть 1 миллиард ячеек с плавающей запятой в кубе)?


person Thomas Browne    schedule 14.06.2009    source источник


Ответы (5)


Массивы NumPy более компактны, чем списки Python - список списков, который вы описываете в Python, займет не менее 20 МБ или около того, в то время как трехмерный массив NumPy с плавающими точками одинарной точности в ячейках уместится в 4 МБ. Доступ к чтению и записи также стал быстрее с NumPy.

Может быть, вас не слишком заботит всего миллион ячеек, но вы определенно хотели бы получить миллиард ячеек - ни один подход не подходит для 32-битной архитектуры, но с 64-битными сборками NumPy уйдет с 4 ГБ или около того. , Одному Python потребуется как минимум около 12 ГБ (много указателей, размер которых удваивается) - гораздо более дорогостоящее оборудование!

Разница в основном связана с «косвенностью» - список Python представляет собой массив указателей на объекты Python, по крайней мере, 4 байта на указатель плюс 16 байтов даже для самого маленького объекта Python (4 для указателя типа, 4 для счетчика ссылок, 4 для значения - и распределители памяти округляются до 16). Массив NumPy - это массив однородных значений: числа с одинарной точностью занимают 4 байта каждое, с двойной точностью - 8 байтов. Менее гибкий, но вы существенно платите за гибкость стандартных списков Python!

person Alex Martelli    schedule 14.06.2009
comment
Я пытался использовать sys.getsizeof () для сравнения размеров списков Python и массивов NumPy с одинаковым количеством элементов, и это, похоже, не указывает на то, что массивы NumPy были намного меньше. Так ли это или у sys.getsizeof () возникают проблемы с определением размера массива NumPy? - person Jack Simpson; 08.06.2016
comment
@JackSimpson getsizeof ненадежен. В документации четко указано, что: Учитывается только потребление памяти, напрямую связанное с объектом, а не потребление памяти объектами, на которые он ссылается. Это означает, что если у вас есть вложенный python, перечисляет размер элементов не принимается во внимание. - person Bakuriu; 09.08.2016
comment
getsizeof в списке только сообщает вам, сколько ОЗУ потребляет сам объект списка, и ОЗУ, потребляемое указателями в его массиве данных, но не сообщает вам, сколько ОЗУ потребляется объектами, на которые ссылаются эти указатели. - person PM 2Ring; 10.10.2016
comment
@AlexMartelli, дайте мне знать, откуда у вас эти числа? - person lmiguelvargasf; 06.05.2017
comment
Предупреждаем, ваша оценка размера эквивалентного списка списков Python отключена. Массив numpy размером 4 ГБ из C floats (4 байта) будет преобразован в значение, близкое к 32 ГБ, равное lists и Python float (которые на самом деле являются C doubles), а не 12 ГБ; каждый float на 64-битном Python занимает ~ 24 байта (при условии отсутствия потерь выравнивания в распределителе) плюс еще 8 байтов в list для хранения ссылки (и это игнорирует превышение доступности и заголовки объектов для самих lists, что может добавить еще один ГБ в зависимости от того, насколько точно происходит превышение доступности). - person ShadowRanger; 08.11.2018
comment
Вы могли бы получить список списков Python до 8 ГБ, если бы все сохраненные float ссылались на тот же float, но учитывая, что Python не имеет float кеширования, ничего, кроме того же значения снова и снова (бесполезно) потребовало бы, чтобы вы вручную реализовали интернирование для ваших float, чтобы добиться этого сокращения памяти, и кажется маловероятным, что у вас будет так мало уникальных float, которые поможет интернирование (поскольку сам внутренний кеш в конечном итоге окажется в конечном итоге потребляет тонну памяти). - person ShadowRanger; 08.11.2018
comment
Я также отмечу, что если использование памяти является единственной проблемой, Встроенный в Python модуль array может уже компактно хранить float (хотя нарезка не приведет к дешевым представлениям без явного использования memoryview, где numpy нарезка по умолчанию выполняется для представлений). Преимущества numpy заключаются в эффективном и удобном использовании данных, а не только в их эффективном хранении. - person ShadowRanger; 14.08.2019
comment
Использует ли указатель в numpy быстрее, чем список? Например, array[0:104:52] быстрее, чем list[0][104][52]. - person Fateh; 02.05.2020

NumPy не только более эффективен; это тоже удобнее. Вы получаете бесплатно множество векторных и матричных операций, которые иногда позволяют избежать ненужной работы. И они тоже эффективно реализуются.

Например, вы можете прочитать свой куб прямо из файла в массив:

x = numpy.fromfile(file=open("data"), dtype=float).reshape((100, 100, 100))

Сумма по второму измерению:

s = x.sum(axis=1)

Найдите, какие ячейки находятся выше порогового значения:

(x > 0.5).nonzero()

Удалите каждый срез с четным индексом по третьему измерению:

x[:, :, ::2]

Также многие полезные библиотеки работают с массивами NumPy. Например, библиотеки статистического анализа и визуализации.

Даже если у вас нет проблем с производительностью, изучение NumPy того стоит.

person Roberto Bonvallet    schedule 14.06.2009
comment
Спасибо - вы указали еще одну вескую причину в своем третьем примере, так как я действительно буду искать в матрице ячейки выше порогового значения. Более того, я загружался из sqlLite. Файловый подход будет намного эффективнее. - person Thomas Browne; 15.06.2009

Алекс упомянул об эффективности памяти, а Роберто упомянул об удобстве, и это хорошие моменты. В качестве дополнительных идей я упомяну скорость и функциональность.

Функциональность: вы получаете много встроенных функций с NumPy, БПФ, свертками, быстрым поиском, базовой статистикой, линейной алгеброй, гистограммами и т. Д. И действительно, кто может жить без БПФ?

Скорость: вот тест по суммированию по списку и массиву NumPy, показывающий, что сумма в массиве NumPy в 10 раз быстрее (в этом тесте пробег может отличаться).

from numpy import arange
from timeit import Timer

Nelements = 10000
Ntimeits = 10000

x = arange(Nelements)
y = range(Nelements)

t_numpy = Timer("x.sum()", "from __main__ import x")
t_list = Timer("sum(y)", "from __main__ import y")
print("numpy: %.3e" % (t_numpy.timeit(Ntimeits)/Ntimeits,))
print("list:  %.3e" % (t_list.timeit(Ntimeits)/Ntimeits,))

который в моих системах (пока я выполняю резервное копирование) дает:

numpy: 3.004e-05
list:  5.363e-04
person tom10    schedule 15.06.2009

Вот хороший ответ из часто задаваемых вопросов на сайт scipy.org:

Какие преимущества массивы NumPy предлагают по сравнению со (вложенными) списками Python?

Списки Python - это эффективные универсальные контейнеры. Они поддерживают (довольно) эффективную вставку, удаление, добавление и конкатенацию, а понимание списков Python упрощает их создание и управление. Однако у них есть определенные ограничения: они не поддерживают «векторизованные» операции, такие как поэлементное сложение и умножение, а тот факт, что они могут содержать объекты разных типов, означает, что Python должен хранить информацию о типе для каждого элемента и должен выполнять код диспетчеризации типов. при работе с каждым элементом. Это также означает, что очень немногие операции со списками могут выполняться с помощью эффективных циклов C - каждая итерация потребует проверки типов и другого учета Python API.

person Eliezer    schedule 11.09.2014

Все подчеркнули почти все основные различия между массивом numpy и списком Python, я просто кратко их здесь:

  1. Массивы Numpy имеют фиксированный размер при создании, в отличие от списков Python (которые могут расти динамически). Изменение размера ndarray создаст новый массив и удалит оригинал.

  2. Все элементы в массиве Numpy должны иметь один и тот же тип данных (у нас также может быть гетерогенный тип, но это не позволит вам выполнять математические операции), и, следовательно, они будут одинакового размера в памяти

  3. Облегченные массивы Numpy позволяют выполнять математические и другие операции с большим количеством данных. Обычно такие операции выполняются более эффективно и с меньшим количеством кода, чем это возможно при использовании последовательностей, встроенных в питоны.

person Parvez Khan    schedule 05.02.2019