Запутанное использование отсева при мини-градиентном спуске
Мой вопрос в конце.
Пример CNN, обученный с мини-пакетом GD и использовавший выпадение в последнем полностью подключенном слое (строка 60) как
fc1 = tf.layers.dropout(fc1, rate=dropout, training=is_training)
Сначала я думал, чтоtf.layers.dropout
или жеtf.nn.dropout
случайным образом устанавливает нейроны в ноль в столбцах. Но недавно я обнаружил, что это не так. Приведенный ниже фрагмент кода печатает, что dropout
делает. Я использовал fc0
в качестве матрицы признаков 4 х 10, а fc
как выпавшая версия.
import tensorflow as tf
import numpy as np
fc0 = tf.random_normal([4, 10])
fc = tf.nn.dropout(fc0, 0.5)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
a, b = sess.run([fc0, fc])
np.savetxt("oo.txt", np.vstack((a, b)), fmt="%.2f", delimiter=",")
И в выходнойoo.txt
(исходная матрица: строка 1-4, выпадающая матрица: строка 5-8):
0.10,1.69,0.36,-0.53,0.89,0.71,-0.84,0.24,-0.72,-0.44
0.88,0.32,0.58,-0.18,1.57,0.04,0.58,-0.56,-0.66,0.59
-1.65,-1.68,-0.26,-0.09,-1.35,-0.21,1.78,-1.69,-0.47,1.26
-1.52,0.52,-0.99,0.35,0.90,1.17,-0.92,-0.68,-0.27,0.68
0.20,0.00,0.71,-0.00,0.00,0.00,-0.00,0.47,-0.00,-0.87
0.00,0.00,0.00,-0.00,3.15,0.07,1.16,-0.00,-1.32,0.00
-0.00,-3.36,-0.00,-0.17,-0.00,-0.42,3.57,-3.37,-0.00,2.53
-0.00,1.05,-1.99,0.00,1.80,0.00,-0.00,-0.00,-0.55,1.35
Мое пониманиеправильного? выпадение - это выбивание p% одинаковых единиц для каждого образца в фазе мини-партии или спуска с градиентом партии, а обратное распространение обновляет весовые коэффициенты и смещения "утонченной сети". Однако при реализации примера нейроны каждого образца в одной партии были выброшены случайным образом, как показано на рисунке. oo.txt
от 5 до 8, и для каждого образца "прореженная сеть" отличается.
Для сравнения: в случае стохастического градиентного спуска образцы вводятся в нейронную сеть один за другим, и на каждой итерации вес каждого tf.layers.dropout
Введенные "прореженные сети" обновляются.
Мой вопрос в том, что в мини-партии или в периодическом обучении не должно быть реализовано, чтобы выбивать одни и те же нейроны для всех образцов в одной партии? Может быть, применяя одну маску ко всем входным пакетным выборкам на каждой итерации? Что-то вроде:
# ones: a 1xN all 1s tensor
# mask: a 1xN 0-1 tensor, multiply fc1 by mask with broadcasting along the axis of samples
mask = tf.layers.dropout(ones, rate=dropout, training=is_training)
fc1 = tf.multiply(fc1, mask)
Теперь я думаю, что стратегия отсева в примере может быть взвешенным способом обновления весов определенного нейрона, что если нейрон сохраняется в 1 из 10 образцов в мини-пакете, его вес будет обновляться alpha * 1/10 * (y_k_hat-y_k) * x_k
по сравнению с alpha * 1/10 * sum[(y_k_hat-y_k) * x_k]
для весов другого нейрона, сохраненного во всех 10 образцах?
скриншот отсюда
2 ответа
Выпадения обычно используются для предотвращения переоснащения. В этом случае это будет огромный вес, примененный к одному из нейронов. Время от времени делая случайным образом 0, вы заставляете сеть использовать больше нейронов при определении результата. Чтобы это работало хорошо, вы должны отбрасывать разные нейроны для каждого примера, чтобы вычисляемый вами градиент был больше похож на тот, который вы получили бы без выпадения.
Если бы вы отбрасывали одни и те же нейроны для каждого примера в пакете, я предполагаю, что у вас будет менее стабильный градиент (может не иметь значения для вашего приложения).
Кроме того, выпадающее меню увеличивает масштаб остальных значений, чтобы средняя активация оставалась примерно на одном уровне. Без этого сеть выучила бы неправильные отклонения или была бы перенасыщена, когда вы отключили отсев.
Если вы все еще хотите, чтобы те же нейроны были отброшены в пакете, тогда примените выпадение ко всем 1 тензорным фигурам (1, num_neurons) и затем умножьте их на активации.
При использовании отсева вы фактически пытаетесь оценить среднюю производительность сети для случайно выбранной маски отсева, используя выборку по методу Монте-Карло (путем дифференцирования под знаком интеграла средний градиент равен градиенту среднего). Устанавливая маску исключения для каждой мини-партии, вы просто вводите корреляцию между последовательными оценками градиента, что увеличивает дисперсию и приводит к более медленному обучению.
Представьте себе, что для каждого изображения в мини-пакете используется отдельная маска выпадения, но при этом формируется мини-партия из k копий одного и того же изображения; очевидно, что это будет полная трата усилий!