Каковы преимущества NumPy перед обычными списками Python?
-
13-09-2019 - |
Вопрос
В чем преимущества NumPy над обычными списками Python?
У меня есть около 100 серий финансовых рынков, и я собираюсь создать массив кубов размером 100x100x100 = 1 миллион ячеек.Я буду регрессировать (с тремя переменными) каждый x по каждому y и z, чтобы заполнить массив стандартными ошибками.
Я слышал, что для «больших матриц» мне следует использовать NumPy, а не списки Python, из соображений производительности и масштабируемости.Дело в том, что я знаю списки Python, и они, похоже, мне подходят.
Какие преимущества я получу, если перейду на NumPy?
Что, если бы у меня было 1000 серий (то есть 1 миллиард ячеек с плавающей запятой в кубе)?
Решение
Массивы NumPy более компактны, чем списки Python - список списков, как вы описываете, в Python займет не менее 20 МБ или около того, а 3D-массив NumPy с числами с плавающей запятой одинарной точности уместится в 4 МБ.Доступ к элементам чтения и записи также ускоряется с помощью NumPy.
Возможно, вас не так уж волнует миллион ячеек, но вас определенно волнует миллиард ячеек - ни один из подходов не подходит для 32-битной архитектуры, но с 64-битными сборками NumPy сойдет с рук 4 ГБ или около того. , одному Python потребуется как минимум около 12 ГБ (множество указателей, размер которых удваивается) — гораздо более дорогостоящее оборудование!
Разница в основном связана с «косвенностью»: список Python представляет собой массив указателей на объекты Python, не менее 4 байтов на указатель плюс 16 байтов даже для самого маленького объекта Python (4 для указателя типа, 4 для счетчика ссылок, 4 для значения - и распределители памяти округляют до 16).Массив NumPy представляет собой массив однородных значений: числа одинарной точности занимают 4 байта каждое, числа двойной точности — 8 байтов.Менее гибкий, но за гибкость стандартных списков Python приходится платить значительную сумму!
Другие советы
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 стоит затраченных усилий.
Алекс упомянул эффективность памяти, а Роберто упомянул удобство, и это оба хорошие моменты.Еще несколько идей, я упомяну скорость и функциональность.
Функциональность:Вы получаете множество встроенных функций: NumPy, FFT, свертки, быстрый поиск, базовую статистику, линейную алгебру, гистограммы и т. д.И действительно, кто может жить без БПФ?
Скорость:Вот тест на суммирование по списку и массиву 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
Вот хороший ответ из FAQ на сайт scipy.org:
Какие преимущества имеют массивы NumPy по сравнению с (вложенными) списками Python?
Списки Python — это эффективные контейнеры общего назначения.Они поддерживают (справедливо) эффективную вставку, удаление, добавление и конкатенацию, а понимание списка Python позволяет им легко строить и манипулировать.Однако у них есть определенные ограничения:Они не поддерживают «векторизованные» операции, такие как элемент, добавление и умножение, и тот факт, что они могут содержать объекты различных типов, означает, что Python должен хранить информацию типа для каждого элемента и должен выполнять код отправки типа при работе на каждом элементе.Это также означает, что очень немногие операции списка могут быть выполнены с помощью эффективных петлей C - каждая итерация потребует проверки типа и другой бухгалтерии Python API.
Все они выделили почти все основные различия между массивом numpy и списком Python, я просто кратко изложу их здесь:
Массивы Numpy имеют фиксированный размер при создании, в отличие от списков Python (которые могут динамически расти).Изменение размера ndarray приведет к созданию нового массива и удалению оригинала.
Все элементы массива Numpy должны иметь один и тот же тип данных (у нас также может быть гетерогенный тип, но это не позволит вам выполнять математические операции) и, следовательно, они будут иметь одинаковый размер в памяти.
Массивы Numpy облегчают математические и другие типы операций с большими объемами данных.Обычно такие операции выполняются более эффективно и с меньшим количеством кода, чем это возможно при использовании последовательностей Python.