🔴 Сложный ⏱️ 60 минут

Dropout и регуляризация

📋 Содержание урока

Dropout и регуляризация 🎲

В уроке 304 ты уже разобрал переобучение в общем виде: модель запоминает шум обучающей выборки вместо настоящей закономерности, и разрыв между train loss и validation loss на графике — самый узнаваемый симптом этой болезни. Тогда речь шла о моделях с сотнями или тысячами параметров — полиномах высокой степени, деревьях решений без ограничения глубины. У современной нейросети параметров не тысячи, а миллионы, а то и миллиарды. Простая полносвязная сеть для распознавания рукописных цифр с одним скрытым слоем из 512 нейронов между входом в 784 пикселя и десятью выходными классами — это уже больше 400 тысяч весов, обучаемых на выборке из 60 тысяч примеров. Любая современная свёрточная сеть или трансформер счёт параметров ведёт на десятки и сотни миллионов. Формально это означает, что у сети чудовищно высокая ёмкость (capacity) — способность выучить наизусть практически любую обучающую выборку, включая весь содержащийся в ней шум, вплоть до случайных меток, если их специально перемешать.

Именно поэтому регуляризация нейросетей — это не факультативное дополнение, а обязательная часть почти каждого реального цикла обучения. Если для линейной регрессии из урока 312 регуляризация — способ справиться с мультиколлинеарностью или числом признаков, превышающим число наблюдений, то для глубокой сети регуляризация — это способ выжить в условиях, когда параметров систематически на порядки больше, чем можно строго обосновать статистически. Без неё сеть с миллионами весов, обучаемая градиентным спуском достаточно долго, рано или поздно найдёт способ идеально подогнаться под обучающую выборку — и тем самым разучится обобщать на новые данные.

Сегодняшний урок — про специфический арсенал приёмов регуляризации, которые родились именно в контексте глубоких сетей или получили в этом контексте новую жизнь. Центральная тема — dropout: метод, который на каждом шаге обучения случайно «выключает» часть нейронов слоя, заставляя сеть строить более робастные, избыточные представления вместо того, чтобы полагаться на узкие, хрупкие комбинации конкретных нейронов. Ты увидишь, что интуиция dropout — почти дословная параллель с бэггингом из урока про случайный лес (урок 317): там разнообразие деревьев создавалось случайностью данных и признаков, здесь разнообразие «подсетей» создаётся случайностью самой архитектуры на каждом шаге. Отдельно разберём L1/L2-регуляризацию весов слоёв — прямое продолжение Ridge и Lasso из урока 312, только применённое не к коэффициентам линейной модели, а к весовым матрицам каждого слоя сети. И закончим двумя предельно практичными техниками — ранней остановкой обучения (early stopping) и аугментацией данных, — которые работают не через изменение функции потерь, а через управление самим процессом обучения и составом обучающей выборки.

🎯 Ты узнаешь:

  • Почему риск переобучения у нейросетей качественно выше, чем у классических моделей ML, и как это связано с числом параметров и ёмкостью модели
  • Что такое dropout, как формально описывается случайная маска нейронов, и почему обучение с dropout — это, по сути, одновременное обучение экспоненциально многих «прореженных» подсетей с общими весами
  • Чем dropout похож на бэггинг в случайном лесе (урок 317), а чем принципиально отличается — прежде всего разделением весов между «подсетями»
  • Что такое inverted dropout, почему именно эта версия — стандарт в PyTorch и TensorFlow, и как масштабирование активаций делает поведение сети на обучении и на инференсе согласованным
  • Как L1- и L2-регуляризация из урока 312 переносятся на веса слоёв нейросети — и чем weight decay в современных оптимизаторах (Adam, AdamW) отличается от классического L2-штрафа в функции потерь
  • Почему ранняя остановка обучения — один из самых дешёвых и эффективных способов регуляризации, и как она напрямую следует из графика переобучения из урока 304
  • Что такое аугментация данных и почему искусственное увеличение обучающей выборки — тоже форма регуляризации, пусть и действующая по-другому, чем dropout или weight decay

История

Идея dropout родилась в лаборатории Джеффри Хинтона в Университете Торонто и прошла путь от короткой заметки до одной из самых влиятельных техник в истории глубокого обучения всего за пару лет. Первое упоминание появилось в 2012 году в статье Хинтона, Нитиша Шринивы, Алекса Крижевского, Ильи Суцкевера и Руслана Салахутдинова «Improving neural networks by preventing co-adaptation of feature detectors» — уже само название говорит о сути идеи: остановить «со-адаптацию» детекторов признаков, то есть ситуацию, когда группы нейронов начинают работать только вместе, компенсируя ошибки друг друга, и теряют способность быть полезными по отдельности.

Хинтон рассказывал о происхождении идеи две истории, обе стали классикой лекций по глубокому обучению. Первая — биологическая: половое размножение при передаче генов перемешивает гены обоих родителей случайным образом, и это заставляет каждый отдельный ген быть полезным «сам по себе», в сочетании с почти произвольным набором генов партнёра, а не полагаться на удачное сочетание именно с конкретными соседними генами — иначе бесполое размножение, копирующее целиком успешный «пакет» генов родителя, было бы эволюционно эффективнее. Вторая история — про банковских служащих: если сотрудники банка не знают заранее, кто именно выйдет в смену завтра, сговориться и организовать мошенничество значительно труднее, потому что план должен работать при случайном составе коллег, а не при одном конкретном сочетании исполнителей. Обе метафоры об одном и том же: устойчивость к случайным перестановкам заставляет каждый элемент системы становиться независимо полезным.

Настоящую известность dropout получил в 2012 году, когда та же группа применила его в сети AlexNet — свёрточной архитектуре, с разгромным отрывом выигравшей конкурс ImageNet и запустившей нынешнюю волну глубокого обучения. AlexNet использовал dropout с вероятностью $p=0{,}5$ в двух последних полносвязных слоях с десятками миллионов весов — именно там риск переобучения был максимален. Авторы прямо писали, что без dropout сеть демонстрировала существенное переобучение, и что этот единственный приём заметно улучшил обобщающую способность архитектуры. В 2014 году в журнале Journal of Machine Learning Research вышла развёрнутая статья «Dropout: A Simple Way to Prevent Neural Networks from Overfitting» — Шриниваса, Хинтона, Крижевского, Суцкевера и Салахутдинова — с полным теоретическим и экспериментальным разбором метода, включая интерпретацию dropout как приближённого обучения экспоненциально большого ансамбля сетей с общими весами и вывод правила масштабирования активаций на инференсе.

Метод оказался настолько влиятельным, что Google даже получил на него патент в США — редкий случай, когда алгоритмический приём регуляризации нейросетей защищён патентным правом (это никак не помешало его свободному использованию во всех основных фреймворках). Уже к середине 2010-х dropout стал стандартным компонентом почти любой глубокой архитектуры с полносвязными слоями. Интересно, что по мере распространения батч-нормализации (урок 332, придуманной в 2015 году) роль dropout в самых больших современных архитектурах — трансформерах, крупных свёрточных сетях — частично сместилась: батч-нормализация сама обладает регуляризующим эффектом, и во многих state-of-the-art архитектурах dropout применяется точечно (например, в слоях внимания трансформеров) или с меньшими значениями $p$, чем в оригинальной статье 2014 года. Но как общий принцип — обучение через управляемое случайное разрежение сети — dropout остаётся одним из первых инструментов, к которым тянется рука практика, столкнувшегося с переобучением полносвязной части архитектуры.


Переобучение в нейросетях: почему риск особенно велик

Интуиция

В уроке 304 ты видел переобучение на примере полиномиальной регрессии: полином степени 15 на 20 точках данных идеально проходит через каждую обучающую точку, но дико колеблется между ними. Нейросеть переобучается по той же логике, но масштаб проблемы другой. Полином степени 15 имеет 16 коэффициентов. Небольшая полносвязная сеть для MNIST с архитектурой 784→512→256→10 имеет сотни тысяч весов. Современный трансформер — миллиарды. Чем больше у модели свободных параметров относительно числа обучающих примеров, тем шире пространство функций, которые она способна выучить, — и тем выше шанс, что среди этих функций найдётся одна, идеально подогнанная под шум конкретной обучающей выборки, но бесполезная на новых данных.

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

Определение

Определение (ёмкость модели, capacity, применительно к нейросети): Ёмкость модели — это мера того, насколько широкий класс функций она способна представить и подогнать под произвольные данные, включая шум. Формально ёмкость связана с числом обучаемых параметров и структурой сети (глубиной, шириной, типом связей), но не сводится к простому подсчёту весов: нелинейные функции активации и глубина композиции многократно увеличивают эффективную ёмкость по сравнению с линейной моделью с тем же числом параметров. Модель с ёмкостью, значительно превышающей объём и разнообразие обучающих данных, склонна к переобучению — минимизации ошибки на обучении ценой роста ошибки на новых данных.

Примеры

Пример 1: подсчёт параметров скромной полносвязной сети. Архитектура $784 \to 512 \to 256 \to 10$ для классификации рукописных цифр (28×28 пикселей на входе, 10 классов на выходе). Число весов и смещений: первый слой $784 \times 512 + 512 = 401\,920$; второй слой $512 \times 256 + 256 = 131\,328$; третий слой $256 \times 10 + 10 = 2\,570$. Итого $401\,920+131\,328+2\,570 = 535\,818$ обучаемых параметров.

Решение. Обучающая выборка MNIST содержит $60\,000$ изображений. Соотношение параметров к примерам: $535\,818 / 60\,000 \approx 8{,}9$ — на каждый обучающий пример приходится почти девять параметров. Для сравнения, у Ridge-регрессии из урока 312 на реалистичных табличных задачах соотношение признаков к наблюдениям редко превышает $1{:}10$ в обратную сторону (то есть наблюдений на порядок больше, чем признаков), и даже это иногда требует регуляризации. Здесь ситуация зеркальная — параметров почти в девять раз больше, чем можно было бы формально считать безопасным без какой-либо регуляризации.

Ответ: сеть из трёх полносвязных слоёв — уже больше полумиллиона параметров, что примерно в девять раз превышает число обучающих примеров MNIST; без регуляризации такая сеть способна выучить обучающую выборку почти наизусть.

Пример 2: экспоненциальный рост выразительной способности с глубиной. Две сети с одинаковым общим числом нейронов в скрытых слоях — одна с одним скрытым слоем из 1000 нейронов, другая с десятью скрытыми слоями по 100 нейронов, обе с ReLU-активацией.

Решение. Известный теоретический результат (Монтуфар и др., 2014) показывает, что число линейных областей, на которые кусочно-линейная функция ReLU-сети разбивает входное пространство, растёт полиномиально с шириной слоя, но экспоненциально с числом слоёв при фиксированном общем числе нейронов. Неглубокая сеть с одним широким слоем из 1000 нейронов может представлять существенно менее сложные кусочно-линейные функции, чем узкая, но глубокая сеть с тем же суммарным числом нейронов, распределённым по десяти слоям.

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

Пример 3: переобучение на случайных метках как демонстрация избыточной ёмкости. Эксперимент Чжан и др. (статья «Understanding deep learning requires rethinking generalization», 2017): те же архитектуры, что достигают state-of-the-art качества на ImageNet и CIFAR-10, обучались на тех же изображениях, но со случайно перемешанными метками классов — то есть с целевой переменной, не имеющей никакой реальной связи с входными данными.

Решение. Сети без каких-либо изменений в архитектуре успешно доводили ошибку на обучении до нуля даже на полностью случайных метках, то есть буквально запоминали соответствие «это конкретное изображение → этот конкретный случайный класс» для каждого из десятков тысяч примеров. Естественно, на новых данных такая «обученная» сеть работала не лучше случайного угадывания, потому что реальной закономерности в данных не было и сеть не могла её выучить — она просто запомнила таблицу соответствий.

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

Почему это важно

Понимание масштаба риска переобучения в нейросетях — не абстрактная теория, а прямое руководство к действию при построении любого реального пайплайна. Если для линейной регрессии из урока 312 регуляризация чаще нужна в частных, хоть и нередких случаях — при явной мультиколлинеарности или при $p>n$, — то для глубокой сети с сотнями тысяч или миллионами параметров отсутствие хоть какой-то регуляризации на данных ограниченного размера следует считать скорее исключением, оправданным только при по-настоящему огромных датасетах (как в предобучении больших языковых моделей на триллионах токенов), чем безопасным выбором по умолчанию. Именно поэтому dropout, weight decay, early stopping и аугментация данных — не экзотические техники для сложных случаев, а стандартный, почти всегда присутствующий набор инструментов в любом серьёзном цикле обучения нейросети.


Dropout: обучение ансамбля прореженных подсетей

Интуиция

Представь команду из десяти аналитиков, которые совместно готовят отчёт. Если один аналитик привык, что коллега X всегда проверяет его цифры, а коллега Y всегда причёсывает финальный текст, со временем в команде выстроится хрупкая сеть взаимных зависимостей: стоит X заболеть — и ошибки в цифрах Y уже некому поймать. Команда работает отлично, пока присутствуют все десять, но плохо приспособлена к любым отклонениям от привычного состава. Теперь представь то же самое, но с намеренным правилом: каждый день случайным образом ровно половина аналитиков не выходит на работу, а оставшиеся всё равно обязаны выпустить качественный отчёт. Аналитик больше не может полагаться на то, что рядом окажется именно X или именно Y — ему приходится становиться более самодостаточным и учиться работать с любым случайным подмножеством коллег. Команда в целом станет менее хрупкой и более устойчивой к отсутствию отдельных людей.

Dropout применяет ровно эту логику к нейронам слоя. На каждом шаге обучения (обычно — на каждом мини-батче) для каждого нейрона слоя независимо подбрасывается монета с вероятностью «выпадения» $p$: если монета выпала — нейрон на этом шаге полностью обнуляется, как будто его никогда не было в сети, и он не участвует ни в прямом проходе, ни в обратном распространении градиента для этого шага. Нейрон не может «договориться» с конкретными соседями о слаженной, но узкоспециализированной совместной работе, потому что на следующем шаге состав его «коллег» окажется уже другим. Это и есть борьба с co-adaptation — со-адаптацией нейронов, о которой писал Хинтон в самом первом названии статьи 2012 года.

Определение

Определение (dropout): На каждом шаге обучения для слоя с активациями $a = (a_1, \dots, a_n)$ независимо для каждой координаты $i$ генерируется бинарная маска $m_i \sim \text{Bernoulli}(1-p)$, где $p \in [0,1]$ — вероятность отключения (dropout rate), гиперпараметр слоя. Итоговая «прореженная» активация: $\tilde a_i = m_i \cdot a_i$ — если $m_i = 0$, нейрон обнулён полностью и не передаёт сигнал дальше; если $m_i=1$, нейрон работает как обычно. Маска перегенерируется заново на каждом шаге обучения (для каждого мини-батча) и, как правило, независимо для каждого примера в батче. На инференсе dropout отключается — маска не применяется, и используется вся сеть целиком, но с компенсацией масштаба активаций (inverted dropout, разобран ниже).

Dropout как ансамбль: параллель со случайным лесом

В уроке 317 ты разбирал, как случайный лес добивается низкой корреляции между деревьями двумя независимыми источниками случайности — бэггингом по объектам (каждое дерево видит свою bootstrap-выборку) и случайным подмножеством признаков на каждом узле. Ключевая математика оттуда — формула дисперсии усреднённого предсказания $B$ деревьев с попарной корреляцией $\rho$: $\mathbb{D}\bar f = \rho\sigma^2 + (1-\rho)\sigma^2/B$. Dropout работает на удивление похоже, хоть и в другом обличье: на каждом шаге обучения фактически обучается не одна сеть, а одна из $2^n$ возможных «прореженных» подсетей слоя с $n$ нейронами — каждая такая подсеть отвечает конкретной реализации бинарной маски. При $n=1000$ нейронов число различных подсетей равно $2^{1000}$ — число, астрономически превышающее любое реалистичное количество деревьев в случайном лесе (обычно несколько сотен, как ты видел в уроке 317).

Но есть принципиальное отличие, которое стоит проговорить явно, чтобы параллель не вводила в заблуждение. Деревья случайного леса — полностью независимые модели: у каждого свой набор узлов, порогов и листьев, они не делят между собой ни одного параметра. «Подсети» dropout, напротив, все до единой пользуются одной и той же общей матрицей весов слоя — каждый шаг обучения просто временно обнуляет часть координат активации, но веса, связывающие нейроны, общие для всех $2^n$ возможных подсетей. Это разделение весов (weight sharing) делает dropout вычислительно дешёвым трюком — не нужно хранить и обучать $2^n$ отдельных наборов параметров, — но именно оно и лежит в основе теста-времени сети: полная сеть с масштабированными активациями на инференсе — это приближение усреднённого предсказания всех $2^n$ подсетей, использующее общие веса, а не честное голосование независимо обученных моделей, как в случайном лесе. Тем не менее сама идея снижения дисперсии итогового предсказания за счёт усреднения по многим разнообразным, слабо скоррелированным «версиям» модели — интеллектуальное ядро обоих методов, бэггинга и dropout, несмотря на разную техническую реализацию.

Примеры

Пример 1 (простой): конкретная маска и прореженная активация. Слой с шестью нейронами имеет активации после ReLU: $a = (2{,}0;\ -0{,}0;\ 3{,}0;\ 0{,}5;\ 4{,}0;\ 1{,}0)$ (отрицательные значения уже обнулены самой функцией активации ReLU). Вероятность отключения $p=0{,}5$, сгенерированная на этом шаге маска: $m=(1,0,1,1,0,1)$.

Решение. Умножаем покоординатно: $\tilde a = m \odot a = (2{,}0\cdot1;\ 0{,}0\cdot0;\ 3{,}0\cdot1;\ 0{,}5\cdot1;\ 4{,}0\cdot0;\ 1{,}0\cdot1) = (2{,}0;\ 0;\ 3{,}0;\ 0{,}5;\ 0;\ 1{,}0)$. Нейроны 2 и 5 полностью обнулены на этом шаге, независимо от того, какими были их значения до применения маски.

Ответ: прореженная активация $\tilde a = (2{,}0;\ 0;\ 3{,}0;\ 0{,}5;\ 0;\ 1{,}0)$; на следующем мини-батче маска будет сгенерирована заново, и, скорее всего, отключится уже другая пара нейронов.

Пример 2 (обязательный, численная демонстрация inverted dropout): почему нужно масштабировать активации. Возьмём тот же слой из шести нейронов с активациями $a = (2{,}0;\ -1{,}5;\ 3{,}0;\ 0{,}5;\ -2{,}0;\ 1{,}0)$ (до применения ReLU, чтобы числа были показательнее), вероятность отключения $p=0{,}5$, то есть вероятность сохранения $q=1-p=0{,}5$. Сгенерирована маска $m=(1,0,1,1,0,1)$, как в примере 1.

Решение. Наивный dropout без компенсации: $\tilde a_{\text{train}} = m \odot a = (2{,}0;\ 0;\ 3{,}0;\ 0{,}5;\ 0;\ 1{,}0)$, сумма координат $= 6{,}5$. Если посчитать математическое ожидание такой прореженной активации по всем возможным маскам, то для каждой координаты $\mathbb{E}[m_i \cdot a_i] = q\cdot a_i = 0{,}5\cdot a_i$ — то есть в среднем по всем шагам обучения сигнал систематически уменьшен вдвое по сравнению с исходными активациями $a$. Сумма исходных координат $a$: $2{,}0-1{,}5+3{,}0+0{,}5-2{,}0+1{,}0=3{,}0$, а её ожидаемое значение после наивного dropout — $0{,}5\cdot3{,}0=1{,}5$, что не совпадает с суммой активаций полной сети $a$ на инференсе (где dropout выключен и используются все шесть нейронов без изменений).

Inverted dropout (стандартная практика): сразу после применения маски результат делится на вероятность сохранения $q$: $\tilde a_{\text{train}}^{\text{inv}} = \dfrac{m \odot a}{q} = \dfrac{(2{,}0;\ 0;\ 3{,}0;\ 0{,}5;\ 0;\ 1{,}0)}{0{,}5} = (4{,}0;\ 0;\ 6{,}0;\ 1{,}0;\ 0;\ 2{,}0)$. Теперь для каждой координаты $\mathbb{E}\!\left[\dfrac{m_i\cdot a_i}{q}\right] = \dfrac{q\cdot a_i}{q} = a_i$ — математическое ожидание прореженной, но масштабированной активации в точности равно исходному значению $a_i$, без каких-либо систематических искажений.

Ответ: при inverted dropout ожидаемое значение активации на каждом шаге обучения совпадает с активацией полной сети — значит, на инференсе достаточно просто выключить маску и использовать сеть как есть, без всякого пересчёта весов; на этом и основана стандартная реализация torch.nn.Dropout(p=0.5), где model.train() включает случайное маскирование с делением на $q$, а model.eval() отключает и то, и другое.

Пример 3 (сложный): комбинаторика подсетей и связь с формулой снижения дисперсии из урока 317. Слой из $n=10$ нейронов с $p=0{,}5$.

Решение. Число различных бинарных масок, а значит и число различных «подсетей», которые теоретически может породить dropout на этом слое, равно $2^{10}=1024$. Каждая конкретная маска реализуется с вероятностью $0{,}5^{10}\approx0{,}00098$ — все подсети равновероятны при $p=0{,}5$, но при $p\ne0{,}5$ распределение по числу оставшихся нейронов становится биномиальным: ожидаемое число сохранённых нейронов равно $nq$, а его дисперсия — $npq$. При $p=0{,}5$, $n=10$: ожидаемое число сохранённых нейронов $=5$, дисперсия $=10\cdot0{,}5\cdot0{,}5=2{,}5$.

Ответ: даже для небольшого слоя из 10 нейронов dropout порождает больше тысячи различных архитектурных вариантов сети, обучаемых на разных шагах, — а для реалистичного слоя из нескольких сотен или тысяч нейронов число подсетей становится настолько огромным, что ни один explicit-ансамбль (вроде случайного леса из урока 317, где число деревьев редко превышает несколько тысяч) не приближается к этому масштабу; расплатой за это служит то, что все подсети делят один и тот же набор весов, а не обучаются полностью независимо.

Почему это важно

Dropout решает ту же задачу, что и бэггинг в случайном лесе — снижение дисперсии предсказания за счёт усреднения по многим разнообразным «версиям» модели, — но делает это способом, специфичным именно для нейросетей: не через явное обучение отдельных моделей, а через управляемую случайность внутри одной и той же сети с общими весами. Это позволяет получить эффект, близкий к ансамблированию, практически бесплатно с точки зрения памяти и почти бесплатно с точки зрения вычислений — не нужно хранить и обучать тысячи отдельных наборов параметров, как пришлось бы при честном явном ансамблировании тысяч независимых сетей. Понимание dropout именно как приближённого ансамблирования — а не просто как «трюка, который почему-то работает» — объясняет и то, почему разные архитектуры выигрывают от разного $p$, и то, почему dropout особенно эффективен именно в широких, избыточных слоях с большим числом нейронов, где действительно есть из чего строить разнообразие.


L1/L2-регуляризация весов нейросети

Интуиция

В уроке 312 ты разбирал, как Ridge и Lasso добавляют к функции потерь линейной регрессии штраф за величину весов — $\lambda\sum w_i^2$ для Ridge, $\lambda\sum|w_i|$ для Lasso, — заставляя модель предпочитать решения с маленькими коэффициентами среди всех решений с одинаковой ошибкой на обучении. Ровно та же идея переносится на нейросеть почти без изменений: у сети тоже есть веса — на этот раз не один вектор коэффициентов, а набор весовых матриц $W_1, W_2, \dots, W_L$, по одной на каждый слой, — и к суммарной функции потерь можно добавить штраф за их величину. Интуиция сохраняется полностью: без ограничения сверху веса нейросети, обучаемой градиентным спуском достаточно долго, склонны разрастаться, подстраиваясь под мельчайшие детали обучающей выборки, — регуляризация весов не даёт им это делать бесконтрольно.

Определение

Определение (L1/L2-регуляризация весов нейросети): Для сети с весовыми матрицами слоёв $W_1,\dots,W_L$ и функцией потерь на данных $L_{\text{data}}(W_1,\dots,W_L)$ регуляризованная функция потерь имеет вид $L(W) = L_{\text{data}}(W) + \lambda\sum_{l=1}^{L}\|W_l\|_2^2$ (L2, часто называемая weight decay) или $L(W) = L_{\text{data}}(W) + \lambda\sum_{l=1}^{L}\|W_l\|_1$ (L1), где $\|W_l\|_2^2 = \sum_{i,j}(W_l)_{ij}^2$ и $\|W_l\|_1=\sum_{i,j}|(W_l)_{ij}|$ — суммы квадратов и модулей всех элементов весовой матрицы слоя $l$ соответственно, а $\lambda\ge0$ — общий или, реже, индивидуальный для каждого слоя коэффициент силы регуляризации. Смещения (biases) обычно не регуляризуются.

Принципиальное отличие от Ridge-регрессии урока 312: там задача была выпуклой и квадратичной, и градиент по весам приравнивался к нулю аналитически, что давало закрытую формулу $w_{\text{Ridge}}=(X^\top X+\lambda I)^{-1}X^\top y$. Функция потерь глубокой сети — невыпуклая и нелинейная из-за композиции слоёв с нелинейными активациями, и никакой аналог этой формулы не существует. Единственный доступный путь — итеративная минимизация градиентным спуском (или его вариантами вроде Adam), а регуляризация просто добавляет к каждому шагу дополнительное слагаемое в градиент: $\nabla_{W_l} L = \nabla_{W_l} L_{\text{data}} + 2\lambda W_l$ для L2.

Здесь важно отдельно оговорить нюанс, которого не было в контексте линейной регрессии: для простого градиентного спуска (SGD) добавление $2\lambda W_l$ к градиенту в точности эквивалентно классическому L2-штрафу в функции потерь. Но для адаптивных оптимизаторов вроде Adam эта эквивалентность нарушается — Adam масштабирует каждый параметр индивидуально по накопленной статистике вторых моментов градиента, и если добавить L2-штраф в градиент до этого масштабирования, эффективная сила регуляризации для разных весов получается разной и плохо предсказуемой. В 2017 году Илья Лошчилов и Франк Хуттер в статье «Decoupled Weight Decay Regularization» показали эту проблему явно и предложили AdamW — версию Adam, где weight decay применяется как отдельный шаг ($W_l \leftarrow W_l - \eta\lambda W_l$), не проходящий через адаптивное масштабирование Adam, а не как добавка к градиенту. Сегодня torch.optim.AdamW — фактический стандарт для обучения большинства современных архитектур именно из-за этого исправления.

Примеры

Пример 1 (простой): численный расчёт L2-штрафа для маленькой весовой матрицы. Слой имеет весовую матрицу $2\times2$: $W = \begin{pmatrix}1{,}5 & -0{,}5\\ 0{,}8 & -2{,}0\end{pmatrix}$, $\lambda=0{,}01$.

Решение. $\|W\|_2^2 = 1{,}5^2+(-0{,}5)^2+0{,}8^2+(-2{,}0)^2 = 2{,}25+0{,}25+0{,}64+4{,}0=7{,}14$. Вклад в функцию потерь: $\lambda\|W\|_2^2 = 0{,}01\cdot7{,}14=0{,}0714$.

Ответ: штраф за этот конкретный слой добавляет $0{,}0714$ к суммарной функции потерь — небольшая величина сама по себе, но её градиент влияет на каждый шаг обновления весов на протяжении всего обучения, накопительно удерживая веса от неограниченного роста.

Пример 2 (средний): один шаг градиентного спуска с weight decay против без него. Один конкретный вес $w=2{,}0$, градиент функции потерь по данным на этом шаге $\nabla_w L_{\text{data}} = 0{,}05$, скорость обучения $\eta=0{,}1$, коэффициент регуляризации $\lambda=0{,}01$.

Решение. Без регуляризации: $w_{\text{new}} = w - \eta\cdot\nabla_w L_{\text{data}} = 2{,}0 - 0{,}1\cdot0{,}05 = 2{,}0-0{,}005=1{,}995$. С L2/weight decay: $w_{\text{new}} = w-\eta\left(\nabla_w L_{\text{data}}+2\lambda w\right) = 2{,}0-0{,}1\left(0{,}05+2\cdot0{,}01\cdot2{,}0\right)=2{,}0-0{,}1\cdot(0{,}05+0{,}04)=2{,}0-0{,}1\cdot0{,}09=2{,}0-0{,}009=1{,}991$.

Ответ: за один шаг разница кажется незначительной ($1{,}995$ против $1{,}991$), но добавка $2\lambda w=0{,}04$ к градиенту пропорциональна самому весу — чем крупнее становится вес, тем сильнее его «тянет назад» регуляризация, и за тысячи шагов обучения это накопительное давление заметно ограничивает итоговую величину весов, точно так же как в уроке 312 Ridge асимптотически сжимал коэффициенты линейной модели к нулю при росте $\lambda$.

Пример 3 (сложный): L1-регуляризация весов и разреженность сети. Слой с весовой матрицей, где часть элементов после обучения с L1-штрафом ($\lambda\|W\|_1$) оказалась в точности равна нулю, а часть — сохранила заметные ненулевые значения, аналогично тому, как в уроке 312 Lasso точно обнулял коэффициенты слабых признаков через мягкое пороговое отображение $S_\lambda(v)=\text{sign}(v)\max(|v|-\lambda,0)$.

Решение. Тот же самый излом функции $|w|$ в нуле, из-за которого субградиентный спуск обнуляет слабые коэффициенты линейной модели в уроке 312, действует и здесь — покоординатно для каждого элемента весовой матрицы. На практике L1-регуляризация весов нейросети применяется реже, чем L2 или dropout, именно потому что цель у неё специфическая: не столько борьба с переобучением как таковая (с этим прекрасно справляются L2 и dropout), сколько явное разрежение сети — обнуление части весов для последующего структурного прунинга (structured pruning) и сжатия модели перед развёртыванием на устройствах с ограниченными ресурсами.

Ответ: L1-регуляризация переносит на веса нейросети ту же способность к точному обнулению, что Lasso демонстрировал для коэффициентов линейной регрессии в уроке 312, но на практике в глубоких сетях эта способность чаще используется целенаправленно — для сжатия модели, — тогда как для «обычной» борьбы с переобучением подавляющее большинство архитектур по умолчанию использует L2/weight decay и dropout.

Почему это важно

L1/L2-регуляризация весов — самый прямой мостик между классическим ML и глубоким обучением: одна и та же математическая идея, один и тот же штраф за величину параметров, применяются буквально к тем же формулам, что и в уроке 312, только теперь весовых матриц несколько, а функция потерь, которую они регуляризуют, нелинейна и невыпукла. Понимание этой прямой связи избавляет от необходимости учить L2-регуляризацию нейросетей как что-то новое: это в точности Ridge, примененный к каждому слою, с единственной практически важной оговоркой — для адаптивных оптимизаторов вроде Adam нужно использовать decoupled weight decay (AdamW), а не наивное добавление L2-штрафа в функцию потерь, чтобы регуляризация работала так, как задумывалась.


Early stopping и аугментация данных

Ранняя остановка: интуиция

Вернись мысленно к графику из урока 304: train loss монотонно убывает на протяжении всего обучения, а validation loss сначала убывает вместе с ним, достигает минимума где-то в середине обучения, а затем начинает расти, хотя train loss продолжает падать. Early stopping — предельно прямолинейный ответ на эту картину: раз момент, когда модель начинает переобучаться, виден прямо на графике validation loss, почему бы не остановить обучение именно в этот момент, вместо того чтобы продолжать его до заранее заданного числа эпох? Это не изменение функции потерь и не изменение архитектуры — это управление самим процессом обучения, и именно поэтому early stopping часто называют самым дешёвым способом регуляризации: он не требует ни новых гиперпараметров вроде $p$ у dropout или $\lambda$ у weight decay (кроме параметра терпения, patience, о котором ниже), ни дополнительных вычислений на каждом шаге.

Ранняя остановка: определение

Определение (early stopping, ранняя остановка): После каждой эпохи (или через фиксированное число шагов) обучения модель оценивается на отложенной валидационной выборке, и текущее значение validation loss (или другой отслеживаемой метрики) сравнивается с наилучшим значением, достигнутым до сих пор. Если validation loss не улучшается на протяжении заданного числа эпох подряд — параметра терпения (patience) — обучение останавливается, и в качестве итоговой модели используются веса, соответствующие эпохе с наилучшим (наименьшим) значением validation loss, а не веса последней эпохи.

Ранняя остановка: примеры

Пример 1 (простой): чтение таблицы validation loss и применение правила patience. Обучение логируется по эпохам:

Эпоха 1 2 3 4 5 6 7 8
val loss 0,82 0,61 0,49 0,45 0,47 0,46 0,48 0,50

Patience $=3$ (обучение останавливается, если 3 эпохи подряд нет улучшения относительно лучшего значения).

Решение. Лучшее значение val loss $=0{,}45$ достигнуто на эпохе 4. Эпохи 5, 6, 7 подряд не улучшают этот минимум ($0{,}47$, $0{,}46$, $0{,}48$ — все хуже $0{,}45$) — это ровно 3 эпохи без улучшения, значит на эпохе 7 срабатывает критерий остановки.

Ответ: обучение останавливается после эпохи 7, но в качестве итоговой модели сохраняются веса, зафиксированные на эпохе 4 (наилучший val loss $=0{,}45$), а не веса эпохи 7 — иначе весь смысл ранней остановки терялся бы.

Пример 2 (средний): выбор patience — компромисс между риском. Малое patience (например, $1$) останавливает обучение при первом же ухудшении val loss; большое patience (например, $20$) позволяет обучению пройти через длинные «плато» или временные ухудшения прежде, чем остановиться.

Решение. Слишком маленькое patience рискует остановить обучение преждевременно, приняв обычный шум измерения val loss на одном мини-батче валидации (или временную немонотонность траектории оптимизации) за начало устойчивого переобучения, — и тогда модель недообучится, не успев выучить всё, что могла. Слишком большое patience, наоборот, позволяет модели переобучаться значительное число эпох после истинного оптимума, прежде чем сработает остановка, — теряется большая часть выгоды от техники. На практике patience обычно выбирают в диапазоне от 5 до 20 эпох в зависимости от того, насколько шумной выглядит кривая val loss конкретной задачи.

Ответ: patience — это тоже гиперпараметр, требующий подбора, а не универсальная константа; типичный диапазон 5–20 эпох — разумная отправная точка, которую стоит скорректировать по форме конкретной кривой обучения.

Пример 3 (сложный): практическая реализация — сохранение чекпоинта лучшей модели. В PyTorch ранняя остановка не встроена как единая функция (в отличие от Keras, где есть готовый EarlyStopping callback), поэтому её реализуют вручную, отслеживая лучшее значение val loss и сохраняя чекпоинт весов при каждом улучшении.

best_val_loss = float("inf")
patience, patience_counter = 5, 0

for epoch in range(max_epochs):
    train_one_epoch(model, train_loader, optimizer)
    val_loss = evaluate(model, val_loader)

    if val_loss < best_val_loss:
        best_val_loss = val_loss
        patience_counter = 0
        torch.save(model.state_dict(), "best_model.pt")   # чекпоинт лучшей модели
    else:
        patience_counter += 1
        if patience_counter >= patience:
            print(f"Ранняя остановка на эпохе {epoch}")
            break

model.load_state_dict(torch.load("best_model.pt"))  # возвращаем лучшие веса

Решение. Код на каждой эпохе явно сравнивает текущий val loss с лучшим на данный момент, сбрасывает счётчик терпения при улучшении и увеличивает его при отсутствии улучшения; при достижении лимита patience цикл обучения прерывается через break, а после цикла явно загружаются веса лучшего чекпоинта, а не веса последней (возможно, уже переобученной) эпохи.

Ответ: несмотря на отсутствие единой встроенной функции в PyTorch, ранняя остановка реализуется буквально пятью-шестью строчками кода поверх обычного цикла обучения — минимальная цена за один из самых надёжных способов регуляризации.

Ранняя остановка: почему это важно

Early stopping напрямую замыкает круг с уроком 304: там график расхождения train и validation loss был диагностическим инструментом, показывающим факт переобучения постфактум, — здесь тот же самый график используется как активный управляющий сигнал прямо во время обучения. Более того, ранняя остановка полезна не только сама по себе, но и как страховка при использовании других приёмов регуляризации: если dropout или weight decay подобраны неидеально, early stopping всё равно не даст обучению зайти слишком далеко за точку оптимального баланса между bias и variance, действуя как последний рубеж защиты почти в каждом реальном цикле обучения.

Аугментация данных: интуиция

Все рассмотренные выше приёмы — dropout, weight decay, early stopping — работают, ограничивая или направляя процесс обучения при фиксированной обучающей выборке. Аугментация данных (data augmentation) заходит с другой стороны: вместо того чтобы ограничивать модель, она увеличивает эффективный объём и разнообразие самих данных, искусственно создавая новые обучающие примеры из уже имеющихся с помощью преобразований, которые не меняют «истинную» метку объекта. Изображение кота, повёрнутое на пять градусов, отражённое по горизонтали или немного обрезанное по краю, остаётся изображением кота — но с точки зрения пиксельных значений это уже новый, отдельный обучающий пример, которого не было в исходном датасете.

Аугментация данных: определение

Определение (аугментация данных, data augmentation): Аугментация данных — это техника искусственного увеличения эффективного размера и разнообразия обучающей выборки за счёт применения к исходным примерам преобразований, которые сохраняют семантическую метку объекта, но изменяют его конкретное представление в данных. Для изображений типичные преобразования — повороты, горизонтальные и вертикальные отражения, обрезка (cropping), изменение яркости и контраста, добавление шума; аугментация действует как регуляризатор, потому что не позволяет модели запомнить конкретные пиксельные значения обучающих примеров — при каждой эпохе она видит слегка изменённую версию каждого изображения.

Аугментация данных: примеры

Пример 1 (простой): базовый набор аугментаций для изображений в PyTorch.

from torchvision import transforms

train_transform = transforms.Compose([
    transforms.RandomHorizontalFlip(p=0.5),
    transforms.RandomRotation(degrees=15),
    transforms.RandomCrop(32, padding=4),
    transforms.ToTensor(),
])

Решение. Каждый вызов train_transform на одном и том же исходном изображении, скорее всего, вернёт разный результат: с вероятностью $0{,}5$ изображение отразится по горизонтали, дополнительно повернётся на случайный угол в диапазоне $\pm15°$ и будет обрезано со случайным сдвигом. За $N$ эпох обучения сеть эффективно увидит не $N$ одинаковых копий каждого изображения, а $N$ разных его вариаций.

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

Пример 2 (средний): аугментация не заменяет, а дополняет dropout и weight decay. Модель обучена тремя способами на одном датасете: (а) без какой-либо регуляризации, (б) только с аугментацией данных, (в) с аугментацией плюс dropout и weight decay.

Решение. Аугментация борется с переобучением, увеличивая разнообразие входных данных, а dropout и weight decay — ограничивая способность самой сети запоминать детали, независимо от того, насколько разнообразны эти данные. Это разные, взаимно дополняющие механизмы: аугментация не мешает сети иметь избыточную ёмкость (она просто даёт ей больше материала, чтобы эту ёмкость использовать для реальной закономерности, а не для шума), а dropout напрямую ограничивает эту ёмкость независимо от объёма данных. На практике комбинация (в) почти всегда показывает лучшую обобщающую способность, чем любая из техник по отдельности.

Ответ: аугментация данных и регуляризация архитектуры (dropout, weight decay) решают смежные, но разные задачи и в подавляющем большинстве реальных пайплайнов применяются вместе, а не как взаимозаменяемые альтернативы.

Пример 3 (сложный): аугментация должна сохранять метку — иначе она вредит, а не помогает. При обучении классификатора рукописных цифр случайно применили RandomRotation(degrees=180) и RandomHorizontalFlip без ограничений.

Решение. Поворот на угол до 180 градусов и свободное горизонтальное отражение способны превратить цифру «6» в подобие цифры «9» (поворот на 180°) или исказить асимметричные цифры вроде «2» и «5» до неузнаваемости. В этом случае аугментация нарушает собственное определение — преобразование перестаёт сохранять истинную метку объекта, и модель обучается на систематически неверных парах «изображение — метка», что не регуляризует, а прямо портит качество.

Ответ: выбор конкретных аугментаций — не универсальный чек-лист, а решение, зависящее от домена задачи: то, что работает для естественных фотографий (повороты на небольшой угол, отражения, изменение яркости), может быть разрушительным для рукописного текста или показаний приборов, где ориентация и точная форма несут смысл; этот нюанс подробнее разбирается в блоке курса про свёрточные сети, где аугментация — один из центральных практических инструментов.

Аугментация данных: почему это важно

Аугментация данных — единственная техника этого урока, которая борется с переобучением не через ограничение модели, а через расширение эффективного объёма данных, и именно поэтому она особенно ценна в задачах, где размеченных данных объективно мало, а собрать больше — дорого или невозможно (медицинские изображения, специализированные промышленные датасеты). В сочетании с dropout, weight decay и early stopping она формирует полный практический арсенал: одни техники ограничивают модель, другая — расширяет данные, и вместе они решают проблему переобучения нейросетей с разных сторон одновременно.


Практика: 30 заданий

Базовые (задания 1–10)

Задание 1: Полносвязный слой $256\to128$. Посчитай число обучаемых параметров (веса плюс смещения).


Задание 2: Слой из 8 нейронов, dropout с $p=0{,}25$ (вероятность отключения). Сколько нейронов сохранится в среднем (по математическому ожиданию)?


Задание 3: Активация нейрона до dropout: $a=4{,}0$. Маска сохраняет этот нейрон ($m=1$), вероятность сохранения $q=0{,}5$. Найди значение после inverted dropout.


Задание 4: Слой из 4 нейронов с активациями $a=(1{,}0;\ 2{,}0;\ 3{,}0;\ 4{,}0)$, маска $m=(1,0,1,0)$, $q=0{,}5$. Найди прореженную активацию при обычном (не inverted) dropout и при inverted dropout.


Задание 5: Весовая матрица слоя $1\times3$: $W=(2{,}0;\ -1{,}0;\ 0{,}5)$, $\lambda=0{,}1$. Найди значение L2-штрафа $\lambda\|W\|_2^2$.


Задание 6: Для того же вектора $W=(2{,}0;\ -1{,}0;\ 0{,}5)$ найди значение L1-штрафа $\lambda\|W\|_1$ при $\lambda=0{,}1$.


Задание 7: Таблица val loss по эпохам: $1{,}0;\ 0{,}7;\ 0{,}5;\ 0{,}52;\ 0{,}49;\ 0{,}51;\ 0{,}53$ (эпохи 1–7). Patience $=2$. На какой эпохе сработает ранняя остановка и какая модель будет сохранена?


Задание 8: Перечисли параметры torch.nn.Dropout и torch.optim.AdamW, отвечающие за: (а) вероятность отключения нейрона, (б) силу weight decay.


Задание 9: Слой из 5 нейронов. Сколько различных бинарных масок (подсетей) теоретически может сгенерировать dropout на этом слое?


Задание 10: Объясни своими словами, почему на инференсе dropout отключается, а не применяется так же, как на обучении.


Средние (задания 11–20)

Задание 11: Полносвязная сеть $784\to256\to64\to10$. Посчитай общее число параметров.


Задание 12: Слой из 4 нейронов, $p=0{,}5$, вероятность сохранения $q=0{,}5$. Найди дисперсию числа сохранённых нейронов (биномиальное распределение).


Задание 13: Активации слоя $a=(3{,}0;\ -2{,}0;\ 1{,}0;\ 4{,}0;\ -1{,}0)$, маска $m=(1,1,0,1,0)$, $q=0{,}6$ (вероятность сохранения). Найди активацию после inverted dropout.


Задание 14: Вес $w=1{,}5$, градиент по данным $\nabla_w L_{\text{data}}=0{,}1$, $\eta=0{,}05$, $\lambda=0{,}02$. Найди $w_{\text{new}}$ с L2-регуляризацией (weight decay), добавленной прямо в градиент.


Задание 15: Для того же примера (задание 14) найди $w_{\text{new}}$ без регуляризации и сравни величину «лишнего» сдвига, вызванного weight decay.


Задание 16: Val loss по эпохам: $0{,}9;\ 0{,}6;\ 0{,}4;\ 0{,}38;\ 0{,}39;\ 0{,}40;\ 0{,}37;\ 0{,}41;\ 0{,}42$ (эпохи 1–9). Patience $=2$. Определи, на какой эпохе сработает остановка, и обрати внимание на «ловушку» — временное ухудшение перед новым улучшением.


Задание 17: Объясни, почему для оптимизатора Adam наивное добавление L2-штрафа в градиент даёт непредсказуемую силу регуляризации для разных весов, а AdamW это исправляет.


Задание 18: Слой из 1000 нейронов, $p=0{,}3$ (вероятность отключения). Найди ожидаемое число сохранённых нейронов и стандартное отклонение этого числа.


Задание 19: Датасет из 5000 изображений. Применили аугментацию: горизонтальное отражение с вероятностью $0{,}5$, поворот на случайный угол из диапазона $\pm10°$ с вероятностью $1{,}0$ (то есть всегда применяется). Сеть обучается 50 эпох. Оцени, сколько «эффективно разных» вариантов изображений увидит сеть за всё обучение (без учёта конечной точности представления пикселей).


Задание 20: Объясни, почему аугментация данных и dropout не взаимозаменяемы, приведя конкретный сценарий, где помогает только одна из этих техник.


Продвинутые (задания 21–30)

Задание 21: Выведи, чему равно математическое ожидание прореженной активации при inverted dropout $\mathbb{E}\left[\dfrac{m\cdot a}{q}\right]$, где $m\sim\text{Bernoulli}(q)$ и $a$ — фиксированное (не случайное) значение активации.


Задание 22: Для обычного (не inverted) dropout правило Хинтона на инференсе — умножать веса (или активации) слоя на $q$. Покажи, что это даёт то же математическое ожидание, что и обучение с обычным dropout.


Задание 23: Слой из $n$ нейронов, dropout с вероятностью отключения $p$. При каком значении $p$ дисперсия числа сохранённых нейронов $np(1-p)$ максимальна? Обоснуй через производную.


Задание 24: Weight decay реализован двумя способами: (а) как слагаемое $\lambda\|W\|_2^2$ в функции потерь при использовании обычного SGD, (б) как отдельный шаг $W\leftarrow W-\eta\lambda W$ при AdamW. Покажи, что для чистого SGD (без адаптивного масштабирования) эти два способа дают идентичное обновление весов.


Задание 25: Две сети обучены с одинаковой архитектурой и данными: сеть А — с dropout $p=0{,}5$ на всех скрытых слоях, сеть Б — вообще без dropout, но с очень сильным weight decay ($\lambda=1{,}0$). Обе показывают низкий train accuracy. Предложи диагностическую гипотезу для каждой сети.


Задание 26: Сравни формулу снижения дисперсии ансамбля случайного леса $\mathbb{D}\bar f=\rho\sigma^2+(1-\rho)\sigma^2/B$ (урок 317) с ситуацией dropout. Почему эту формулу нельзя применить к dropout напрямую в неизменном виде?


Задание 27: Объясни, почему dropout обычно не применяют (или применяют с намного меньшим $p$) к самому первому (входному) слою сети и к самому последнему (выходному) слою перед функцией потерь.


Задание 28: Постройка численного примера: слой с 3 нейронами обучается 4 шага подряд с $p=1/3$ (вероятность отключения). На каждом шаге сгенерированы маски: шаг 1 — $(1,1,0)$, шаг 2 — $(1,0,1)$, шаг 3 — $(0,1,1)$, шаг 4 — $(1,1,1)$. Посчитай эмпирическую долю шагов, на которых каждый конкретный нейрон был сохранён, и сравни с теоретической вероятностью сохранения $q$.


Задание 29: Сеть обучена с комбинацией dropout ($p=0{,}3$) и L2-регуляризации весов ($\lambda=10^{-4}$) одновременно. Объясни, почему такая комбинация обычно не считается избыточной, в отличие от одновременного применения сразу нескольких очень сильных регуляризаторов.


Задание 30: Сформулируй, почему ранняя остановка (early stopping) остаётся полезной даже в сети, уже использующей dropout, weight decay и аугментацию данных одновременно.


Частые ошибки

Забывать переключать сеть в режим инференса перед оценкой качества модели — вызов model.eval() в PyTorch отключает dropout (и переключает BatchNorm на накопленные статистики, урок 332). Если оставить сеть в режиме model.train() при валидации или инференсе, dropout продолжит случайно обнулять нейроны, и предсказания станут случайными и заниженного качества — а метрика val accuracy окажется искусственно и непредсказуемо хуже реальной.

Использовать одинаковое значение $p$ для всех слоёв без разбора их размера и роли. Крупные полносвязные слои с сотнями или тысячами нейронов действительно выигрывают от классического $p=0{,}5$, но небольшие слои, узкие «бутылочные горлышки» архитектуры или входной слой требуют существенно меньшего $p$ (часто $0{,}1$–$0{,}2$) или вовсе обходятся без dropout — иначе легко перейти от регуляризации к недообучению.

Применять наивный (не inverted) dropout и забывать про компенсацию масштаба на инференсе. Если реализовать маскирование вручную без деления на $q$ на обучении и без соответствующего умножения весов на $q$ при инференсе, среднее значение активаций окажется систематически смещено между обучением и инференсом, и качество модели на новых данных резко упадёт без какой-либо очевидной причины в логах обучения.

Игнорировать взаимодействие dropout и batch normalization. Как уже отмечалось в уроке 332, порядок и совместное использование этих техник требует аккуратности: dropout, применённый непосредственно перед BatchNorm, меняет статистику активаций внутри батча случайным образом на каждом шаге, что вступает в противоречие с идеей BatchNorm стабилизировать эту статистику — на практике многие современные архитектуры либо разносят их по разным частям сети, либо полагаются преимущественно на один из двух механизмов.

Не регуляризовать смещения (biases) наравне с весами при использовании weight decay. Слепое применение weight_decay ко всем параметрам модели, включая смещения и параметры $\gamma,\beta$ слоёв BatchNorm, часто ухудшает качество: смещения и параметры нормализации, как правило, не являются источником переобучения в том же смысле, что весовые матрицы, и их излишнее стягивание к нулю ограничивает полезную гибкость сети без необходимости — большинство современных реализаций (включая PyTorch с явной настройкой групп параметров) сознательно исключают bias и параметры нормализации из weight decay.

Подбирать patience для early stopping «на глаз», один раз, без учёта шумности конкретной задачи. Слишком маленькое patience на шумной кривой val loss (типично для маленьких валидационных выборок или задач с высокой дисперсией метрики) приводит к массовым преждевременным остановкам ещё до выхода на настоящий оптимум, а слишком большое — сводит на нет всю пользу техники.

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


Главное запомнить

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

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

Интуитивно dropout обучает экспоненциально много ($2^n$ для слоя из $n$ нейронов) «прореженных» подсетей с общими весами одновременно — прямая параллель с бэггингом в случайном лесе (урок 317), но с принципиальным отличием: подсети dropout делят параметры, а деревья случайного леса обучаются полностью независимо.

Inverted dropout делит активации на вероятность сохранения $q=1-p$ прямо на обучении, что делает математическое ожидание активации равным исходному значению и позволяет использовать полную, немасштабированную сеть на инференсе без дополнительного пересчёта весов — это и есть современный стандарт, реализованный в torch.nn.Dropout.

L1/L2-регуляризация весов нейросети — прямое продолжение Ridge и Lasso из урока 312, применённое к весовой матрице каждого слоя вместо коэффициентов линейной модели; в отличие от Ridge, для нелинейной сети не существует аналитической закрытой формулы, регуляризация действует через добавку к градиенту на каждом шаге.

Для адаптивных оптимизаторов (Adam) наивный L2-штраф в функции потерь даёт непредсказуемую силу регуляризации из-за адаптивного масштабирования шага; decoupled weight decay в AdamW исправляет это, применяя штраф отдельным шагом.

Early stopping останавливает обучение, когда validation loss перестаёт улучшаться в течение заданного числа эпох (patience), и сохраняет веса эпохи с наилучшим val loss — прямое практическое применение диагностического графика переобучения из урока 304.

Аугментация данных увеличивает эффективный объём и разнообразие обучающей выборки через преобразования, сохраняющие метку объекта, — это единственная из рассмотренных техник, которая борется с переобучением через расширение данных, а не через ограничение модели.

Dropout, weight decay, early stopping и аугментация данных — не взаимозаменяемые альтернативы, а взаимно дополняющие механизмы, атакующие переобучение с разных сторон одновременно, и в реальных пайплайнах почти всегда используются в комбинации, а не по отдельности.


Связь с темами курса

Урок 304 (переобучение и недообучение) — прямой фундамент всего сегодняшнего урока. Там ты впервые увидел график расхождения train и validation loss и разложение ошибки на bias² + variance + irreducible error. Всё, что разобрано сегодня, — конкретные, специализированные для нейросетей ответы на ту же самую проблему: dropout и weight decay напрямую атакуют высокую дисперсию (variance) модели, снижая её эффективную ёмкость; early stopping использует тот самый график validation loss из урока 304 не как пассивную диагностику постфактум, а как активный управляющий сигнал прямо во время обучения, останавливая процесс ровно в точке минимума этого графика.

Урок 312 (Ridge, Lasso) — источник математического аппарата L1/L2-регуляризации, перенесённого сегодня на веса слоёв нейросети почти без изменений: тот же штраф $\lambda\sum w_i^2$ или $\lambda\sum|w_i|$, та же логика сжатия весов к нулю, то же принципиальное отличие L1 (точное обнуление) от L2 (асимптотическое сжатие без точного нуля). Единственное существенное отличие — отсутствие закрытой аналитической формулы из-за нелинейности сети, и появление отдельного практического нюанса — decoupled weight decay для адаптивных оптимизаторов, которого не существовало в контексте простой линейной регрессии.

Урок 317 (Random Forest) — источник самой глубокой концептуальной параллели сегодняшнего урока. Бэггинг в случайном лесе создаёт разнообразие моделей через случайность данных (bootstrap-выборка) и случайность признаков на каждом узле; dropout создаёт разнообразие «подсетей» через случайность архитектуры на каждом шаге обучения. В обоих случаях цель одна — снизить дисперсию итогового предсказания за счёт усреднения по многим слабо скоррелированным версиям модели, — но техническая реализация принципиально разная: деревья случайного леса полностью независимы и не делят параметры, тогда как подсети dropout делят один и тот же набор весов слоя, что делает dropout вычислительно значительно дешевле честного ансамблирования, но не позволяет напрямую применить формулу снижения дисперсии $\rho\sigma^2+(1-\rho)\sigma^2/B$ из урока 317 в неизменном виде.

Уроки 330–332 (backpropagation, инициализация весов, batch normalization) — вместе с сегодняшним уроком формируют цельную практическую картину того, как реально обучается глубокая сеть: backpropagation считает градиенты, правильная инициализация не даёт им затухнуть или взорваться в первые шаги, batch normalization стабилизирует распределение активаций слой за слоем, а dropout и регуляризация весов не дают сети, однажды обучившейся стабильно, скатиться в переобучение по мере того, как обучение продолжается достаточно долго, чтобы выучить данные наизусть.


Интересные факты

Dropout был официально запатентован Google в США (патент US9406017B2) — редкий случай, когда алгоритмический приём регуляризации нейросетей получил патентную защиту; это не помешало свободной реализации dropout во всех крупных открытых фреймворках глубокого обучения.

В оригинальной статье 2014 года Шриниваса и соавторов dropout с $p=0{,}5$ на скрытых слоях в сочетании с dropout $p=0{,}2$ на входном слое на нескольких эталонных датасетах (MNIST, CIFAR-10, ImageNet того времени) снижал ошибку тестирования на несколько процентных пунктов по сравнению с идентичными архитектурами без dropout — впечатляющий результат для метода, реализация которого укладывается в пару строк кода.

Существует вариант DropConnect (Ван и др., 2013), в котором вместо целых нейронов случайно обнуляются отдельные связи (веса) между нейронами, а не активации целиком — более тонкая версия той же идеи, формально более общая, чем dropout (dropout эквивалентен DropConnect, если обнулять сразу все входящие связи конкретного нейрона одновременно), но на практике сложнее в эффективной реализации и не вытеснившая обычный dropout в массовом применении.

С распространением batch normalization (урок 332) и архитектур с residual-связями роль dropout в самых крупных современных сетях частично сместилась: многие state-of-the-art свёрточные архитектуры используют его умеренно или точечно, полагаясь на другие источники регуляризации (сама нормализация, аугментация данных, ранняя остановка), тогда как в трансформерах dropout сохраняет важную роль — он применяется, в частности, внутри блоков внимания (attention dropout) и после полносвязных подслоёв, оставаясь стандартным компонентом архитектур вроде исходного Transformer из статьи «Attention Is All You Need» (2017).


Лайфхаки

Начинай с $p=0{,}5$ для крупных полносвязных слоёв как с разумного значения по умолчанию из оригинальной статьи, но обязательно проверяй кривые train/val loss после первых экспериментов — если train accuracy подозрительно низкий и не растёт, вероятно, $p$ слишком велик для этого конкретного слоя.

Не применяй dropout бездумно ко всем слоям подряд — начни с самых широких и избыточных слоёв (обычно ближе к выходу полносвязной части сети), где риск переобучения и избыточность нейронов выше всего, и добавляй dropout к остальным слоям только если проблема переобучения сохраняется.

Используй torch.optim.AdamW вместо связки Adam плюс ручной L2-штраф в функции потерь — decoupled weight decay даёт более предсказуемый и управляемый эффект регуляризации, особенно на длинных циклах обучения.

Отделяй параметры, которые должны регуляризоваться weight decay, от тех, что не должны (смещения, параметры BatchNorm), через явное разделение на группы параметров в оптимизаторе — большинство современных обучающих циклов делают это как норму, а не как опциональную тонкую настройку.

Реализуй early stopping с сохранением чекпоинта лучшей модели буквально в первом же учебном цикле обучения, а не как «улучшение на потом» — цена реализации пренебрежимо мала (несколько строк кода), а выгода — почти гарантированная страховка от переобучения при любом другом наборе гиперпараметров.

Подбирай силу разных регуляризаторов (dropout $p$, weight decay $\lambda$, интенсивность аугментации) совместно через кросс-валидацию или отдельную валидационную выборку (уроки 305–306), а не по одной технике за раз в изоляции — их совокупный эффект нелинеен, и оптимальная комбинация редко совпадает с суммой независимо подобранных «лучших» значений.

Проверяй симптом переизбытка регуляризации так же внимательно, как симптом переобучения: если train loss не опускается ниже разумного уровня даже на долгом обучении, в первую очередь подозревай слишком агрессивные dropout или weight decay, а не спеши усложнять архитектуру.


Регуляризация нейросетей — это ровно то место, где абстрактная математика курса встречается с ежедневной практикой инженера по машинному обучению: формула soft thresholding из урока про Lasso, формула снижения дисперсии из урока про случайный лес, диагностический график переобучения из урока 304 — всё это сегодня собралось в один рабочий набор инструментов, без которого не обходится практически ни один реальный проект. Освоив dropout, weight decay, early stopping и аугментацию данных не как разрозненные трюки, а как взаимно дополняющие ответы на одну и ту же фундаментальную проблему избыточной ёмкости модели, ты готов к следующему шагу — разбору конкретных архитектур нейронных сетей, где все эти приёмы регуляризации будут применяться уже не в вакууме, а в контексте реальных, проверенных временем решений.

Понял тему? Закрепи в боте! 🚀

Попрактикуйся на задачах и получи персональные рекомендации от AI

💪 Начать тренировку
💬 Есть вопрос? Спроси бота!