NumPy
| Тип | библиотека численных вычислений |
|---|---|
| Автор | Тревис Олифант |
| Первый выпуск | 2006 (предшественники — Numeric с 1995, Numarray) |
| Языки | Python, C |
| Лицензия | BSD |
| Ключевой объект | ndarray — многомерный однородный массив |
| NumPy 2.0 | июнь 2024 |
| Сайт | numpy.org |
NumPy (от Numerical Python) — библиотека для численных вычислений на Python. Её центральный объект — ndarray, многомерный массив чисел одного типа, хранящихся в памяти подряд. Операции над такими массивами выполняются в скомпилированном коде на C сразу над всеми элементами — это называется векторизацией — и работают в десятки и сотни раз быстрее циклов на Python.[1]
NumPy — фундамент научного стека Python: на нём построены pandas, SciPy, scikit-learn, Matplotlib, а интерфейс массивов NumPy повторяют PyTorch, JAX и CuPy.
История
В 1995 году Джим Хьюгунин создал пакет Numeric для работы с массивами в Python; позже появился конкурирующий Numarray, лучше справлявшийся с большими массивами. В 2005–2006 годах Тревис Олифант объединил их в один проект — NumPy, — покончив с расколом сообщества. В 2020 году вклад NumPy в науку отметила статья в журнале Nature: библиотека использовалась, в частности, при получении первого изображения чёрной дыры и обнаружении гравитационных волн.[1] Версия NumPy 2.0 (июнь 2024) стала первым крупным обновлением за 18 лет, очистив API и изменив правила приведения типов.[5]
Массивы
import numpy as np
a = np.array([1, 2, 3, 4]) # из списка
m = np.zeros((3, 4)) # матрица 3×4 из нулей
r = np.arange(0, 1, 0.25) # [0. , 0.25, 0.5 , 0.75]
x = np.linspace(0, 2 * np.pi, 100) # 100 точек на отрезке
rng = np.random.default_rng(42)
data = rng.normal(size=(1000, 3)) # 1000 строк, 3 столбца
print(data.shape, data.dtype, data.ndim) # (1000, 3) float64 2
У массива есть форма (shape) — размер по каждой оси, и тип данных (dtype): int64, float32, bool, complex128 и другие. Все элементы одного типа, поэтому массив занимает в разы меньше памяти, чем список Python, где каждое число — отдельный объект.[3]
Векторизация
prices = np.array([100.0, 250.0, 80.0])
qty = np.array([3, 1, 10])
total = prices * qty # поэлементно: [300., 250., 800.]
print(total.sum(), total.mean()) # агрегаты
print(np.sqrt(prices), prices > 90) # функции и сравнения тоже поэлементные
# вместо цикла: нормализация каждого столбца
normalized = (data - data.mean(axis=0)) / data.std(axis=0)
Параметр axis указывает, вдоль какой оси выполнять агрегацию: axis=0 — по строкам (для каждого столбца), axis=1 — по столбцам (для каждой строки).
Трансляция (broadcasting)
Массивы разной формы автоматически «растягиваются» до общей, если их размеры совместимы: сравнение идёт с последней оси, и размеры должны совпадать или один из них равняться 1.[4] Так из матрицы 1000×3 вычитается вектор средних длины 3 — без копирования данных и циклов. Трансляция — мощный, но коварный механизм: ошибка в форме иногда не вызывает исключения, а молча даёт неверный результат.
Индексация
data[0] # первая строка
data[:, 1] # второй столбец
data[10:20, :2] # срез строк и столбцов — представление, без копирования
data[data[:, 0] > 2] # логическая маска: строки, где первый столбец больше 2
data[[1, 5, 7]] # выборка по списку индексов — копия
Срезы возвращают представления (view) исходного массива: изменение среза меняет оригинал. Логическая и списочная индексация создают копию.
Линейная алгебра и прочее
@иnp.matmul— матричное умножение;np.linalg— обращение матриц, решение систем, собственные значения, разложения (SVD, QR) поверх оптимизированных библиотек BLAS и LAPACK.np.random.default_rng()— генераторы случайных чисел с воспроизводимостью по зерну.np.fft— быстрое преобразование Фурье.- Сохранение и загрузка:
np.save,np.load(формат.npy),np.savez_compressed.
Векторный поиск по эмбеддингам в простейшем виде — одна строка NumPy: scores = vectors @ query, а затем np.argsort(-scores)[:5].
Экосистема
| Библиотека | Связь с NumPy |
|---|---|
| pandas | таблицы поверх массивов NumPy (и Apache Arrow) |
| SciPy | оптимизация, статистика, обработка сигналов |
| scikit-learn | принимает и возвращает массивы NumPy |
| Matplotlib | графики из массивов |
| Numba | компиляция циклов над массивами в машинный код |
| CuPy, JAX, PyTorch | NumPy-подобные массивы на GPU |
Чтобы код мог работать с разными библиотеками массивов, сообщество разработало общий стандарт Array API.[6]
Советы
- Избегайте циклов Python по элементам массива — ищите векторизованную функцию или трансляцию.
- Следите за
dtype: целочисленные массивы переполняются молча, аfloat32вдвое экономнееfloat64. - Не добавляйте элементы в массив в цикле (
np.appendкопирует весь массив) — собирайте список и превращайте в массив один раз или выделяйте память заранее.
Полная справка — в документации NumPy.[2]