Важность нормализации ваших данных

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

Часть II: Соображения по инициализации

Часть III: Какие функции активации позволяют вам узнать

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

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

Начнем с задачи классификации, состоящей из двух концентрических окружностей.

Мы сгенерировали данные по следующему правилу: если x [0] ² + x [1] ² ≥ 1, то Y = 1 (зеленым), иначе Y = 0 (синим). Наша цель - найти хорошее приближение к этому правилу на основе созданной нами выборки. Для выполнения этой задачи мы создали простую нейронную сеть с одним скрытым слоем, содержащим 2 нейрона:

model = keras.models.Sequential()
model.add(layers.Dense(2, input_dim=2, activation=SOME_ACTIVATION))
model.add(layers.Dense(1, activation='sigmoid'))
model.compile(loss="binary_crossentropy")

Мы можем визуализировать Сеть как таковую:

Примечание. Мы используем сигмовидную активацию для последнего слоя и binary_crossentropy потерь, чтобы использовать интуицию из логистической регрессии, где граница решения между нашими двумя классами будет линейной функцией h0 и h1. Напомним, если мы не активируем скрытый слой, тогда h0 и h1 являются линейными функциями от x0 и x1, что означает, что мы вернулись к традиционной логистической регрессии.

Мы активируем наш скрытый слой с помощью ReLU (мы подробно рассмотрим функции активации в Части III), потому что нейрон будет активен, если вход в ReLU больше, чем 0 и неактивен в противном случае. Это упростит рассуждение об активации.

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

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

По большей части кажется, что когда h0 активирован, h1 нет, и наоборот. Когда h0 или h1 активированы, он выводит линейную комбинацию x0 и x1, которые его активировали, - преобразование наших данных, которые затем сеть линейно разделяет, как показано выше.

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

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

Насколько вероятно это случится?

Читая Документацию Keras, мы видим, что метод инициализации по умолчанию - это генерация весов равномерно и случайным образом на интервале [-L, L], где L зависит от слоя.

Давайте продолжим использовать сеть выше и предположим, что все веса взяты из U (-1, 1). Если x [0] и x [1] также происходят из U (-1, 1), каково распределение числа активированных нейронов? Если сейчас игнорировать смещение, как часто WX> 0 для двух скрытых нейронов в сети?

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

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

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

Таким образом, у нас есть хороший шанс, что примерно половина наших данных для этой конкретной Сети активирует данный нейрон после инициализации - каждый нейрон получит случайный 50% -ный фрагмент наших данных. Похоже, это связано с симметрией наших данных относительно 0.

Что произойдет, если наши данные не сосредоточены вокруг 0? Вот анимация распределения доли данных, ответственных за активацию данного нейрона, по мере того, как наши данные меняются от U (-1, 1) до U (8, 10), а веса остаются U (-1, 1).

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

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

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

Влияет ли центрирование около 0 на распределение числа активированных нейронов? Опять же, исправив распределение веса как U (-1, 1), но изменив распределение данных:

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

Это имеет интуитивный смысл: если все значения X положительны, то WX ›0 так же часто, как W› 0 - что примерно в половине случаев, если W имеет нулевой центр.

Давайте изобразим это явление на реальной нейронной сети.

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

Мы видим большое движение и изменчивость, потому что каждый нейрон имеет доступ к случайной части (которая, как мы ожидаем, составляет около 50%) наших данных. Степень перекрытия между этими частями для любых двух нейронов является случайной (на самом деле U (0, 1/2)).

Вот анимация процесса обучения:

Теперь посмотрим, что происходит, когда данные не нормализованы! Для данных с центром в [10, 10] вы увидите слева сеть после инициализации и справа после обучения:

Сеть зависла. Функции представляют собой либо глобальные линейные преобразования данных, либо постоянно равны 0. И после эпох обучения (изображение справа) это не улучшается, потому что требуется найти веса, которые активируют только части данных, которые, как мы установили, имеют очень низкий вероятность возникновения. Ничего нового мы не узнали ... Вот анимация процесса обучения:

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

Это зависит от того, насколько далеко от нуля сместились данные. Рассмотрим сигмовидную функцию:

Если данные примерно равны [10,10], как указано выше, то, поскольку WX может принимать очень большие величины, мы можем ожидать, что 𝞂 (WX) большую часть времени будет фактически равным 0 или фактически 1. В обоих случаях нейрон усвоил постоянную особенность, которая не помогает процессу обучения.

Итак, мы можем ожидать такого же поведения от других функций активации.

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

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

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

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

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

Часть II: Соображения по инициализации

Часть III: Какие функции активации позволяют вам узнать

Благодарности

Спасибо Джеймсу Кунстлу, Ицзинь Яну, Кэмерон Гаррисон, Марии Шевчук, Анки Линь, Кристине Сюй, Минчэн Сюй за их вклад.