NumPy (произносится / ˈ n ʌ m p aɪ / NUM -py ) — библиотека для языка программирования Python , добавляющая поддержку больших многомерных массивов и матриц , а также большую коллекцию математических функций высокого уровня для работы с ними. эти массивы. [3] Предшественник NumPy, Numeric, был первоначально создан Джимом Хугунином при участии нескольких других разработчиков. В 2005 году Трэвис Олифант создал NumPy, включив в Numeric функции конкурирующего Numarray с обширными модификациями. NumPy — это программное обеспечение с открытым исходным кодом , в котором участвует множество разработчиков. NumPy — это проект, финансируемый NumFOCUS. [4]
Язык программирования Python изначально не был разработан для численных вычислений, но сразу привлек внимание научного и инженерного сообщества. В 1995 году была основана группа специальных интересов (SIG) Matrix-sig с целью определения пакета вычислений на массивах ; среди его членов был дизайнер и сопровождающий Python Гвидо ван Россум , который расширил синтаксис Python (в частности, синтаксис индексации [5] ), чтобы упростить вычисления с массивами . [6]
Реализация матричного пакета была завершена Джимом Фултоном, затем обобщена [ необходимо дальнейшее объяснение ] Джимом Хугунином и названа Numeric [6] (также известным как «Числовые расширения Python» или «NumPy») с влиянием APL . семейство языков Basis, MATLAB , FORTRAN , S и S+ и другие. [7] [8] Хугунин, аспирант Массачусетского технологического института (MIT), [8] : 10 присоединился к Корпорации национальных исследовательских инициатив (CNRI) в 1997 году для работы над JPython , [6] оставив Поля Дюбуа из Ливерморская национальная лаборатория Лоуренса (LLNL) возьмет на себя обязанности специалиста по сопровождению. [8] : 10 Среди других первых участников — Дэвид Ашер, Конрад Хинсен и Трэвис Олифант . [8] : 10
Новый пакет под названием Numarray был написан как более гибкая замена Numeric. [9] Как и Numeric, он также устарел. [10] [11] Numarray имел более быстрые операции для больших массивов, но был медленнее, чем Numeric для маленьких, [12] поэтому какое-то время оба пакета использовались параллельно для разных случаев использования. Последняя версия Numeric (v24.2) была выпущена 11 ноября 2005 г., а последняя версия numarray (v1.5.2) — 24 августа 2006 г. [13]
Было желание занести Numeric в стандартную библиотеку Python, но Гвидо ван Россум решил, что код в том виде, в котором он тогда был, не поддерживается. [ когда? ] [14]
В начале 2005 года разработчик NumPy Трэвис Олифант захотел объединить сообщество вокруг единого пакета массивов и перенес функции Numarray в Numeric, выпустив результат как NumPy 1.0 в 2006 году. [9] Этот новый проект был частью SciPy . Чтобы избежать установки большого пакета SciPy только для получения объекта массива, этот новый пакет был отделен и назван NumPy. Поддержка Python 3 была добавлена в 2011 году в NumPy версии 1.5.0. [15]
В 2011 году PyPy начала разработку реализации API NumPy для PyPy. [16] По состоянию на 2023 год он еще не полностью совместим с NumPy. [17]
NumPy нацелен на эталонную реализацию Python CPython , которая представляет собой неоптимизирующий интерпретатор байт-кода . Математические алгоритмы , написанные для этой версии Python, часто работают намного медленнее, чем скомпилированные эквиваленты, из-за отсутствия оптимизации компилятора. NumPy частично решает проблему медленности, предоставляя многомерные массивы, функции и операторы, которые эффективно работают с массивами; их использование требует переписывания некоторого кода, в основном внутренних циклов , с использованием NumPy.
Использование NumPy в Python дает функциональность, сравнимую с MATLAB , поскольку они оба интерпретируются [18] и оба позволяют пользователю писать быстрые программы, поскольку большинство операций работают с массивами или матрицами, а не со скалярами . Для сравнения, MATLAB может похвастаться большим количеством дополнительных наборов инструментов, в частности Simulink , тогда как NumPy внутренне интегрирован с Python, более современным и полным языком программирования . Кроме того, доступны дополнительные пакеты Python; SciPy — это библиотека, которая добавляет больше функций, подобных MATLAB, а Matplotlib — это пакет для построения графиков , который обеспечивает функции построения графиков, подобные MATLAB. Хотя Matlab может выполнять операции с разреженными матрицами, numpy сам по себе не может выполнять такие операции и требует использования библиотеки scipy.sparse. Внутри MATLAB и NumPy используются BLAS и LAPACK для эффективных вычислений линейной алгебры .
Привязки Python широко используемой библиотеки компьютерного зрения OpenCV используют массивы NumPy для хранения данных и работы с ними. Поскольку изображения с несколькими каналами представляются просто как трехмерные массивы, индексирование, нарезка или маскирование с помощью других массивов являются очень эффективными способами доступа к определенным пикселям изображения. Массив NumPy как универсальная структура данных в OpenCV для изображений, извлеченных точек функций , ядер фильтров и многого другого значительно упрощает рабочий процесс программирования и отладки . [ нужна цитата ]
Важно отметить, что многие операции NumPy выпускают GIL , который обеспечивает многопоточную обработку. [19]
NumPy также предоставляет C API, который позволяет коду Python взаимодействовать с внешними библиотеками, написанными на языках низкого уровня. [20]
Основная функциональность NumPy — это «ndarray», для n -мерного массива, структура данных . Эти массивы представляют собой пошаговые представления о памяти. [9] В отличие от встроенной в Python структуры данных списка, эти массивы имеют однородную типизацию: все элементы одного массива должны быть одного типа.
Такие массивы также можно просматривать в буферах памяти, выделенных расширениями C / C++ , Python и Fortran для интерпретатора CPython, без необходимости копировать данные, что обеспечивает определенную степень совместимости с существующими числовыми библиотеками. Эта функциональность используется пакетом SciPy, в который входит ряд таких библиотек (в частности, BLAS и LAPACK). NumPy имеет встроенную поддержку ndarrays, отображаемых в памяти . [9]
Вставка или добавление записей в массив не так тривиальна, как со списками Python. Процедура np.pad(...)
расширения массивов фактически создает новые массивы желаемой формы и значений заполнения, копирует данный массив в новый и возвращает его. Операция NumPy np.concatenate([a1,a2])
на самом деле не связывает два массива, а возвращает новый, последовательно заполненный записями из обоих заданных массивов. Изменение размерности массива с помощью np.reshape(...)
возможно только до тех пор, пока количество элементов в массиве не изменится. Эти обстоятельства возникают из-за того, что массивы NumPy должны представлять собой представления в смежных буферах памяти . Пакет замены под названием Blaze пытается преодолеть это ограничение. [21]
Алгоритмы , которые невозможно выразить в виде векторизованной операции, обычно работают медленно, поскольку их необходимо реализовать на «чистом Python», тогда как векторизация может увеличить сложность памяти для некоторых операций с константной до линейной, поскольку необходимо создавать временные массивы размером с входы. Компиляция числового кода во время выполнения была реализована несколькими группами, чтобы избежать этих проблем; решения с открытым исходным кодом, которые взаимодействуют с NumPy, включают numexpr [22] и Numba . [23] Cython и Pythran являются альтернативами статической компиляции.
Многие современные крупномасштабные научные вычислительные приложения предъявляют требования, превосходящие возможности массивов NumPy. Например, массивы NumPy обычно загружаются в память компьютера , емкость которой может оказаться недостаточной для анализа больших наборов данных . Кроме того, операции NumPy выполняются на одном процессоре . Однако многие операции линейной алгебры можно ускорить, выполняя их на кластерах ЦП или специализированном оборудовании, таком как графические процессоры и ТПУ , на которые полагаются многие приложения глубокого обучения . В результате за последние годы в научной экосистеме Python появилось несколько альтернативных реализаций массивов, таких как Dask для распределенных массивов и TensorFlow или JAX для вычислений на графических процессорах. Из-за своей популярности они часто реализуют подмножество API NumPy или имитируют его, так что пользователи могут изменить реализацию своего массива с минимальными изменениями в своем коде. [3] Недавно представленная библиотека CuPy , [24] ускоренная с помощью платформы CUDA от Nvidia , также продемонстрировала потенциал для более быстрых вычислений, являясь « заменой » NumPy. [25]
импортируйте numpy как np из numpy.random, импортируйте rand из numpy.linalg, импортируйте решение , inv a = np . массив ([[ 1 , 2 , 3 , 4 ],[ 3 , 4 , 6 , 7 ],[ 5 , 9 , 0 , 5 ]]) a . транспонировать ()
>>> а = НП . массив ([ 1 , 2 , 3 , 6 ]) >>> b = np . linspace ( 0 , 2 , 4 ) # создаем массив из четырех одинаково расположенных точек, начиная с 0 и заканчивая 2. >>> c = a - b >>> c array ([ 1. , 1.33333333 , 1.66666667 , 2. ] ) >>> массив ** 2 ([ 1 , 4 , 9 , 36 ] )
>>> а = НП . linspace ( - np . pi , np . pi , 100 ) >>> b = np . грех ( а ) >>> c = np . cos ( a ) >> >>> # Функции могут принимать в качестве параметров как числа, так и массивы. >>> нп . грех ( 1 ) 0,8414709848078965 >>> np . sin ( np . array ([ 1 , 2 , 3 ])) массив ([ 0.84147098 , 0.90929743 , 0.14112001 ])
>>> из numpy.random import rand >>> из numpy.linalg importsolve , inv >>> a = np . _ массив ([[ 1 , 2 , 3 ], [ 3 , 4 , 6.7 ], [ 5 , 9.0 , 5 ]]) >>> a . transpose () массив ([[ 1. , 3. , 5. ], [ 2. , 4. , 9. ], [ 3. , 6.7 , 5. ]]) >>> inv ( a ) массив ([[ - 2,27683616 , 0,96045198 , 0,07909605 , [ 1,04519774 , - 0,56497175 , 0,1299435 ], [ 0,39548023 , 0,05649718 , - 0,11299435 ]]) > >> б = НП . array ([ 3 , 2 , 1 ]) >>> решить ( a , b ) # решить уравнение ax = b array ([ - 4.83050847 , 2.13559322 , 1.18644068 ]) >>> c = rand ( 3 , 3 ) * 20 # создаем случайную матрицу 3x3 значений в пределах [0,1], масштабированную на 20 >>> c array ( [[ 3.98732789 , 2.47702609 , 4.71167924 ], [ 9.24410671 , 5.5240412 , 10.6468792 ] , [ 10.38136661 , 8.44968437 , 15.17639591 ]]) > >> НП . dot ( a , c ) # массив умножения матрицы ([[ 53.61964114 , 38.8741616 , 71.53462537 ], [ 118.4935668 , 86.14012835 , 158.40440712 ], [ 155.04043289 , 104.3499231 , 195.26228855 ]]) >>> a @c # Начиная с массива Python 3.5 и NumPy 1.10 ([[ 53 .61964114 , 38.8741616 , 71.53462537 ], [ 118.4935668 , 86.14012835 , 158.40440712 ], [ 155.04043289 , 104.3499231 , 195.26228855 ]])
>>> М = нп . нули ( форма = ( 2 , 3 , 5 , 7 , 11 )) >>> T = np . транспонировать ( M , ( 4 , 2 , 1 , 3 , 0 )) >>> T . форма ( 11 , 5 , 3 , 7 , 2 )
>>> импортировать numpy как np >>> импортировать cv2 >>> r = np . reshape ( np . arange ( 256 * 256 ) % 256 ,( 256 , 256 )) # Массив пикселей 256x256 с горизонтальным градиентом от 0 до 255 для канала красного цвета >>> g = np . Zeros_like ( r ) # массив того же размера и типа, что и r, но заполнен нулями для канала зеленого цвета >>> b = r . T # транспонированный r даст вертикальный градиент для канала синего цвета >>> cv2 . imwrite ( 'gradients.png' , np . dstack ([ b , g , r ])) # Изображения OpenCV интерпретируются как BGR, массив с накоплением глубины будет записан в 8-битный PNG-файл RGB с именем 'gradients.png' Истинный
Итерационный алгоритм Python и векторизованная версия NumPy.
>>> # # # Чистый итеративный Python # # # >>> Points = [[ 9 , 2 , 8 ],[ 4 , 7 , 2 ],[ 3 , 4 , 4 ],[ 5 , 6 , 9 ], [ 5 , 0 , 7 ],[ 8 , 2 , 7 ],[ 0 , 3 , 2 ],[ 7 , 3 , 0 ],[ 6 , 1 , 1 ],[ 2 , 9 , 6 ]] >> > qPoint = [ 4 , 5 , 3 ] >>> minIdx = - 1 >>> minDist = - 1 >>> для idx , точка в перечислении ( points ): # перебрать все точки ... dist = sum ([ ( dp - dq ) ** 2 for dp , dq в zip ( point , qPoint )]) ** 0.5 # вычислить евклидово расстояние для каждой точки до q ... if dist < minDist или minDist < 0 : # если необходимо, обновить минимальное расстояние и индекс соответствующей точки ... minDist = dist ... minIdx = idx>>> print ( f 'Ближайшая точка к q: { points [ minIdx ] } ' ) Ближайшая точка к q : [ 3 , 4 , 4 ]>>> # # # Эквивалентная векторизация NumPy # # # >>> import numpy как np >>> Points = np . массив ([[ 9 , 2 , 8 ],[ 4 , 7 , 2 ],[ 3 , 4 , 4 ],[ 5 , 6 , 9 ],[ 5 , 0 , 7 ],[ 8 , 2 , 7 ] ,[ 0 , 3 , 2 ],[ 7 , 3 , 0 ],[ 6 , 1 , 1 ],[ 2 , 9 , 6 ]]) >>> qPoint = np . массив ([ 4 , 5 , 3 ]) >>> minIdx = np . argmin ( np.linalg.norm ( points - qPoint , axis = 1 )) # вычислить все евклидовы расстояния одновременно и вернуть индекс наименьшего из них >>> print ( f ' Ближайшая точка к q : { points [ minIdx ] } ' ) Ближайшая точка к q : [ 3 4 4 ]
Быстро переносите собственный код для более быстрых сценариев. [26] [27] [28]
! Пример вызова собственного кода Python Fortran ! f2py -c -m foo *.f90 ! Скомпилируйте Fortran в именованный модуль Python, используя операторы намерения ! Только подпрограммы Фортрана не являются функциями - проще, чем JNI с оболочкой C ! требует gfortran и делает подпрограмму ftest ( a , b , n , c , d ) неявной none целое , намерение ( in ) :: a целое число , намерение ( in ) :: b целое число , намерение ( in ) :: n целое число , намерение ( out ) :: c целое число , намерение ( out ) :: d целое число :: i c = 0 do i = 1 , n c = a + b + c end do d = ( c * n ) * ( - 1 ) конец подпрограммы ftest
>>> импортировать numpy как np >>> импортировать foo >>> a = foo . ftest ( 1 , 2 , 3 ) # или c,d = вместо ac и ad >>> print ( a ) (9,-27) >>> help ( 'foo.ftest' ) # foo.ftest.__doc__