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

Рассмотрим следующую задачу: вы получили изображение и хотите, чтобы алгоритм возвращал (предсказывал) правильное количество людей на изображении.

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

Предположим, вы построили какую-то нейронную сеть для выполнения этой задачи. Для данного обсуждения не так уж важно, сколько слоев в сети или характер математических манипуляций, выполняемых на каждом слое. Однако важно то, что в конце концов есть один выходной нейрон, который предсказывает (неотрицательное, желательно целое) значение.

Математическая работа сети может быть выражена в виде функции:

f(x, w) = y

где x — входное изображение (мы можем представить его как вектор, содержащий все значения пикселей), y — предсказание сети, а w — вектор, содержащий все внутренние параметры функции (например, в f(x,w) = a + bx + exp(c*x) = y значения a, b и c являются параметрами функции).

Как мы видели в сообщении о персептронах, во время обучения нам нужен какой-то механизм, который:

  1. Оценивает прогноз сети на заданном входе,
  2. Сравнивает его с желаемым ответом (основной истиной),
  3. Производит обратную связь, которая соответствует величине ошибки,
  4. И, наконец, изменяет параметры сети таким образом, чтобы улучшить ее предсказание (уменьшить величину ошибки).

И благодаря умным умам — такой механизм у нас есть. Чтобы понять это, нам нужно охватить две темы:

  1. Функция потерь
  2. Обратное распространение

Функция потери

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

Мы хотели бы использовать функцию потерь, которая возвращает небольшое значение, когда прогноз сети близок к истине, и большое, когда оно далеко от истины.

Цель функции потерь — сообщить нашему обучающему механизму, насколько велика ошибка. Если на изображении 6 человек, а наша сеть предсказала только 1, это большая ошибка, чем если бы сеть предсказала 5. Таким образом, было бы логичным выбором использовать функцию потерь.

L(y, y’) = абс(y-y’),

где y и y’ — сетевое предсказание и наземная правда соответственно.

Более распространенный выбор:

L(y, y’) = (y-y’)²

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

  1. Его акцент на больших ошибках больше, чем просто линейный,
  2. Она гладкая везде, даже при y=y’. Вскоре мы поймем, почему это важно.

Значение, которое нас на самом деле интересует, — это не сама потеря. Мы хотим, чтобы наш обучающий механизм вычислял производную потерь. «Производная по отношению к чему?» — спросите вы. А вот и суть дела: вопреки тому, что могут подумать многие новички в области машинного обучения, мы не получаем потери по отношению к входному значению x. Для нас вход — это заданное независимое значение. Вместо этого мы получаем потери относительно параметров сети w.

Почему?

Поскольку производная убытков или градиент по отношению к параметрам сети, dL/dw, говорит нам, насколько изменится убыток (при заданном входе x), если мы изменим параметры сети незначительно. Если мы представим функцию потерь как ландшафт с холмами и долинами в пространстве параметров (это легко сделать всего с двумя параметрами, но помните, что на практике обычно есть миллионы параметров), то градиент потерь представляет собой вектор, который указывает в гору. Если мы хотим уменьшить ошибку, мы должны двигаться (т.е. немного изменять параметры) в направлении отрицательного градиента — вниз.

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

Как вывести неизвестную функцию?

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

Обратное распространение

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

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

Получив градиент потерь, мы обновляем параметры сети:

w_new = w — lr * град (L)

где w_new — обновленное значение вектора параметров, grad(L) — градиент потерь по отношению к параметрам, а lrскорость обучения: коэффициент, который контролирует размер шага обновления. Это гиперпараметр, устанавливаемый пользователем, который обычно уменьшается на этапах обучения в соответствии с заданным расписанием.

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

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

Когда прекращать тренировки?

Мы используем два индикатора, чтобы понять, эффективно ли обучается сеть:

  1. Отслеживание потерь. Когда сеть обучается эффективно, мы ожидаем, что потери со временем уменьшатся. Если потери не уменьшаются, это может означать, что сеть достигла точки глубокого минимума или что скорость обучения слишком высока, и сеть постоянно пропускает минимумы в ландшафте потерь.
  2. Выполнение проверочного теста: через фиксированные промежутки времени запускайте сеть в режиме вывода (используя сеть для прогнозирования без обновления параметров) на проверочном наборе. — набор изображений, не входящий в обучающую выборку. Мы ожидаем, что потери на этом наборе также уменьшатся. Если потери уменьшаются на обучающем наборе но не на проверочном наборе, это означает, что сеть начинает переоснащаться — она изучает атрибуты обучающих примеров, но не не учится обобщать, и его производительность на невидимых данных в конечном итоге ухудшится. Это происходит, когда обучающая выборка слишком мала или в сети слишком много параметров.

Еще несколько слов о тренировках

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

  1. Обучение сети относится к разделу математики и инженерии, который называется оптимизация. Вероятно, вы сталкивались с задачами оптимизации на уроках математики в школе, где от вас требовалось найти форму поля с наибольшей площадью и т. д. Аналитически эти задачи требуют обнуления производной некоторой функции и решения ее для требуемых свойств (например, длины поля , ширина и др.). В реальных задачах мы не всегда можем вычислить производную, но можем ее аппроксимировать. Это то, что мы делаем при обучении сети: мы определяем функцию потерь, которая для идеальной модели имела бы свои параметры в точке минимума. Цель процесса обучения — оказаться в точке пространства параметров, которая находится в достаточно глубоком локальном минимуме функции потерь.
  2. Обычно нейронные сети предсказывают более одного значения: сети обнаружения предсказывают тысячи значений для каждого изображения, соответствующих координатам ограничивающей рамки объекта, уровням достоверности, классам объектов. Сети улучшения изображения буквально предсказывают целые изображения и т. д. Как правило, потеря будет иметь несколько зависимостей от различных выходных функций: например. сеть обнаружения объектов будет иметь потери для отсутствующих объектов, а также для объектов, которые не были правильно локализованы, и для объектов, которые не были правильно классифицированы. Выбор хорошей функции потерь — это больше, чем просто математика и инженерия, это искусство. Два инженера машинного обучения, работающие над одной и той же сетевой архитектурой и выполняющие одну и ту же задачу, могут разработать разные функции потерь. С помощью функции потерь вы формируете сеть, чтобы определенным образом изучить особенности. Некоторые функции потерь могут быть недостаточно хорошими в том смысле, что трудно сходиться к их локальным минимумам. Некоторые функции потерь содержат сложные отношения между различными выходными узлами сети или коэффициенты потерь, которые меняются на разных этапах обучения (например, Yolo).
  3. Обычно этапы обучения выполняются для более чем одной точки данных одновременно. Средние потери рассчитываются по партии входных данных, что обеспечивает более сглаженную картину потерь (и лучшее использование методов параллельных вычислений для повышения скорости).
  4. Как видно на изображении ландшафта потерь выше, найти самый глубокий минимум не так просто, как позволить шарику скатиться в яму. Типичный ландшафт потерь состоит из множества трещин, каньонов и перевалов, которые уводят нас от корня к самой глубокой точке. Кроме того, мы не рассчитываем найти глобальный минимум даже при успешном обучении. Нас устраивает один из многих локальных минимумов, которые дают хорошие результаты на данных.
  5. Существует много эвристик о том, как изменить скорость обучения во время обучения. Слишком большой шаг будет препятствовать сходимости, в то время как слишком маленький шаг сделает обучение очень долгим и может застрять в менее чем оптимальных минимумах. Распространенным методом является экспоненциальное затухание (умножение lr на фиксированный коэффициент ‹ 1 с фиксированными интервалами обучения). Другой метод изменяет l косинусным образом либо только в течение полупериода во время обучения, либо периодически. См. несколько примеров здесь. Помимо скорости обучения, есть и другие приемы управления динамикой сходимости, такие как импульс (используя средневзвешенное значение текущего и предыдущего градиентов).
  6. Чтобы помочь сети обобщить (а также увеличить эффективный размер обучающей выборки), мы обычно добавляем случайные дополнения к обучающим изображениям, например. — изменение яркости, отражение изображения по горизонтали, добавление шума — до тех пор, пока полученное изображение является допустимым входом для задачи. Этот метод очень полезен, когда ваших данных для обучения недостаточно или изображения сильно коррелированы (как в случае, когда вы используете кадры, взятые из видеоклипа).