Выбрано из PCC Мэттом Х., Даниэлем Р., составлено Heart of the Machine.
В этой статье представлены некоторые основные методы построения глубоких нейронных сетей, начиная с трех аспектов: общие методы, отладка нейронных сетей и тематические исследования.
В нашей лаборатории машинного обучения мы накопили богатый опыт, проведя тысячи часов обучения на многих высокопроизводительных машинах. В этом процессе не только компьютеры получили много знаний, на самом деле, наши исследователи также сделали много ошибок и исправили множество лазеек.
В этой статье мы предоставим вам несколько практических советов по обучению глубоких нейронных сетей, основанных на собственном опыте (в основном на основе TensorFlow). Некоторые советы могут быть вам уже знакомы, а другие нет. Есть также некоторые предложения, которые могут быть неприменимы и даже могут быть плохими для конкретной задачи, поэтому используйте их с осторожностью!
Это некоторые известные методы, а мы стоим на плечах гигантов! Цель этой статьи — просто дать общий обзор того, как их использовать на практике.
Общие советы
Используйте оптимизатор ADAM. Это работает, и мы предпочитаем ADAM более традиционным оптимизаторам, таким как ванильный градиентный спуск. Примечание при использовании ADAM в среде TensorFlow: если вы хотите сохранить и восстановить веса модели, не забудьте установить Saver после настройки AdamOptimizer, потому что у ADAM также есть состояние, которое необходимо восстановить (т.е. обучение, соответствующее каждому весу) Rate).
ReLU — лучшая нелинейность (функция активации), точно так же, как Sublime — лучший текстовый редактор. Но, по правде говоря, ReLU действительно являются самыми быстрыми и простыми в использовании, и, что удивительно, они не уменьшают постепенно градиенты во время работы (таким образом предотвращая их исчезновение). Хотя сигмовидная является широко используемой функцией активации, она не очень эффективна для распространения градиентов в DNN.
Не используйте функции активации в выходном слое. Это должно быть очевидно, но если вы строите каждый слой с помощью общей функции, легко допустить ошибку: убедитесь, что вы не используете функцию активации в выходном слое.
Добавьте термин смещения к каждому слою. Вот пример машинного обучения: по сути, член смещения преобразует плоскость в наиболее подходящее положение. В формуле y=mx+b b — это член смещения, который позволяет линии перемещаться вверх или вниз в наилучшее положение.
Инициализировать с масштабированием дисперсии. В TensorFlow этот метод записывается как tf.contrib.layers.variance_scaling_initializer(). Согласно нашим экспериментам, этот метод инициализации имеет лучшую производительность обобщения/масштабирования, чем обычная гауссовская инициализация, усеченная гауссовская инициализация и инициализация Ксавьера. Грубо говоря, инициализация масштабирования дисперсии регулирует дисперсию начальных случайных весов на основе количества входных или выходных данных в каждом слое (которое в TensorFlow по умолчанию равно количеству входных данных), помогая сигналу, когда нет других приемов, таких как отсечение градиента или пакетная обработка. необходима нормализация) для более глубокого распространения в сети. Xavier похож на инициализацию масштабирования дисперсии, за исключением того, что дисперсия каждого слоя в Xavier почти одинакова; однако, если масштаб слоев сильно различается (как это часто бывает в сверточных нейронных сетях), эти сети могут работать плохо. иметь дело с одной и той же дисперсией в каждом слое.
Отбеливает (нормализует) входные данные. Во время обучения вычтите среднее значение набора данных из значения точки выборки, а затем разделите на его стандартное отклонение. Чем меньше веса вашей сети растягиваются и расширяются во всех направлениях, тем быстрее и легче ваша сеть может обучаться. Сохранение ввода данных вокруг среднего значения с постоянной дисперсией помогает достичь этого. Вы также должны выполнить один и тот же процесс нормализации для каждого тестового входа, поэтому убедитесь, что ваш тренировочный набор похож на реальные данные.
Масштабируйте входные данные таким образом, чтобы разумно сохранялся динамический диапазон. Этот шаг связан с нормализацией, но его следует выполнять перед операцией нормализации. Например, данными x в диапазоне [0, 140000000] в реальном мире обычно можно управлять с помощью «tanh(x)» или «tanh(x/C)», где C — некоторая константа, которую можно использовать для управления кривая Растягивается, чтобы подогнать данные по большему входному диапазону в динамически скошенной (большой наклон) части функции тангенса. Особенно, когда входные данные не ограничены на одном или обоих концах функции, нейронная сеть лучше обучается, когда данные находятся в (0,1).
Как правило, не используйте затухание скорости обучения. В стохастическом градиентном спуске (SGD) обычно снижают скорость обучения, но ADAM, естественно, учитывает это. Если вы действительно хотите достичь максимальной производительности своей модели, уменьшите скорость обучения на короткий период до окончания обучения; вы можете увидеть небольшое внезапное падение ошибки, после чего она снова выравнивается.
Если ваш сверточный слой имеет 64 или 128 фильтров, этого должно быть достаточно. Особенно для глубоких сетей, скажем, 128 фильтров — это много. Если у вас уже есть большое количество фильтров, добавление дополнительных фильтров может не повысить производительность.
Объединение предназначено для инвариантности преобразования. Объединение по существу позволяет сети изучить «общую концепцию» «некоторой части» изображения. Например, максимальное объединение может помочь сверточной сети быть устойчивой к перемещению, вращению и масштабированию функций в изображениях.
Отладка нейронных сетей
Если сеть плохо обучается (имеется в виду, что потери/точность сети во время обучения не сходятся или вы не получаете желаемых результатов), вы можете попробовать следующие советы:
Переоснащение! Если ваша сеть плохо обучается, первое, что вы должны сделать, это подобрать точку обучающих данных. Точность в основном должна быть 100% или 99,99%, или ошибка близка к 0. Если ваша нейронная сеть не может переопределить точку данных, то может возникнуть серьезная проблема с архитектурой модели, но проблема может быть очень тонкой. Если вы можете переопределить точку данных, но по-прежнему не можете сходиться при обучении на большом наборе, попробуйте несколько из приведенных ниже предложений.
Снизить скорость обучения. Ваша сеть будет обучаться медленнее, но она может найти минимум, который она не нашла ранее, с большим размером шага. (Интуитивно можно представить, что вы идете через канаву на обочине дороги, и в этот момент вы хотите пройти в самую глубокую часть канавы, где погрешность модели наименьшая.)
Увеличьте скорость обучения. Это ускорит обучение и поможет укрепить петлю обратной связи. Это означает, что вы можете быстро получить приблизительное представление о том, работает ли ваша сеть. Хотя таким образом сеть должна сходиться быстрее, результаты обучения могут быть не такими хорошими, и это «сходящееся» состояние может на самом деле многократно колебаться. (При использовании оптимизатора ADAM мы считаем, что ~ 0,001 — это хорошая скорость обучения во многих экспериментальных сценариях.)
Уменьшите размер (мини) пакетной обработки. Уменьшение размера пакета до 1 может дать вам более точную обратную связь, связанную с обновлениями веса, и вы должны показать этот процесс в TensorBoard (или другом инструменте отладки/визуализации).
Удалите слой нормализации партии. При этом возникают такие проблемы, как исчезновение и взрыв градиентов при уменьшении размера пакета до 1. Однажды у нас была сеть, которая не сходилась неделями, и когда мы удалили слой пакетной нормализации (слой BN), мы поняли, что на выходе второй итерации все было NaN. Использование слоя пакетной нормализации здесь эквивалентно наложению пластыря на рану, требующую наложения жгута. У пакетной нормализации есть место, где она может работать, но только если вы уверены, что ваша сеть свободна от ошибок.
Увеличьте размер (небольшой) пакетной обработки. Использование большего размера пакета — если этого недостаточно, вы можете также использовать весь обучающий набор, если можете — уменьшает дисперсию обновлений градиента, делая каждую итерацию более точной. Другими словами, обновление веса может пойти в правильном направлении. но! Существует верхний предел его эффективности, а также некоторые ограничения физической памяти. Мы обнаружили, что это предложение, как правило, менее полезно, чем первые два предложения (уменьшить размер пакета до 1, удалить слой нормализации пакета).
Проверьте "изменить форму" вашей матрицы. Масштабные матричные реконструкции (например, изменение размеров изображения по осям X и Y) разрушат пространственную локальность и усложнят обучение сети, потому что тогда сеть также должна научиться реконструировать. (Природные объекты становятся фрагментированными. Тот факт, что естественные объекты демонстрируют пространственную локальность, делает сверточные нейронные сети такими эффективными!) Будьте особенно осторожны при использовании нескольких изображений/каналов для реконструкции; это можно сделать с помощью numpy.stack() Правильной операции выравнивания.
Дважды проверьте свою функцию потерь. Если мы работаем со сложной функцией, попробуйте упростить ее до чего-то вроде L1 или L2. Мы обнаружили, что L1 менее чувствителен к выбросам и может немного корректироваться, когда мы сталкиваемся с шумными партиями или тренировочными точками.
Если можете, перепроверьте свои визуализации. Ваша библиотека визуализации (matplotlib, OpenCV и т. д.) корректирует диапазон значений данных или обрезает их? Вы можете рассмотреть возможность использования визуально однородной цветовой схемы.
тематическое исследование
Чтобы сделать описанный выше процесс более актуальным, вот несколько графиков потерь (визуализированных с помощью TensorBoard), которые использовались для описания некоторых реальных экспериментов по регрессии нашей сконструированной сверточной нейронной сети.
Изначально сеть вообще не узнала:
Попробуем обрезать значения данных, чтобы они не выходили за пределы допустимого диапазона:
Посмотрите, какие «сумасшедшие» эти несглаженные значения! Скорость обучения слишком высока? Давайте попробуем уменьшить скорость обучения и потренироваться на наборе входных данных:
Вы можете увидеть, где происходят первые несколько изменений в скорости обучения (около 300 и 3000 шагов обучения). Очевидно, здесь мы слишком быстро снижаем скорость обучения. Поэтому, если вы дадите ему более длительное время затухания скорости обучения, он будет работать лучше (меньшие потери):
Как видите, скорость обучения падает на шагах 2000 и 5000. Это лучше, но все же не идеально, потому что потери не падают до 0.
Затем мы останавливаем снижение скорости обучения и пытаемся сместить входное значение в более узкий диапазон с помощью функции tanh. Это, очевидно, приводит к тому, что значение ошибки становится меньше 1, но мы все еще не можем переобучить тренировочный набор:
Здесь мы обнаруживаем, что при удалении слоя пакетной нормализации сеть быстро выводит NaN после одной или двух итераций. Мы отключили пакетную нормализацию и изменили метод инициализации на масштабирование дисперсии. В этом вся разница! Мы можем переобучить тестовый набор, содержащий только один или два входа. Однако на графике ниже ось Y обрезана. Начальное значение ошибки намного выше 5, что означает, что ошибка уменьшилась почти на 4 порядка:
Верхний график очень гладкий, но, как вы можете видеть, он очень быстро превосходит входные данные теста, и со временем потери падают ниже 0,01 для всего тренировочного набора. Этот процесс не снижает скорость обучения. После этого мы продолжили обучение после того, как скорость обучения снизилась на порядок, и получили лучшие результаты:
Эти результаты намного лучше! Но что, если вместо разделения обучения на две части мы уменьшим скорость обучения в геометрической прогрессии?
Умножая скорость обучения на 0,9995 на каждом шаге, мы получаем не очень хороший результат:
Вероятно, это связано с тем, что скорость обучения падает слишком быстро. Множитель 0,999995 был бы лучше, но результат не сильно отличается от полного отсутствия затухания. Из этой конкретной последовательности экспериментов мы пришли к выводу, что пакетная нормализация скрывает взрывные градиенты, вызванные плохой инициализацией, и что, если не считать преднамеренно спроектированного снижения скорости обучения в конце, которое может помочь, снижение скорости обучения мало влияет на оптимизатор ADAM. помощь. Как и в случае пакетной нормализации, отсечение значений маскирует реальную проблему. Мы также контролируем входные значения с высокой дисперсией с помощью функции tanh.
Мы надеемся, что эти основные советы помогут вам по мере того, как вы будете лучше разбираться в построении глубоких нейронных сетей. Часто именно простые вещи решают все.