Не всегда необходимо запускать алгоритм оптимизации для выполнения линейной регрессии. Вы можете решить конкретное алгебраическое уравнение - нормальное уравнение - чтобы получить результаты напрямую. Хотя для больших наборов данных он даже близко не является оптимальным с точки зрения вычислений, это все же один из вариантов, о котором следует знать.

1. Введение

Линейная регрессия - один из самых важных и популярных методов прогнозирования в анализе данных. Это также один из старейших - знаменитых C.F. Гаусс в начале 19 века использовал его в астрономии для расчета орбит (подробнее).

Его цель состоит в том, чтобы подогнать лучшую линию (или гипер- / плоскость) к набору заданных точек (наблюдений) путем вычисления параметров функции регрессии, которые минимизируют конкретную функцию стоимости (ошибку), например среднеквадратичная ошибка (MSE).

Напоминаем, что ниже представлено уравнение линейной регрессии в развернутом виде.

В векторизованном виде это выглядит так:

где θ - вектор весов параметров.

Обычно поиск лучших параметров модели выполняется с помощью какого-либо алгоритма оптимизации (например, градиентного спуска) для минимизации функции стоимости. Однако можно получить значения (веса) этих параметров, решив также алгебраическое уравнение, называемое нормальным уравнением. Это определено ниже.

2. Ручные расчеты

В этой статье мы выполним линейную регрессию для очень простого случая, чтобы избежать длительных ручных вычислений. Кстати, если вы думаете, что вам нужно освежить свои навыки линейной алгебры, в Интернете есть много хороших ресурсов (например, я рекомендую YouTube series).

В этом примере есть только три точки (наблюдения) только с одной переменной (X₁). На графике они выглядят так, как показано ниже.

В этом случае уравнение линейной регрессии имеет вид:

Функции (X) и метки (y):

Обратите внимание, что мы добавляем член смещения по умолчанию, равный 1 - он будет обновляться во время наших расчетов. Не добавление этого термина приведет к неправильному решению.

Шаг 1: транспонирование матрицы X

Это относительно простая задача - строки становятся новыми столбцами.

Шаг 2. Умножение транспонированной матрицы и матрицы X

Шаг 3. Инверсия результирующей матрицы

Чтобы инвертировать простую матрицу 2x2, мы можем использовать формулу:

Таким образом, получаем:

Примечание: для больших матриц (больше 3x3) их инвертирование становится гораздо более громоздкой задачей, и обычно используется алгоритмический подход - например, исключение Гаусса. Об этом важно помнить!

Шаг 4. Умножение перевернутой матрицы на транспонированный X

Шаг 5. Окончательное умножение для получения вектора наилучших параметров.

Наконец, наши уравнения линейной регрессии принимают форму:

Нанесение этой линии на предыдущий график выглядит так, как показано ниже.

3. Реализация на Python

Те же вычисления можно реализовать в Python с помощью библиотеки Numpy, которая содержит набор функций линейной алгебры в коллекции numpy.linalg.

import numpy as np
X = np.c_[[1,1,1],[1,2,3]] # defining features
y = np.c_[[1,3,2]] # defining labels
theta = np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y) # normal equation
print(theta)

Теперь мы можем определить новые функции, для которых мы хотели бы прогнозировать значения.

X_new = np.c_[[1,1,1,1],[0, 0.5,1.5,4]]  # new features

Реализуя уравнение 2, мы получаем прогнозируемые значения.

y_pred = X_new.dot(theta)  # making predictions
print(y_pred)

4. Комментарии

Как видите, использовать обычное уравнение и реализовать его на Python довольно просто - это всего лишь одна строка кода. Так почему же он не используется повсеместно?

Проблема в его числовой сложности. Решение этого уравнения требует инвертирования матрицы, и это дорогостоящая операция - в зависимости от реализации в большой нотации O это O (n³) или немного меньше. Это означает, что масштабирование ужасно, практически означает, что когда вы удваиваете количество функций, время вычислений увеличивается в 2³ = 8 раз. Также существует некоторая вероятность, что результат шага 2 вообще не обратим, что вызовет большие проблемы. Это причины, по которым на практике такой подход необычен.

С другой стороны, этот подход рассчитывается всего за один шаг, и вам не нужно выбирать параметр скорости обучения. Кроме того, с точки зрения использования памяти этот подход является линейным O (m), что означает, что он эффективно хранит огромные наборы данных, если они помещаются только в память вашего компьютера.