Привет! В этом блоге я расскажу о работе линейной регрессии.
Что такое линейная регрессия?
Если бы нам дали приведенные ниже точки данных и попросили спрогнозировать цену дома для любой заданной площади дома, как бы вы это сделали? Один из способов заключается в том, что мы могли бы сформулировать уравнение прогноза с точки зрения функций, которые максимально точно представляют тенденции в данных. Это основная идея линейной регрессии.
Линейная регрессия – это способ прогнозирования данных путем составления линейного уравнения прогнозирования y в терминах функций x, которые лучше всего соответствуют данным.
В модели линейной регрессии сформированное уравнение всегда является линейным, что означает, что график уравнения представляет собой наклонную прямую линию.
Одномерная линейная регрессия
Это тип линейной регрессии, в котором задается только одна характеристика (например, площадь дома) вместе с непрерывным числовым значением для прогнозирования (например, цена дома).
Линейная регрессия состоит из 3 основных компонентов:
- Функция гипотезы
- Функция стоимости
- Градиентный спуск
Функция гипотезы
Функция гипотезы — это уравнение, которое приравнивает предсказания к функциям. Если бы вы придумали такое уравнение, что бы вы сделали?
Скажем, вы определяете цену дома. Расположение дома важно, но количество собак у вашего соседа не очень важно. Хотя это может быть плохой пример, мы видим, что некоторые функции имеют большее значение, чем другие.
Таким образом, чтобы выделить важные функции, мы можем присвоить каждой функции вес функции (θ). Это покажет нам, насколько важна эта функция. Затем мы могли бы умножить функции и их веса. Это гарантирует, что важные функции будут иметь большее значение, а неважные не будут такими заметными. Затем мы могли бы добавить эти взвешенные функции (функции, умноженные на их веса), чтобы получить взвешенную сумму. Для проблемы, когда этого может быть недостаточно, мы можем добавить термин смещения,который представляет собой разницу между истинными значениями и прогнозируемыми значениями в идеальном сценарии.
Функция гипотезы в коде
Функция стоимости
Теперь у нас есть уравнение для получения значения y для любого заданного значения x. Если бы мы попытались улучшить уравнение, чтобы оно лучше соответствовало данным, было бы хорошо знать, насколько хорошо уравнение представляет данные. Это можно сделать с помощью функции затрат или функции потерь. Снова спросите себя, как бы вы это сделали. Мы можем найти, насколько неправильно уравнение в среднем. Для этого мы можем получить абсолютное значение (чтобы отрицательные ошибки не отсекали положительные) разницы между истинными значениями y и предсказанными значениями y, а затем разделить его на количество предсказаний. На самом деле это функция потерь, называемая MAE (Mean Absolute Error).
Обычно модифицированная версия этой функции потерь используется для линейной регрессии. Вместо того, чтобы брать абсолютное значение для удаления отрицательных значений, мы возводим в квадрат различия, чтобы сделать большие ошибки более значительными, а меньшие ошибки менее значительными. Это называется функцией потерь MSE (Mean Squared Error).
Функция потерь в коде
Градиентный спуск
Теперь, когда у нас есть функция потерь, мы можем проверить, насколько хорошо или плохо работает наша модель. Теперь нам нужен метод для улучшения модели. Это называется градиентным спуском. Как это делается?
Давайте возьмем некоторые данные, где для числа «n» выход равен 2n. Если взять числа 1, 2 и 3, требуемый результат будет 2, 4, 6. Чтобы упростить задачу, предположим, что θ0 является постоянным 0. Теперь давайте построим график стоимости для каждого значения θ1 от -100 до 100. График, который мы получаем, показан ниже.
Участок выглядит как долина, образованная двумя склонами, верно? Итак, я буду использовать классический пример «спуска с холма», чтобы объяснить работу градиентного спуска. Представьте, что вам завязали глаза и сказали идти в самую низкую точку долины внизу. Это было бы довольно легко, потому что вы могли бы почувствовать склон и определить путь вниз. Если вы хотите достичь быстро, вы должны делать огромные шаги и бежать вниз по склону. Если вы хотите играть безопасно, вы идете медленно.
Теперь именно это можно применить к градиентному спуску. Высота, на которой вы находитесь, — это потеря. Вы чувствуете, что наклон будет производным термином потерь(точно так же, как вы работаете над уменьшением наклона, алгоритм градиентного спуска пытается уменьшить потери). Длина ваших шагов — это то, что называется скоростью обучения, которая умножается на наклон. Если бы θ было вашим горизонтальным положением, с каждым шагом вы перемещались бы вперед на наклон, умноженный на единицы скорости обучения. С изменением θ меняется и высота (потери).
На графике красная точка — это долина, в которую мы пытаемся попасть. Чтобы добраться туда, нам нужно получить правильное горизонтальное положение θ.
Градиентный спуск — это алгоритм, который обновляет веса модели, чтобы найти наименьший наклон/градиент (минимальное значение/минимумы)
Для наших двух весов θ0 и θ1 это алгоритм градиентного спуска:
Это можно упростить, как описано в этом блоге. Результирующая формула:
Обратите внимание, что производная изменяется от функции потерь к функции потерь, поэтому, если бы вы использовали другую функцию потерь, вы предприняли бы те же шаги, но член производной изменился бы.
Градиентный спуск в коде.
Фу! Теперь у нас есть все компоненты линейной регрессии. Давайте построим модель линейной регрессии с нуля прямо сейчас!
Линейная регрессия в коде
Приведенная выше реализация градиентного спуска обновляет веса только один раз, но алгоритм говорит нам повторять это, пока мы не сойдемся с минимумами. Это то, что делает модель во время обучения на данных — она запускает градиентный спуск снова и снова определенное количество раз. Обучение модели также называется ее подгонкой к данным.
Давайте теперь создадим класс Linear Regressor со всеми его методами (predict, calculate_loss, fit).
Я установил значение скорости обучения по умолчанию равным 0,001, поскольку обычно это одна из идеальных скоростей обучения. Его можно изменить в зависимости от производительности данных.
Прохладный! Теперь давайте попробуем запустить его на некоторых данных.
#Imports import numpy as np import pandas as pd from sklearn.model_selection import train_test_split # Creating some data np.random.seed(42) # Create ideal data area = np.random.random(size=(1000, )) * 2000 price = area * 100 + 500 # Create a pandas dataframe for better viewing data = pd.DataFrame({"Area": area, "Price": price}) # Create noisy data from ideal data x = np.random.normal(data["Area"].mean(),np.std(data["Area"]),(1000, )) y = data["Price"] # split the data into 80% train and 20% test sets x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
Теперь, используя эти данные, давайте подгоним модель и сделаем некоторые прогнозы.
model = LinearRegressor() # Fit the model model.fit(x=x_train, y=y_train, epochs=10) y_preds = model.predict(x_test)
Вывод будет примерно таким:
Теперь давайте оценим нашу модель на данных, которые она никогда раньше не видела, чтобы увидеть, насколько хорошо она научилась.
model.compute_loss(y_preds, y_test)
По сравнению с потерей поезда 7,73, я получил тестовую потерю 9,53. В идеальной ситуации обе потери будут одинаковыми и будут равны 0, но мы видим, что наша модель немного переоснащается (слишком хорошо изучает данные поезда и не так хорошо работает на тестовых данных), но такая большая часть переобучения приемлема.
Ууууу! Теперь у нас есть полностью работающая модель одномерной линейной регрессии.
До встречи!