Зачем нужен SciPy: алгоритмы поверх NumPy

NumPy умеет складывать и умножать массивы — но кто решит уравнение, найдёт минимум или возьмёт интеграл? Это SciPy.

SciPy — библиотека готовых, отлаженных численных алгоритмов, построенная поверх NumPy-массивов.

Где заканчивается NumPy

NumPy даёт массивы и быструю арифметику: сложить, умножить, взять синус от миллиона чисел. Но наука — это не только арифметика. Нужно решать задачи: найти корень уравнения, минимум функции, проинтегрировать, разложить матрицу, проверить статистическую гипотезу. Писать каждый такой алгоритм самому — долго и рискованно: легко ошибиться в численной устойчивости. SciPy берёт эту работу на себя.

Что внутри SciPy

SciPy — это набор тематических подмодулей. Вот основные (детально разберём дальше в курсе):

ПодмодульЗадача
scipy.linalgЛинейная алгебра: СЛАУ, разложения, собственные значения
scipy.optimizeМинимизация функций, поиск корней, подгонка кривых
scipy.integrateЧисленное интегрирование, решение ОДУ
scipy.interpolateИнтерполяция и сплайны
scipy.statsРаспределения, статтесты, описательная статистика
scipy.signalОбработка сигналов, фильтры, свёртки
scipy.specialСпециальные функции (гамма, Бесселя, эрфы)
scipy.sparseРазреженные матрицы
scipy.spatialПространственные структуры: KD-деревья, расстояния

Почему «не писать самому»: цена ошибки

Кажется, что найти корень уравнения легко — но наивный метод может разойтись или зациклиться. SciPy внутри использует методы с гарантиями сходимости, отслеживанием ошибок и краевыми случаями. Сравним: вот наивный поиск корня √2 методом бисекции «руками» (он работает, но мы сами следим за всем):

def f(x):
    return x * x - 2.0   # корень там, где x^2 = 2

lo, hi = 1.0, 2.0        # знаем: f(1)<0, f(2)>0
for _ in range(50):
    mid = (lo + hi) / 2
    if f(mid) > 0:
        hi = mid
    else:
        lo = mid

print("Корень из 2 ~", round((lo + hi) / 2, 10))

Вывод:

Корень из 2 ~ 1.4142135624

А в SciPy то же самое — одна строка, с проверкой сходимости и обработкой ошибок внутри:

from scipy.optimize import brentq
root = brentq(lambda x: x**2 - 2, 1, 2)
print(root)   # 1.4142135623730951

Как работает под капотом

SciPy почти ничего не считает «на Python». Под каждым подмодулем лежит мировая классика численных методов на Fortran/C: linalg зовёт LAPACK, integrate.quad — QUADPACK, fft — pocketfft, optimize — MINPACK. Эти библиотеки писали и отлаживали десятилетиями; они учитывают тонкости машинной арифметики (потерю точности, переполнение, плохо обусловленные матрицы). Когда вы зовёте scipy.linalg.solve(A, b), ваш массив отдаётся в LAPACK, тот выбирает устойчивый алгоритм (например, LU с выбором главного элемента) и возвращает результат. Вы получаете десятилетия чужого опыта в одной строке.

SciPy против NumPy: где граница

Иногда функции дублируются (например, есть numpy.linalg и scipy.linalg). Практическое правило:

  • NumPy — базовая линейная алгебра «на каждый день», входит даже без SciPy.
  • scipy.linalg — расширенный набор: больше разложений, всегда зовёт LAPACK, чуть быстрее на больших задачах.
  • Если функции нет в NumPy (интегралы, оптимизация, статтесты, сплайны) — это однозначно SciPy.

Частые ошибки

  • Изобретать велосипед. Свой метод Ньютона почти всегда хуже scipy.optimize по устойчивости.
  • Импортировать весь SciPy. import scipy не тянет подмодули; нужно from scipy import optimize или from scipy.optimize import brentq.
  • Забывать про начальное приближение. Многим алгоритмам SciPy нужна точка старта или интервал; плохой старт = расхождение.

Итог

  • SciPy добавляет к массивам NumPy готовые научные алгоритмы.
  • Он организован в тематические подмодули: optimize, integrate, linalg, stats и др.
  • Под капотом — проверенная классика на Fortran/C (LAPACK, QUADPACK, MINPACK).
  • Не пишите численные методы сами, если они уже есть в SciPy.
Проверьте себя
1. Какую задачу решает SciPy, которую НЕ покрывает базовый NumPy?
AСложение и умножение массивов
BГотовые научные алгоритмы: интегрирование, оптимизацию, статтесты, разложения
CХранение многомерных данных
DПоэлементный синус массива
2. Что лежит под капотом scipy.linalg и scipy.integrate.quad?
AЧистый Python-код
BПроверенные временем библиотеки на Fortran/C: LAPACK, QUADPACK
CJavaScript-движок
DТолько NumPy без внешних зависимостей
3. Как правильно импортировать подмодуль оптимизации SciPy?
Aimport scipy и сразу scipy.optimize.brentq
Bfrom scipy.optimize import brentq
Cimport optimize
Dfrom numpy import brentq