Метод наименьших квадратов вручную

Урок о том, как провести «наилучшую прямую» через облако экспериментальных точек без всяких библиотек.

Метод наименьших квадратов (МНК) подбирает параметры зависимости так, чтобы сумма квадратов отклонений точек от модели была минимальной.

Калибруя прибор или проверяя закон $y = kx + b$, мы получаем облако точек с разбросом. Провести «на глаз» прямую — ненаучно. МНК даёт объективные формулы для наклона и сдвига, минимизирующие суммарную невязку. Это рабочая лошадь обработки экспериментальных зависимостей.

Постановка задачи

Ищем прямую $y = kx + b$, минимизирующую сумму квадратов отклонений:

$$Q(k, b) = \sum_{i=1}^{n}\bigl(y_i - k x_i - b\bigr)^2 \to \min$$

Приравняв частные производные $\partial Q/\partial k$ и $\partial Q/\partial b$ к нулю, получаем систему, решение которой:

$$k = \frac{n\sum x_i y_i - \sum x_i \sum y_i}{n\sum x_i^2 - \left(\sum x_i\right)^2}, \qquad b = \frac{\sum y_i - k\sum x_i}{n}$$

Эти формулы — точное решение, никакого перебора не требуется. Достаточно посчитать пять сумм: $\sum x$, $\sum y$, $\sum xy$, $\sum x^2$ и $n$.

Зачем это нужно

МНК превращает разбросанные точки в закон с числовыми коэффициентами и позволяет калибровать прибор линейной поправкой, проверять физические зависимости и интерполировать. Наклон $k$ часто имеет прямой физический смысл — например, жёсткость пружины в законе Гука или сопротивление в законе Ома.

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

Реализуем МНК на чистом Python. Возьмём зашумлённые данные вокруг истинной прямой $y = 2x + 1$ и проверим, восстановит ли метод коэффициенты.

import random
random.seed(101)

# Истинная зависимость y = 2x + 1 плюс шум
xs = list(range(1, 11))
ys = [2 * x + 1 + random.gauss(0, 0.5) for x in xs]

n = len(xs)
sum_x = sum(xs)
sum_y = sum(ys)
sum_xy = sum(x * y for x, y in zip(xs, ys))
sum_x2 = sum(x * x for x in xs)

k = (n * sum_xy - sum_x * sum_y) / (n * sum_x2 - sum_x ** 2)
b = (sum_y - k * sum_x) / n
print("Наклон k =", round(k, 3), "(истина 2)")
print("Сдвиг  b =", round(b, 3), "(истина 1)")

# Качество подгонки: коэффициент детерминации R^2
sr_y = sum_y / n
ss_tot = sum((y - sr_y) ** 2 for y in ys)
ss_res = sum((y - (k * x + b)) ** 2 for x, y in zip(xs, ys))
print("R^2 =", round(1 - ss_res / ss_tot, 4))

Вывод:

Наклон k = 1.989 (истина 2)
Сдвиг  b = 1.043 (истина 1)
R^2 = 0.9943

МНК восстановил коэффициенты с высокой точностью (k=1,99 против истинных 2, b=1,04 против 1), а коэффициент детерминации $R^2 = 0{,}99$ подтвердил отличную линейную подгонку. И всё это — пятью суммами на стандартном Python, без единой внешней библиотеки.

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

  • Применять линейный МНК к явно нелинейным данным без предварительного спрямления (логарифмирования и т. п.).
  • Забывать про выбросы: один промах сильно тянет прямую, ведь МНК минимизирует именно квадраты отклонений.
  • Игнорировать $R^2$: высокий наклон ничего не значит, если подгонка плохая.

Итог

  • МНК подбирает прямую, минимизируя сумму квадратов отклонений.
  • Коэффициенты $k$ и $b$ даются явными формулами через пять сумм.
  • Наклон часто несёт прямой физический смысл (жёсткость, сопротивление и т. п.).
  • Качество подгонки оценивают коэффициентом детерминации $R^2$; МНК чувствителен к выбросам.
Проверьте себя
1. Что минимизирует метод наименьших квадратов?
Aсумму модулей отклонений
Bсумму квадратов отклонений точек от модели
Cмаксимальное отклонение
Dчисло точек
2. Сколько сумм по данным достаточно вычислить, чтобы найти k и b линейной регрессии?
Aдве
Bпять (включая n): Σx, Σy, Σxy, Σx², n
Cдесять
Dпо числу точек