Руководство для начинающих

Алгоритм градиентного спуска 101

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

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

Градиентный спуск (GD) — это алгоритм, который делает именно это, и его важно понимать любому специалисту по данным. Это основное и довольно простое, но крайне важное, и любой, кто хочет войти в эту область, должен быть в состоянии объяснить, что это такое.

В этом посте моя цель — сделать полное и удобное для начинающих руководство, чтобы все поняли, что такое GD, для чего он используется, как он работает, и упомянул различные его варианты.

Как всегда, вы найдете раздел ресурсы в конце сообщения.

Но обо всем по порядку.

Введение

Используя определение из Википедии[1], градиентный спуск — это итеративный алгоритм оптимизации первого порядка для нахождения локального минимума дифференцируемой функции. Хотя это, безусловно, не самый эффективный метод, он широко используется в машинном обучении и глубоком обучении, особенно в нейронных сетях.

В основном он используется для минимизации значения функции путем обновления набора параметров на каждой итерации. С математической точки зрения, он использует производную (градиент) для постепенного уменьшения (спуска) его значения.

Но есть одна загвоздка: не все функции можно оптимизировать. Нам нужна функция — одномерная или многомерная — дифференцируемая, что означает, что производные существуют в каждой точке области определения функции, и выпуклая (U-образная или подобная).

Теперь, после этого простого введения, мы можем немного углубиться в математику, стоящую за ним.

Практический случай

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

Давайте воспользуемся обычным случаем науки о данных, в котором мы хотим разработать регрессионную модель.

Отказ от ответственности: я полностью изобрел это, и нет никаких логических оснований для использования этих функций, все появилось случайно. Цель — показать сам процесс.

Функция стоимости или функция потерь в любой проблеме науки о данных — это функция, которую мы хотим оптимизировать. Поскольку мы используем регрессию, мы собираемся использовать это:

Цель состоит в том, чтобы найти оптимальный минимум f(x,y). Позвольте мне представить, как это выглядит:

Теперь наша цель — получить правильные значения «x» и «y», которые позволят нам найти оптимальные значения этой функции стоимости. Мы уже можем видеть это графически:

  • y=0
  • x равно -1 или 1

На самом GD, потому что мы хотим, чтобы наша машина научилась делать то же самое.

Алгоритм

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

Это простой процесс, в котором мы обновляем x и y на каждой итерации, следуя следующему подходу:

Объясняется словами, на итерации k:

  1. Вычислите градиент, используя значения x и y на этой итерации.
  2. Для каждой из этих переменных — x и y — умножьте ее градиент на лямбду (𝜆), что представляет собой число с плавающей запятой, называемое скоростью обучения.
  3. Удалите из x и y соответственно вычисленные значения на шаге 2.
  4. Заставьте x и y иметь новое значение на следующей итерации.

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

Теперь давайте применим эту теорию на практике.

Первое, что нам нужно сделать, это вычислить градиент f(x,y). Градиент соответствует вектору частных производных:

Теперь, используя Python, все, что я собираюсь сделать, — это создать цикл, который итеративно вычисляет градиент — используя соответствующие x и y — и обновляет эти параметры, как указано выше.

Перед этим я определю еще два значения:

  • Скорость обучения (𝜆) может быть фиксированной или мобильной. Для этого простого урока это будет 0,01.
  • Я также буду использовать значение eps (эпсилон), чтобы определить, когда закончить итерацию. Как только обе частные производные окажутся ниже этого порога, градиентный спуск остановится. Я устанавливаю его на 0,0001.

Теперь давайте напишем код:

import random

# Define constants
eps = 0.0001
lr = 0.01

# Initialize x and y with random values
x = random.uniform(-2, 4)
y = random.uniform(-1, 1)

def f(x,y):
  return (x**2 -1)**2 +y**2

def df_x(x):
  return 4*x*(x**2 - 1)

def df_y(y):
  return 2*y

# Perform gradient descent
while max(df_x(x), df_y(y)) >= eps:
  x = x - lr * df_x(x)
  y = y - lr * df_y(y)

# Print optimal values found
print(f'x = {x}, y = {y}')

Результат случайной итерации:

Мы видим, что эти значения довольно близки к x=1 и y=0, которые действительно были минимумами функции.

Одна вещь, которую я забыл упомянуть, это инициализация x и y. Я решил случайным образом сгенерировать число в случайных диапазонах. В реальных задачах всегда требуется больше времени, чтобы подумать об этом. То же самое со скоростью обучения, условием остановки и многими другими гиперпараметрами.

Но для нашего случая этого было более чем достаточно.

Вариации градиентного спуска

Я уверен, что теперь вы понимаете основной алгоритм. Однако там используется несколько его версий, и я думаю, что некоторые из них заслуживают упоминания.

  • Стохастический градиентный спуск (SGD). SGD — это вариант, который случайным образом выбирает одну точку данных из всего набора данных на каждой итерации. Это уменьшает количество вычислений, но, очевидно, имеет свои недостатки, такие как, например, невозможность сходимости к глобальному минимуму.
  • Пакетный градиентный спуск (BGD). BGD использует весь набор данных в каждой итерации. Это не совсем желательно для больших наборов данных, так как может быть дорогостоящим и медленным в вычислительном отношении, но, с другой стороны, сходимость к глобальному минимуму теоретически гарантирована.
  • Мини-пакетный градиентный спуск (MBGD). Это можно считать средней точкой между SGD и BGD. Он использует не одну точку данных за раз и не весь набор данных, а его подмножество. На каждой итерации мы выбираем случайное количество выборок (предварительно определенных) и выполняем градиентный спуск, используя только их.

Заключение

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

Я надеюсь, что этот пост разъяснил, что это такое, что он делает и как он это делает.

                    Thanks for reading the post! 
            I really hope you enjoyed it and found it insightful.

          Follow me for more content like this one, it helps a lot!
                                  @polmarin

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



Ресурсы

[1] Градиентный спуск — Википедия