Линейная регрессия часто является первым алгоритмом машинного обучения, который специалисты по данным изучают с помощью Scikit-Learn. В этой статье мы заглянем под капот и увидим, как кодировать алгоритм с нуля, используя градиентный спуск. Так что открывай капот и вперед!

Функция стоимости — среднеквадратическая ошибка

Цель линейной регрессии — найти наиболее подходящую линию, которая объясняет наши обучающие данные, чтобы мы могли делать прогнозы на невидимых данных как можно точнее. Мы хотим минимизировать ошибку, разницу между фактическими и прогнозируемыми значениями. Другими словами, цель состоит в том, чтобы минимизировать функцию стоимости, в частности, мы будем минимизировать среднеквадратичную ошибку (тип функции стоимости):

Где прогнозируемые значения для y задаются следующим образом:

Чтобы минимизировать функцию стоимости, нам нужно найти значения m и b, которые минимизируют общую ошибку.

В науке о данных мы используем бета-версии для представления параметров (m и b). Чтобы сохранить согласованность, мы будем использовать это обозначение вместо этого:

Градиентный спуск

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

Максимум

f’(x) = 0, f’’(x) < 0

Минимум

f’(x) = 0, f’’(x) > 0

Поскольку нам нужно найти значения для нескольких параметров, мы используем частные производные, также известные как градиент функции. Эта формула может показаться знакомой:

Давайте продолжим и вычислим градиенты для наших параметров, используя цепное правило:

Поскольку градиент функции всегда указывает в направлении наибольшего подъема, мы можем двигаться в направлении, противоположном градиенту, чтобы найти самый крутой спуск. Если мы будем делать достаточно маленькие шаги на этом пути, мы окажемся в самой низкой точке кривой или очень близко к ней.

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

Теперь, когда у нас есть формулы, давайте напишем этот алгоритм с нуля!

Кодирование на Python

Программирование модели линейной регрессии в Python можно выполнить несколькими способами. Сегодня я буду использовать основную функцию с тремя вспомогательными функциями. Это позволяет интервьюеру или инструктору легко понять ваш код.

Давайте сначала обсудим вспомогательные функции, чтобы, когда мы соберем все вместе, это имело немного больше смысла.

  1. Инициализировать параметры
  2. Рассчитать градиент
  3. Обновить параметры

Вспомогательная функция 1 — инициализация параметров

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

Вспомогательная функция 2 — вычислить градиент

Здесь мы начнем с установки градиентов на 0, но затем рассчитаем градиенты для beta_0 и других бета (beta_n). Как мы видели выше, beta_0 и другие бета-версии имеют другой градиент, поэтому нам нужно учитывать это в этой функции.

Вспомогательная функция 3 — обновить параметры

Опять же, нам нужно будет обновить beta_0 отдельно от других бета-версий. Чтобы обновить другие бета-версии, нам нужно будет использовать цикл for, чтобы каждая бета-версия обновлялась. Здесь играет роль скорость обучения. Каждый шаг к минимуму будет:

Основная функция — линейная регрессия с нуля

Основная функция вызывает три вспомогательные функции и возвращает оптимальные параметры для минимизации MSE.

Вспомогательная функция 1 — инициализация параметров

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

Вспомогательная функция 2 — вычислить градиент

Здесь мы начнем с установки градиентов на 0, но затем рассчитаем градиенты для beta_0 и других бета (beta_n). Как мы видели выше, beta_0 и другие бета-версии имеют другой градиент, поэтому нам нужно учитывать это в этой функции.

Вспомогательная функция 3 — обновить параметры

Опять же, нам нужно будет обновить beta_0 отдельно от других бета-версий. Чтобы обновить другие бета-версии, нам нужно будет использовать цикл for, чтобы каждая бета-версия обновлялась. Здесь играет роль скорость обучения. Каждый шаг к минимуму будет:

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

Я надеюсь, что это помогло прояснить кодирование алгоритма линейной регрессии с нуля. Хотя он не будет часто использоваться на практике, просьба реализовать его с нуля — это честная игра на собеседовании по науке о данных. Итак, будьте готовы. Если вам нужны другие способы подготовиться к собеседованию по науке о данных — в этой статье есть масса ресурсов, которые помогут вам в вашем путешествии!



Если эта статья оказалась вам полезной, рассмотрите мой путь к тому, чтобы стать специалистом по данным. Мы очень ценим вашу поддержку!