Градиентный спуск на пальцах

Почему производная – это направление движения.

Градиентный спуск на пальцах

Когда мы говорим, что модель обучается, на самом деле мы имеем в виду очень простую цель: шаг за шагом уменьшать ошибку. Неважно, идёт ли речь о линейной регрессии, логистической модели или глубокой нейросети – почти всегда за обучением стоит один и тот же базовый механизм.

Этот механизм называется градиентным спуском.

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

Именно так и работает градиентный спуск: он подсказывает, куда сделать следующий шаг, чтобы ошибка стала меньше. Причём шаг за шагом, почти на ощупь – так, что объяснить этот процесс можно буквально "на пальцах".

Ошибка как ландшафт

Представим себе очень простую ситуацию. У нас есть модель с одним параметром ww. Мы меняем ww и каждый раз считаем ошибку L(w)L(w). Например, это может быть MSE.

Если нарисовать график зависимости ошибки от ww, то мы увидим кривую. Где-то ошибка большая, где-то меньше, а в одной точке – минимальная.

В этот момент полезно сменить абстракцию. Перестать думать об ошибке как о формуле и начать думать о ней как о ландшафте.

Значение параметра ww – это положение по горизонтали.

Значение ошибки L(w)L(w) – это высота.

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

12.1 График ошибки как холм

Почему "спуск"

Представим, что мы стоим на склоне холма в тумане. Очевидно, что нужно спускаться вниз. Но где именно находится самая низкая точка, мы не знаем: карты нет, горизонт не виден. Всё, что нам доступно, – это небольшой участок поверхности прямо под ногами.

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

Вот здесь и появляется производная.

Производная как наклон

Производная функции L(w)L(w) по ww – это, по сути, наклон кривой в текущей точке.

Формально:

f(x)=dLdwf′(x) = \frac{dL}{dw}

Но без формального определения это означает следующее:

  • если производная положительная, то при увеличении ww ошибка растет

  • если производная отрицательная, то при увеличении ww ошибка уменьшается

  • если производная равна нулю, то мы либо в минимуме, либо в максимуме, либо на плато (в многомерном случае – также в седловой точке)

Геометрически производная – это тангенс угла наклона касательной к графику.

12.2 График функции и касательная, показывающая наклон

Почему производная – это направление движения

Допустим, мы стоим в точке w0w_0.

Если dLdw>0\frac{dL}{dw} > 0, значит график "идет вправо - вверх". Чтобы спускаться, нам нужно двигаться влево, то есть уменьшать ww.

Если dLdw<0\frac{dL}{dw} < 0, график "идет вправо - вниз ". Значит, выгодно двигаться вправо, увеличивая ww.

Обратите внимание на важный момент: мы не идем по производной, мы идем против нее.

Именно поэтому шаг градиентного спуска выглядит так:

wnew=woldηdLdww_{new} = w_{old} - \eta \cdot \frac{dL}{dw}

Здесь η\eta (эта буква называется "эта") – это скорость обучения, или learning rate.

Она отвечает за то, насколько длинный шаг мы делаем.

Интуиция шага

Можно читать эту формулу буквально словами: "Возьми текущее значение параметра и сдвинь его в сторону, противоположную градиенту функции в этой точке, на величину, пропорциональную этому наклону".

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

Это очень похоже на то, как человек осторожно спускается с горы. На крутом участке он делает заметный шаг вниз. На почти ровном месте – еле переставляет ноги.

Что будет, если шаг слишком большой

Интуиция подсказывает, что можно "ускориться" и взять очень большое значение η\eta. Но тут нас поджидает классическая ловушка.

Если шаг слишком большой, мы не спускаемся, а начинаем перепрыгивать минимум. Сначала – слева от него, потом – справа, затем – снова слева. Ошибка не уменьшается, а скачет.

12.3 График с перескакиванием минимума

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

Отсюда и главный практический вывод: learning rate – один из самых чувствительных параметров в обучении моделей.

Много параметров – тот же принцип

До этого мы говорили про один параметр ww. В реальных же моделях параметров может быть десятки, тысячи или даже миллионы.

Но идея не меняется.

Ошибка становится функцией многих переменных:

L(w1,w2,,wn)L(w_1, w_2, \dots, w_n)

Производная превращается в градиент – вектор из частных производных:

L=(Lw1,Lw2,,Lwn)\nabla L = \left( \frac{\partial L}{\partial w_1}, \frac{\partial L}{\partial w_2}, \dots, \frac{\partial L}{\partial w_n} \right)

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

И снова никакой магии. Мы просто идем вниз по самому крутому склону.

12.4 3D-поверхность ошибки и вектор градиента

Почему без производных никуда

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

Производная отвечает на простой вопрос: "Если я слегка изменю параметры, в какую сторону и насколько изменится ошибка?"

Градиентный спуск – это не более чем повторение одного и того же цикла:

  1. посчитай текущую ошибку

  2. посчитай производные

  3. сделай шаг в сторону уменьшения ошибки

Этот цикл и есть "обучение".

Реализация на PHP – с нуля

Начнём с минимального примера: один признак, один вес. Оценка стоимости квартиры по её площади.

Этот код обучает простейшую линейную регрессию методом градиентного спуска.

Модель имеет вид:

y=wx+by = w \cdot x + b

где

  • xx – один признак (площадь),

  • yy – целевая величина (цена),

  • ww – вес (насколько цена растёт при увеличении площади),

  • bb – смещение (базовая цена).

Код:

  1. берёт набор пар (x,y)(x, y),

  2. начинает с нулевых параметров ww и bb,

  3. много раз (эпох – epochs) считает ошибку,

  4. вычисляет, как нужно изменить ww и bb, чтобы ошибка уменьшалась,

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

В итоге мы получаем линию, максимально близкую к точкам. Важно, что здесь нет никакой "магии ML". Это обычный цикл, обычная математика и аккуратная работа с числами.

Векторная версия

Когда признаков больше, удобнее мыслить векторами.

Здесь bias уже включён как дополнительный признак со значением 1. Это эквивалентно предыдущей формуле, просто записано в расширенном векторном виде.

Это стандартный трюк, который часто используется в ML, потому что:

  • одинаково работает для линейных моделей, логистической регрессии, SVM, нейросетей,

  • упрощает backprop,

  • позволяет хранить всё в матрицах,

  • убирает условные ветки из кода и формул.

На практике почти все линейные модели в библиотеках делают именно так.

Подведём итог

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

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

Именно это и делает градиентный спуск.

Чтобы самостоятельно протестировать этот код, установите примеры из официального репозитория GitHub или воспользуйтесь онлайн-демонстрацией для его запуска.

Last updated