Одной из задач машинного обучения является задача регрессии. В задачи регрессии мы хотим предсказать переменную \(Y\), которая может принимать вещественные значения \(Y \in \mathbb{R}\).
Примеры задачи регрессии:
Хорошо, с регрессией разобрались, а почему линейная? Все просто! Потому что над всеми признаками применяется обычное линейное преобразование (сумма).
Так выглядит наша модель
\[ y_i = w_0 \cdot 1 + w_1 \cdot x_i^{(1)} + w_2 \cdot x_i^{(2)} + \ldots + w_k \cdot x_i^{(k)} + \epsilon_i= w^T \cdot X + \epsilon_i \] Мы пытаемся ее оценить. После того как мы получили оцененные веса (\(\hat{w_i}\)), мы можем написать нашу оцененную модель:
\[ \hat{y_i} = \hat{w_0} \cdot 1 + \hat{w_1} \cdot x_i^{(1)} + \hat{w_2} \cdot x_i^{(2)} + \ldots + \hat{w_k} \cdot x_i^{(k)} = \hat{w}^T \cdot X \]
Итак, модель построили, осталось обучить. Как было сказано в тетрадке до этого (смотреть тут) для этого надо функционал выбрать, а затем его оптимизировать по весам \(w\) так, чтобы он оказался как можно меньше. Ну окей, давайте подберем:
Делай раз:
Логично, что наша ошибка это разность между реальным значением \(y\) и предсказанным нами по всем наблюдениям, то есть для конкретного наблюдения \(i\) выглядит это так:
\[ y_i - (\hat{w_0} \cdot 1 + \hat{w_1} \cdot x_i^{(1)} + \hat{w_2} \cdot x_i^{(2)} + \ldots + \hat{w_k} \cdot x_i^{(k)}) = y_i - \hat{y_i} \] А как же нам тогда ошибку по всем наблюдениям посчитать, чтоб получилось одно число?
Делай два:
Идея №1:
Так давайте просто ошибки по всем наблюдениям сложим и дело с концом. А чтобы мы прославились совсем крутыми математиками, давайте покажем что мы не только складывать умеем, но еще на кол-во делить, чтоб среднее найти:
\[ error = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y_i}) \] Но не все так просто….
Такая функция потерь не очень хороша. Представьте, что на 25 наблюдениях у вас ошибка 10, а на остальных 25 ошибка равна -10. В итоге функция потерь будет равна 0, что означает, что модель идеальна и не допускает ошибок. Положительные и отрицательные ошибки “схлопнули” друг друга.
Идея №2:
Хмм… Тогда давайте подумаем как такие штуки нам мониторить. Придумали! Будем брать модуль или квадрат ошибки. Ну и так как это наши детища, дадим им названия: в первом случае MAE – mean absolute error, а во втором случае MSE – mean squared error.
\[MAE = \frac{1}{n} \sum_{i=1}^{n} |y_i - \hat{y_i}|\] \[MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i -\hat{y_i})^2\]
Функционал выбрали, осталось его оптимизировать. Будем это делать с помощью метода градиентного спуска! Для этого вспомним математический анализ, но обещаю, что его будет совсем немного.
Итак, если у нас есть функция, которая зависит от нескольких параметров, то по каждому параметру мы можем взять производную. Вектор из таких производных называется градиентом. У градиента есть очень важное свойство: он указывает в направлении наискорейшего роста функции!
\[ \nabla f(x_1, \ldots ,x_k) = \Bigl(\frac{\partial{f(x)}}{\partial{x_j}}\Bigr)_{j=1}^k \] Если мы выбираем в качестве функционала \(MSE\), то наш градиент будет выглядеть так:
\[ \nabla MSE(w) = \Bigl( \frac{\partial{MSE(w)}}{\partial{w_0}}, \frac{\partial{MSE(w)}}{\partial{w_1}}, \ldots , \frac{\partial{MSE(w)}}{\partial{w_k}} \Bigr ) \]
Так как мы минимизируем функционал, то нам нужно двигаться не в направлении роста функции, а, наоборот, в направлении убывания. Следовательно, мы будем идти не в сторону градиента, а в направлении антиградиента.
Встречайте, градиентный спуск:
\[ w^{t} = w^{t-1} - \eta_t \cdot \nabla MSE(w^{t-1}) \]
\[ ||{w^{t} - w^{t-1}}|| > \varepsilon \]
Простой пример:
\[y = x^2\] \[ \nabla y = (\frac{\partial{y}}{\partial{x}}) = 2 x \]
Шаг градиентного спуска №1:
\[x^{0} = 1\] \[\nabla y(x^{0}) = 2 \cdot 1 = 2\] \[x^{1} = x^{0} - \eta \cdot \nabla y(x^{0}) = 1 - 0.01 \cdot 2 = 0.98\]
Возьмем \(\epsilon = 0.0000001\). Тогда:
\[ ||1 - 0.98|| = 0.02 > 0.0000001 \Rightarrow continue \] Шаг градиентного спуска №2:
\[x^{1} = 0.98\] \[\nabla y(x^{1}) = 2 \cdot 0.98 = 1.96\] \[x^{2} = x^{1} - \eta \cdot \nabla y(x^{1}) = 0.98 - 0.01 \cdot 1.96 = 0.9604\]
\[ ||0.98 - 0.9604|| = 0.0196 > 0.0000001 \Rightarrow continue \] ……
Проделывая так очень много раз в итоге сойдемся к \(x = 0\), что и является минимум для функции \(y=x^2\).
Замечание: Сходимость к оптимуму сильно зависит от выбранной скорости обучения. В данном случае мы видим, что ползти мы будем очень медленно. Однако, если мы бы выбрали, например, 1 в качестве значения \(\eta\), то тогда на первом шаге уже мы бы перепрыгнули 0 и значение \(x\) было бы -1.
Представим, что в нашей моделе есть признак, который принимает несколько факторных значений. Например, в выборке по студентам есть переменная, отвечающая за то, какой университет закончил студент, и она принимает только 3 значения: РАНХиГС, ВШЭ, МГУ. Так как наша модель понимает только числа, надо эти признаки закодировать. Давайте закодируем их в 1, 2, 3.
Но тут есть проблема. В таком случае на данных установится некий порядок. Модель будет понимать, будто бы раз 2 < 3, значит и категория под номером 2 “меньше” категории под номером 3, то есть ВШЭ хуже МГУ…
Чтобы такого избежать, нужно пользоваться One Hot Encoding.
One Hot Encoding - это преобразование значений категориального признака в отдельные бинарные признаки. То есть раз у нас был признак “Университет”, принимающий значения РАНХиГС, ВШЭ, МГУ, то теперь у нас есть 3 признака РАНХиГС, ВШЭ, МГУ, которые для каждого наблюдения принимают значения 1, если студент закончил данный университет и значения 0, если нет.
Заметим очень важный момент. После преобразования One Hot Encoding у нас во всех наблюдениях построчная сумма значений в признаках РАНХиГС, ВШЭ и МГУ равна 1. Значит, наши признаки линейно-зависимы. Это нарушает одну из предпосылок модели линейной регрессии, обсуждение которых выходит за рамки данного курса, поэтому здесь поступают двумя способами: либо одну категорию выкидывают либо убирают константу из модели.