Зачем нужен 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.