в соавторстве с Apurva Pathak

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

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

  • Что такое размер партии?
  • Почему имеет значение размер партии?
  • Как малые и большие партии работают эмпирически?
  • Почему большие партии имеют тенденцию работать хуже, и как мы можем сократить разрыв в производительности?

Что такое размер партии?

Нейронные сети обучены минимизировать функцию потерь следующего вида:

куда

  • тета представляет параметры модели
  • m - количество примеров обучающих данных
  • каждое значение i представляет собой один пример обучающих данных
  • J_i представляет функцию потерь, примененную к одному примеру обучения

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

B_k - это пакет, выбранный из набора обучающих данных, и его размер может варьироваться от 1 до m (общее количество точек обучающих данных) [1]. Обычно это называется мини-пакетным обучением с размером пакета | B_k |. Мы можем думать об этих градиентах на уровне партии как о приближении «истинного» градиента, градиента общей функции потерь по отношению к тета. Мы используем мини-пакеты, потому что они имеют тенденцию к более быстрому схождению, поскольку нет необходимости полностью проходить через обучающие данные для обновления весов.

Почему имеет значение размер партии?

Кескар и др. Отмечают, что стохастический градиентный спуск является последовательным и использует небольшие пакеты, поэтому его нелегко распараллелить [1]. Использование пакетов большего размера позволит нам в большей степени распараллеливать вычисления, поскольку мы могли бы разделить обучающие примеры между разными рабочими узлами. Это, в свою очередь, может значительно ускорить обучение модели.

Тем не менее, большие размеры пакетов, хотя и могут достигать такой же ошибки обучения, как и меньшие размеры пакетов, имеют тенденцию хуже обобщаться для тестовых данных [1]. Разрыв между ошибкой поезда и тестом называется «разрывом обобщения».

Таким образом, «святой Грааль» заключается в достижении той же ошибки тестирования, что и при использовании небольших партий при использовании больших партий. Это позволило бы значительно ускорить обучение без ущерба для точности модели.

Как ставятся эксперименты?

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

  • Набор данных: мы используем набор данных Cats and Dogs, который состоит из 23 262 изображений кошек и собак, разделенных примерно 50/50 между двумя классами. Поскольку изображения имеют разный размер, мы изменяем их все до одного размера. Мы используем 20% набора данных в качестве данных проверки (набор разработчика), а остальное - как данные обучения.
  • Метрика оценки: мы используем двоичную кросс-энтропийную потерю данных проверки в качестве основного показателя для измерения производительности модели.

  • Базовая модель: мы также определяем базовую модель, вдохновленную VGG16, где мы многократно применяем операции (свертка - ›max-pool), используя ReLU в качестве функции активации для свертки. Затем мы сглаживаем выходной объем и подаем его на два полностью связанных слоя и, наконец, на слой с одним нейроном и сигмовидной активацией, в результате чего получаем выходной сигнал от 0 до 1, который сообщает нам, предсказывает ли модель кота (0) или собака (1).

  • Обучение: мы используем SGD со скоростью обучения 0,01. (Обратите внимание, что эта скорость обучения отличается от предыдущей статьи.) Мы тренируемся до тех пор, пока потеря проверки не перестанет улучшаться более чем на 100 итерациях.

Как размер партии влияет на обучение?

Давайте опробуем различные размеры партий в реальных условиях с помощью нашего набора данных «Кошки против собак» и посмотрим, как работает каждая из них!

Из приведенных выше графиков можно сделать вывод, что чем больше размер партии:

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

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

Во-вторых, обучение больших пакетов приводит к худшим минимальным потерям при проверке, чем обучение небольших пакетов. Например, размер пакета 256 обеспечивает минимальную потерю проверки 0,395 по сравнению с 0,344 для размера пакета 32.

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

Однако обучение большим пакетам требует больше эпох, чтобы сойтись в минимизатор - 958 для размера пакета 256, 158 для размера пакета 32. Из-за этого обучение большим пакетам в целом заняло больше времени: размер пакета 256 занял почти в четыре раза больше, чем 32! Обратите внимание, что здесь мы не распараллеливали обучение - если бы это было так, то обучение в больших пакетах могло бы обучаться так же быстро, как и обучение в небольших пакетах.

Что произойдет, если мы распараллелим тренировочные прогоны? Чтобы ответить на этот вопрос, мы распараллелили обучение на четырех графических процессорах с помощью MirroredStrategy в TensorFlow:

with tf.distribute.MirroredStrategy().scope():
   # Create, compile, and fit model
   # ...

MirroredStrategy копирует все переменные модели на каждый графический процессор и распределяет вычисления прямого / обратного прохода в пакете на все графические процессоры. Затем он комбинирует градиенты от каждого графического процессора, используя all-reduce, а затем применяет результат к каждой копии модели графического процессора. По сути, он разделяет пакет и назначает каждый фрагмент графическому процессору.

Мы обнаружили, что распараллеливание сделало обучение небольшими партиями немного медленнее для каждой эпохи, в то время как оно сделало обучение большими партиями быстрее - для размера партии 256 каждая эпоха занимала 3,97 секунды, по сравнению с 7,70 секунды. Однако даже с ускорением на каждую эпоху он не может соответствовать размеру пакета 32 с точки зрения общего времени обучения - когда мы умножаем на общее количество эпох (958), мы получаем общее время обучения ~ 3700 секунд, что составляет все еще намного больше, чем 1915 секунд для размера партии 32.

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

Почему партии меньшего размера работают лучше?

Кескар и др. Предлагают объяснение разницы в производительности между маленькими и большими размерами пакетов: обучение с небольшими размерами пакетов имеет тенденцию сходиться к плоским минимизаторам, которые незначительно различаются в пределах небольшой окрестности минимизатора, тогда как большие пакеты размеры сходятся к резким минимизаторам, которые резко различаются [1]. Плоские минимизаторы обычно лучше обобщают, поскольку они более устойчивы к изменениям между обучающим и тестовым наборами [1].

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

Давайте проверим эти гипотезы.

Гипотеза 1: Минимизатор малых партий находится дальше от начальных весов по сравнению с минимизатором больших партий.

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

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

Почему тренировки с большими партиями приближаются к начальным весам? Требуются ли более мелкие шаги обновления? Давайте выясним, почему, измерив расстояние между эпохами, т. Е. Расстояние между окончательными весами в эпоху i и начальными весами в эпоху i - для пакетов размером 32 и 256.

Первый график выше показывает, что пакеты большего размера действительно проходят меньшее расстояние за эпоху. Расстояние эпохи обучения пакета 32 варьируется от 0,15 до 0,4, тогда как для пакета 256 обучения оно составляет около 0,02–0,04. Фактически, как мы видим на втором графике, соотношение расстояний между эпохами увеличивается со временем!

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

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

Median batch update norm for batch size 32: 3.3e-3
Median batch update norm for batch size 256: 1.5e-3

Мы видим, что каждое пакетное обновление тем меньше, чем больше размер пакета. Почему это так?

Чтобы понять это поведение, давайте создадим фиктивный сценарий, в котором у нас есть два вектора градиента a и b, каждый из которых представляет градиент для одного обучающего примера. Давайте подумаем, как средний размер пакета обновления для размера пакета = 1 сравнивается с размером пакета = 2.

Если мы используем размер партии, равный единице, мы сделаем шаг в направлении a, затем в направлении b, в конечном итоге в точке, представленной a + b. (Технически градиент для b будет пересчитан после применения a, но пока давайте проигнорируем это). В результате получается средний размер пакетного обновления (| a | + | b |) / 2 - сумма размеров пакетного обновления, деленная на количество пакетных обновлений.

Однако, если мы используем размер пакета, равный двум, пакетное обновление вместо этого будет представлено вектором (a + b) / 2 - красной стрелкой на рисунке 12. Таким образом, средний размер пакета обновления составляет | (a + b) / 2 | / 1 = | а + Ь | / 2.

Теперь сравним два средних размера пакетного обновления:

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

Другими словами, чтобы средний размер пакета для размера пакета 1 и размера пакета 2 был равен, векторы a и b должны быть направлены в одном направлении. , поскольку именно тогда | a | + | b | = | а + Ь |. Мы можем расширить этот аргумент до n векторов - только когда все n векторов указывают в одном направлении, это средние размеры пакета обновления для размера пакета = 1 и размера пакета = n то же самое. Однако этого почти никогда не бывает, поскольку векторы градиента вряд ли будут указывать в одном и том же направлении.

Если мы вернемся к уравнению обновления мини-пакета на рисунке 16, мы в некотором смысле говорим, что по мере увеличения размера пакета | B_k | величина суммы градиентов увеличивается сравнительно менее быстро. Это связано с тем, что векторы градиента указывают в разных направлениях, и, таким образом, удвоение размера пакета (т. Е. Количества векторов градиента для суммирования) не приводит к удвоению величины итоговой суммы векторов градиента. При этом делим на знаменатель | B_k | это вдвое больше, что приводит к уменьшению общего шага обновления.

Это могло бы объяснить, почему пакетные обновления для пакетов большего размера имеют тенденцию быть меньше - сумма векторов градиента становится больше, но не может полностью компенсировать больший знаменатель | B_k |.

Гипотеза 2: обучение небольшими партиями находит более плоские минимизаторы

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

В первом мы наносим на график потери при обучении и проверке по линии между минимизатором небольшой партии (размер партии 32) и устройством минимизации большой партии (размер партии 256). Эта линия описывается следующим уравнением:

где x_l * - минимизатор большой партии, x_s * - минимизатор маленькой партии, а альфа - коэффициент от -1 до 2.

Как мы видим на графике, минимизатор малых партий (альфа = 0) намного более плоский, чем минимизатор больших партий (альфа = 1), который изменяется гораздо более резко.

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

где epsilon - параметр, определяющий размер окрестности, а x - минимизатор (веса).

Затем мы определяем метрику резкости как максимальные потери в этой окрестности вокруг минимизатора:

где f - функция потерь, а входными данными являются веса.

Используя приведенные выше определения, давайте вычислим резкость минимизаторов при различных размерах пакетов со значением эпсилон 1e-3:

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

Наконец, давайте попробуем построить минимизаторы с визуализацией потерь, нормализованных фильтром, как это сформулировано Ли и др. [2]. Этот тип графика выбирает два случайных направления с теми же размерами, что и веса модели, а затем нормализует каждый сверточный фильтр (или нейрон, в случае слоев FC), чтобы иметь ту же норму, что и соответствующий фильтр в весах модели. Это гарантирует, что резкость минимизатора не зависит от величины его веса. Затем он отображает потери по этим двум направлениям, причем центр графика является минимизатором, который мы хотим охарактеризовать.

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

Можем ли мы улучшить производительность при работе с большими партиями за счет увеличения скорости обучения?

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

Этот подход был предложен ранее, например, Гоялом и др. [3]:

Правило линейного масштабирования: когда размер мини-пакета умножается на k, умножьте скорость обучения на k.

Давайте попробуем это с размерами пакетов 32, 64, 128 и 256. Мы будем использовать базовую скорость обучения 0,01 для размера пакета 32 и соответственно масштабировать для других размеров пакетов.

Действительно, мы обнаружили, что регулировка скорости обучения действительно устраняет большую часть разрыва в производительности между небольшими и большими размерами пакетов. Теперь при размере пакета 256 потеря проверки составляет 0,352 вместо 0,395, что намного ближе к потере размера 32 пакета, равной 0,345.

Как увеличение скорости обучения влияет на время обучения? Поскольку обучение больших пакетов теперь может сходиться примерно за такое же количество итераций, как и обучение небольших пакетов, как показано на левом графике на рисунке 25, теперь обучение занимает меньше времени - 2197 секунд для пакета размером 256 по сравнению с 3156 секунд для пакета. размер 32. Ускорение становится еще более заметным, если мы распараллеливаем 4 графических процессора.

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

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

Неужели тренировочные прогоны больших партий теперь так же далеки от начальных весов, как и маленькие партии?

Ответ, по большей части, да. Если мы посмотрим на график выше, регулировка скорости обучения помогает сократить разрыв между размером пакета 32 и другими размерами пакетов с точки зрения расстояния от начальных весов. (Обратите внимание, что 128 кажется аномалией, когда увеличение скорости обучения уменьшало расстояние - почему это так, остается открытым для дальнейшего исследования.)

Всегда ли так, что обучение небольшими партиями превосходит обучение большими партиями?

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

Здесь мы видим, что размер пакета 64 на самом деле превосходит размер пакета 32! Это связано с тем, что скорость обучения и размер пакета тесно связаны: небольшие размеры пакетов лучше всего работают с меньшей скоростью обучения, в то время как большие размеры пакетов лучше всего работают с большей скоростью обучения. Мы можем увидеть это явление ниже:

Мы видим, что скорость обучения 0,01 - лучшая для пакета размером 32, тогда как 0,08 - наилучшая для других размеров пакета.

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

Заключение

Так что все это значит? Что мы можем извлечь из этих экспериментов?

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

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

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

Пакеты больших размеров, даже с учетом скорректированной скорости обучения, в наших экспериментах выполнялись несколько хуже, но требуется больше данных, чтобы определить, хуже ли в целом большие пакеты. Мы по-прежнему наблюдаем небольшой разрыв в производительности между наименьшим размером партии (val loss 0,343) и наибольшим (val loss 0,352). Некоторые предположили, что небольшие партии имеют регуляризирующий эффект, потому что они вносят шум в обновления, который помогает тренировке избежать притяжения субоптимальных локальных минимумов [1]. Однако результаты этих экспериментов показывают, что разрыв в производительности относительно невелик, по крайней мере, для этого набора данных. Это говорит о том, что до тех пор, пока вы найдете правильную скорость обучения для вашего размера партии, вы можете сосредоточиться на других аспектах обучения, которые могут иметь большее влияние на производительность.

Github

Код и цифры можно найти здесь.

использованная литература

  1. Кескар, Ночедал, Мудигере, Смелянский, Тан. О крупномасштабном обучении для глубокого обучения: пробел в обобщении и резкие минимумы. Https://arxiv.org/pdf/1609.04836.pdf
  2. Ли, Сюй, Тейлор, Студер и Гольдштейн. Визуализация ландшафта потерь нейронных сетей. Https://papers.nips.cc/paper/7875-visualizing-the-loss-landscape-of-neural-nets.pdf.
  3. Гойал, Доллар, Гиршик, Нордхейс, Весоловски, Кирола, Туллох, Джиа и Хе. Точная, крупная минипакетная SGD: обучение ImageNet за 1 час. Https://research.fb.com/wp-content/uploads/2017/06/imagenet1kin1h5.pdf.