Как работает дроп-аут в нейронных сетях
Что проверяют
Понимаете ли вы, что происходит с активациями на обучении и на инференсе и зачем нужно масштабирование. Вопрос из категории кодинга, поэтому часто просят написать прямой проход dropout руками, а следом спрашивают, почему модель в проде даёт разные ответы на один и тот же вход.
Как отвечать
Dropout это регуляризация: на каждом шаге обучения каждый нейрон слоя обнуляется с вероятностью p независимо от остальных. Сеть не может опереться на пару конкретных нейронов и учит более избыточные признаки. Удобная интерпретация: обучается ансамбль прореженных подсетей с общими весами, а на инференсе используется их усреднение.
Ключевой момент в масштабе. Во всех современных фреймворках реализован inverted dropout:
- обучение: выжившие активации умножают на
1/(1-p), чтобы матожидание выхода не менялось; - инференс: слой ничего не делает, выход проходит как есть.
В NumPy это две строки: mask = (np.random.rand(*x.shape) > p) / (1-p) и out = x * mask. Маску сохраняют, на обратном проходе градиент умножается на неё же.
Практика:
- PyTorch:
nn.Dropout(p=0.5), гдеpэто доля обнуляемых, а не сохраняемых. Режим переключаютmodel.train()иmodel.eval(); - Keras:
layers.Dropout(rate), активен только приtraining=True, вfitэто происходит само; - где ставить: после полносвязных слоёв, в трансформерах на attention и residual, обычно около 0.1. В свёрточных сетях с BatchNorm его часто не ставят вовсе, при предобучении больших языковых моделей тоже нередко выключают;
- MC dropout: если оставить слой включённым на инференсе и прогнать вход много раз, разброс ответов даёт оценку неопределённости.
Где спотыкаются
Масштабируют дважды: делят на 1-p при обучении и ещё раз домножают на инференсе. В исходной статье масштаб действительно применяли на тесте, но смешивать два варианта нельзя.
Забывают model.eval() перед валидацией или в проде. Метрики скачут, а одинаковые запросы дают разные предсказания.
Путают смысл p. В PyTorch и Keras это вероятность выключить нейрон, а в старом TensorFlow 1 был keep_prob, ровно наоборот.