NumPy

Материал из llmdocs — справочник разработчика
Портал: Python
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]

См. также

Источники

  1. C. R. Harris et al. — Array programming with NumPy (Nature, 2020)
  2. NumPy Documentation
  3. NumPy — the absolute basics for beginners
  4. NumPy — Broadcasting
  5. NumPy 2.0 migration guide
  6. Python array API standard