Keras, миниатюрный градиентный спуск со слоем Dropout - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть вопрос о реализации Dropout в Keras / Tensorflow с оптимизацией мини-пакетного градиентного спуска, когда параметр batch_size больше единицы. Оригинальный документ гласит:

Единственное отличие состоит в том, что для каждого учебного случая в мини-партии мы отбираем разбавленную сеть, отбрасывая единицы. Прямое и обратное распространение для этого учебного случая выполняется только в этой прореженной сети. Градиенты для каждого параметра усредняются по тренировочным кейсам в каждой мини-партии. Любой обучающий случай, в котором не используется параметр, вносит нулевой градиент для этого параметра.

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

Проходя по исходному коду, я не вижу, если и где он обрабатывается. В функции _process_single_batch вычисляется общая \ средняя потеря партии и на основе этого градиента партии рассчитывается. Это прекрасно работает для моделей без слоя Dropout, но как насчет слоя Dropout, как запоминаются индивидуальные настройки модели для каждого образца (с выпадением разных нейронов), а затем учитываются при расчете градиентного спуска?

Я думаю, что я я что-то упустил, и я хочу быть уверен, что правильно понимаю реализацию Keras мини-пакетного градиентного спуска, когда задействован слой Dropout.

Ответы [ 2 ]

0 голосов
/ 19 февраля 2020

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

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

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

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

Реализация полной идеи отбрасывания нейронов будет много более сложный.

0 голосов
/ 19 февраля 2020

TensorFlow на самом деле не «выбрасывает» некоторые нейроны из модели, а просто умножает на ноль их выходы. Давайте посмотрим на реализацию выпадения:

def dropout_v2(x, rate, noise_shape=None, seed=None, name=None):
    <...>
    # Sample a uniform distribution on [0.0, 1.0) and select values larger than
    # rate.
    #
    # NOTE: Random uniform actually can only generate 2^23 floats on [1.0, 2.0)
    # and subtract 1.0.
    random_tensor = random_ops.random_uniform(
        noise_shape, seed=seed, dtype=x.dtype)
    keep_prob = 1 - rate
    scale = 1 / keep_prob
    # NOTE: if (1.0 + rate) - 1 is equal to rate, then we want to consider that
    # float to be selected, hence we use a >= comparison.
    keep_mask = random_tensor >= rate
    ret = x * scale * math_ops.cast(keep_mask, x.dtype)
    <...>
    return ret

Итак, x - это вход выпадающего слоя, а rate - это скорость выпадения нейронов. На основе этой скорости генерируется mask - с вероятностью rate каждое значение в этой маске равно 0, в противном случае - 1. Когда мы умножаем выход нейрона на ноль, его градиент также становится равным нулю. Таким образом, мы на самом деле не выбираем какую-то подсеть, а просто обнуляем некоторые ее нейроны. Надеюсь, что это поможет:)

...