W3docs

Учебник по SciPy

Изучите SciPy: линейная алгебра, интегрирование, оптимизация, интерполяция, статистика и обработка изображений с примерами.

SciPy (Scientific Python) — это библиотека с открытым исходным кодом, которая опирается на NumPy и добавляет обширный набор алгоритмов для математики, науки и инженерии. Если NumPy предоставляет ndarray и базовые операции, то SciPy предлагает специализированные решатели: численное интегрирование, оптимизацию, интерполяцию, обработку сигналов, статистику, пространственные алгоритмы и многое другое.

В этой главе рассматриваются:

  • Установка SciPy и соглашение об импорте
  • Линейная алгебра (scipy.linalg)
  • Численное интегрирование и дифференцирование (scipy.integrate)
  • Оптимизация — поиск минимумов и корней (scipy.optimize)
  • Интерполяция (scipy.interpolate)
  • Статистика (scipy.stats)
  • N-мерная обработка изображений (scipy.ndimage)

Установка SciPy

SciPy входит в состав дистрибутива Anaconda. Чтобы установить его с помощью pip:

pip install scipy

SciPy зависит от NumPy, который pip устанавливает автоматически, если он ещё не присутствует.

Соглашение об импорте

SciPy организован в виде подпакетов. Импортируйте только те подпакеты, которые вам нужны, а не всю библиотеку целиком:

import numpy as np
from scipy import linalg, integrate, optimize, interpolate, stats, ndimage

Вы также можете проверить установленную версию:

import scipy
print(scipy.__version__)  # e.g. 1.13.0

Линейная алгебра

scipy.linalg расширяет подпрограммы линейной алгебры NumPy дополнительными разложениями и решателями. Все функции работают с обычными массивами NumPy.

Определитель и обратная матрица

import numpy as np
from scipy import linalg

a = np.array([[1, 2],
              [3, 4]])

det = linalg.det(a)
print(det)          # -2.0

inv = linalg.inv(a)
print(inv)
# [[-2.   1. ]
#  [ 1.5 -0.5]]

det([[1,2],[3,4]]) = 1×4 − 2×3 = −2. Обратная матрица удовлетворяет условию a @ inv == I.

Собственные значения и собственные векторы

Собственные значения описывают, как матрица растягивает пространство; собственные векторы задают направления, которые не подвергаются вращению.

import numpy as np
from scipy import linalg

a = np.array([[1, 2],
              [3, 4]])

eigenvalues, eigenvectors = linalg.eig(a)
print(eigenvalues)
# [-0.37228132+0.j  5.37228132+0.j]
print(eigenvectors)
# [[-0.82456484 -0.41597356]
#  [ 0.56576746 -0.90937671]]

Каждый столбец eigenvectors соответствует соответствующему собственному значению. Собственные значения возвращаются как комплексные числа, даже когда мнимая часть равна нулю.

Сингулярное разложение (SVD)

SVD разложение факторизует матрицу A на три матрицы U, s, Vt так, что A = U @ diag(s) @ Vt. Это основа метода главных компонент (PCA) и многих техник уменьшения размерности.

import numpy as np
from scipy import linalg

a = np.array([[1, 2],
              [3, 4]])

u, s, vt = linalg.svd(a)
print(u)
# [[-0.40455358 -0.9145143 ]
#  [-0.9145143   0.40455358]]
print(s)    # [5.4649857  0.36596619]
print(vt)
# [[-0.57604844 -0.81741556]
#  [ 0.81741556 -0.57604844]]

Решение системы линейных уравнений

linalg.solve — правильный способ решения Ax = b. Он быстрее и численно стабильнее, чем вычисление обратной матрицы с последующим умножением.

import numpy as np
from scipy import linalg

# Solve: 1x + 2y = 5
#        3x + 4y = 11
A = np.array([[1, 2],
              [3, 4]])
b = np.array([5, 11])

x = linalg.solve(A, b)
print(x)   # [1. 2.]

# Verify: A @ x should equal b
print(np.allclose(A @ x, b))  # True

Численное интегрирование

scipy.integrate предоставляет подпрограммы для вычисления определённых интегралов, когда аналитическое решение нецелесообразно.

Интегрирование функции одной переменной с помощью quad

integrate.quad использует адаптивную квадратуру для интегрирования функции на интервале. Возвращает результат и оценку абсолютной погрешности.

import numpy as np
from scipy import integrate

# Integrate f(x) = x^2 + 2x + 1 from 0 to 1
# Analytical result: [x^3/3 + x^2 + x] from 0 to 1 = 1/3 + 1 + 1 = 7/3
def f(x):
    return x**2 + 2*x + 1

result, error = integrate.quad(f, 0, 1)
print(result)   # 2.3333333333333335
print(error)    # ~2.6e-14  (absolute error estimate)

Численное дифференцирование

Функция approx_fprime из SciPy вычисляет градиент методом конечных разностей. Для скалярных функций проще использовать центральные разности derivative из scipy.misc:

import numpy as np
from scipy.optimize import approx_fprime

# Derivative of sin(x) at x = 0 should be cos(0) = 1
result = approx_fprime([0.0], lambda x: np.sin(x[0]), 1e-8)
print(result[0])   # ~1.0

Оптимизация

scipy.optimize находит минимумы, максимумы (путём минимизации отрицательного значения) и корни функций.

Минимизация функции многих переменных

optimize.minimize поддерживает множество методов (Nelder-Mead, BFGS, L-BFGS-B, …). Метод по умолчанию выбирается автоматически.

from scipy import optimize

# Minimize f(x) = x^2 + 2x + 1 = (x + 1)^2  — minimum at x = -1
def f(x):
    return x**2 + 2*x + 1

result = optimize.minimize(f, x0=0)   # x0 is the starting guess
print(result.success)   # True
print(result.x)         # [-1.00000001]  (near -1)
print(result.fun)       # ~0.0           (minimum value)

Минимизация скалярной функции на ограниченном интервале

optimize.minimize_scalar проще для задач с одной переменной. Всегда указывайте bounds с method='bounded', когда функция не имеет глобального минимума (то есть не ограничена):

from scipy import optimize

# Minimize h(x) = x^2 - 4x + 3 over [0, 4]  — minimum at x = 2, h(2) = -1
def h(x):
    return x**2 - 4*x + 3

result = optimize.minimize_scalar(h, bounds=(0, 4), method='bounded')
print(result.x)     # ~2.0
print(result.fun)   # -1.0

Поиск корней

optimize.root_scalar находит точки, где функция обращается в ноль:

from scipy.optimize import root_scalar

# Solve x^2 - 4 = 0 in the interval [0, 3]  — root at x = 2
res = root_scalar(lambda x: x**2 - 4, bracket=[0, 3])
print(res.root)     # 2.0

Интерполяция

scipy.interpolate строит гладкую кривую через точки данных, позволяя оценивать значения между ними.

Одномерная интерполяция

interp1d создаёт вызываемую функцию интерполяции из дискретных пар (x, y). Параметр kind задаёт метод: 'linear' (по умолчанию), 'quadratic' или 'cubic'.

import numpy as np
from scipy.interpolate import interp1d

# Sample points from y = x^2
x = np.array([0, 1, 2, 3, 4])
y = np.array([0, 1, 4, 9, 16])

f_linear = interp1d(x, y)           # piecewise linear
f_cubic  = interp1d(x, y, kind='cubic')  # cubic spline

# Estimate y at x = 2.5  (exact value: 2.5^2 = 6.25)
print(float(f_linear(2.5)))   # 6.5   (linear — slightly off)
print(float(f_cubic(2.5)))    # 6.25  (cubic — matches exactly for polynomials)

Кубическая интерполяция воспроизводит точный результат, поскольку данные получены из квадратного полинома, а кубический сплайн достаточно гибок, чтобы подогнать его идеально.

Статистика

scipy.stats содержит более 80 непрерывных и дискретных вероятностных распределений, а также набор статистических тестов.

Описательная статистика и нормальное распределение

import numpy as np
from scipy.stats import norm

# Standard normal distribution (mean=0, std=1)
print(norm.pdf(0))     # 0.3989422804014327  — probability density at x = 0
print(norm.cdf(1.96))  # 0.9750021048517795  — P(X <= 1.96)
print(norm.ppf(0.975)) # 1.9599639845400536  — inverse CDF (quantile function)

# Fit a normal distribution to data
data = np.array([2.1, 3.3, 2.8, 3.1, 2.5, 3.0, 2.7])
mu, sigma = norm.fit(data)
print(f'Fitted mean: {mu:.4f}, std: {sigma:.4f}')

Проверка гипотез

scipy.stats включает t-тесты, тесты хи-квадрат, ANOVA, тесты Колмогорова-Смирнова и многое другое.

import numpy as np
from scipy.stats import ttest_1samp, ttest_ind

# One-sample t-test: is the sample mean significantly different from 5?
sample = np.array([4.8, 5.1, 4.9, 5.3, 5.2, 4.7, 5.0])
t_stat, p_value = ttest_1samp(sample, popmean=5.0)
print(f't = {t_stat:.4f}, p = {p_value:.4f}')
# p > 0.05 → no significant difference from 5

# Two-sample t-test: are these two groups different?
group_a = np.array([5.1, 5.3, 4.9, 5.2, 5.0])
group_b = np.array([6.1, 6.3, 5.8, 6.0, 5.9])
t_stat2, p_value2 = ttest_ind(group_a, group_b)
print(f't = {t_stat2:.4f}, p = {p_value2:.6f}')
# Very small p → groups are significantly different

Случайные величины и выборка

Каждое распределение в scipy.stats предоставляет единый интерфейс: pdf, cdf, ppf, rvs (случайные величины) и fit.

from scipy.stats import norm, poisson

# Draw 5 samples from a normal distribution with mean=10, std=2
samples = norm.rvs(loc=10, scale=2, size=5, random_state=42)
print(samples.round(2))   # [10.99  9.72 11.3  13.05  9.53]

# Poisson distribution: P(X = k) for mean lambda=3
for k in range(6):
    print(f'P(X={k}) = {poisson.pmf(k, mu=3):.4f}')

N-мерная обработка изображений

scipy.ndimage работает с массивами любой размерности (изображения, объёмы, временны́е кубы). Ниже приведён самодостаточный пример с синтетическим двумерным массивом, не требующий внешнего файла изображения.

Размытие по Гауссу и маркировка связных областей

import numpy as np
from scipy import ndimage

# Create a synthetic 5x5 "image" with a bright spot in the centre
image = np.array([
    [0, 0, 0, 0, 0],
    [0, 1, 1, 1, 0],
    [0, 1, 5, 1, 0],
    [0, 1, 1, 1, 0],
    [0, 0, 0, 0, 0],
], dtype=float)

# Smooth the image with a Gaussian filter (sigma controls the blur radius)
blurred = ndimage.gaussian_filter(image, sigma=1)
print('Center value after blur:', round(blurred[2, 2], 4))
# 1.4166  — the bright peak is spread across neighbouring pixels

# Label connected non-zero regions (like counting distinct objects)
binary = image > 0
labeled, num_regions = ndimage.label(binary)
print('Number of connected regions:', num_regions)  # 1
print(labeled)
# [[0 0 0 0 0]
#  [0 1 1 1 0]
#  [0 1 1 1 0]
#  [0 1 1 1 0]
#  [0 0 0 0 0]]

Распространённые операции ndimage

ФункцияЧто делает
gaussian_filter(a, sigma)Сглаживание с гауссовым ядром
sobel(a)Обнаружение границ (градиент Собеля)
label(a)Маркировка связных областей в бинарном массиве
binary_dilation(a)Расширение областей переднего плана
zoom(a, factor)Изменение размера массива
rotate(a, angle)Поворот массива (в градусах)

Когда использовать SciPy вместо других библиотек

ЗадачаПредпочтительный инструмент
Создание массивов и базовая математикаNumPy
DataFrame, временны́е ряды, ввод/выводPandas
Научные алгоритмы (интегрирование, оптимизация)SciPy
Машинное обучениеscikit-learn (строится на SciPy)
ВизуализацияMatplotlib

SciPy не является заменой NumPy — он зависит от NumPy и расширяет его. На практике вы будете импортировать оба.

Краткий справочник

ПодпакетКлючевые функции
scipy.linalgdet, inv, eig, svd, solve
scipy.integratequad, dblquad, solve_ivp
scipy.optimizeminimize, minimize_scalar, root_scalar
scipy.interpolateinterp1d, CubicSpline, griddata
scipy.statsnorm, ttest_1samp, ttest_ind, chi2_contingency
scipy.ndimagegaussian_filter, label, sobel, zoom
scipy.signalbutter, lfilter, find_peaks
scipy.spatialdistance, KDTree, ConvexHull
Was this page helpful?