Машинное обучение
Функции активации
В 2012 году команда Джеффри Хинтона победила на соревновании ImageNet, опередив ближайшего конкурента на 10 процентных пунктов. Мир увидел, что нейронные сети способны на прорыв. Одним из ключевых решений в архитектуре AlexNet была замена всего одной функции - вместо sigmoid в скрытых слоях использовали ReLU. Три символа в коде: max(0, x). Эта крошечная замена ускорила обучение в 6 раз и позволила тренировать по-настоящему глубокие сети. Выбор функции активации может превратить неработающую сеть в прорывную. А неправильный выбор может убить градиенты, "заморозить" нейроны или просто не дать модели обучиться. Сегодня мы разберём, почему одна математическая функция может решить судьбу всей нейронной сети.
- **Распознавание изображений** - замена sigmoid на ReLU в AlexNet (2012) ускорила обучение в 6 раз и сделала возможным тренировку глубоких CNN, что привело к революции в computer vision и появлению таких систем, как распознавание лиц и автопилот
- **Языковые модели** - GELU в трансформерах (BERT, GPT) обеспечивает гладкую оптимизацию для моделей с сотнями миллиардов параметров, от машинного перевода до генерации кода
- **Медицинская диагностика** - softmax на выходном слое превращает сырые оценки сети в вероятности заболеваний, позволяя врачам оценивать уверенность модели: "85% вероятность пневмонии" информативнее, чем просто "пневмония"
От сигмоиды к ReLU и далее
Первые нейронные сети использовали гладкие классические активации - сигмоиду и гиперболический тангенс, заимствованные из логистической регрессии и теории. Но у них была роковая проблема: при насыщении производная стремится к нулю, и в глубоких сетях градиент затухает, не доходя до ранних слоёв. Перелом наступил в 2010-2011 годах. Винод Наир и Джеффри Хинтон показали пользу ReLU для ограниченных машин Больцмана, а Ксавье Глоро с соавторами продемонстрировали, что ReLU позволяет эффективно обучать глубокие сети без послойного предобучения. Простая функция max(0, x) с почти нулевой стоимостью вычисления и постоянной производной для положительных входов решила проблему затухающего градиента. Позже появились более гладкие наследники - GELU и Swish, ставшие стандартом в трансформерах.
Предварительные знания
ReLU - прорыв глубокого обучения
В 2012 году сеть AlexNet выиграла соревнование ImageNet с огромным отрывом, положив начало эре глубокого обучения. Один из ключевых ингредиентов этого успеха - замена функции активации sigmoid на **ReLU (Rectified Linear Unit)**. Формула проста до невозможности: f(x) = max(0, x). Если вход положительный - пропускаем как есть. Если отрицательный - обнуляем. Эта простота и стала секретом успеха.
Почему ReLU изменил глубокое обучение? Три причины. **Первая:** для положительных входов производная ReLU равна 1, а не дробному числу как у sigmoid. Это означает, что градиент проходит через слои сети без затухания - нет проблемы vanishing gradient. **Вторая:** вычисление max(0, x) в десятки раз быстрее, чем exp(-x) в sigmoid. Для сети с миллионами нейронов это критично. **Третья:** ReLU создаёт разреженные активации - примерно половина нейронов выдаёт 0, что делает представление более эффективным и устойчивым к шуму.
**Проблема Dying ReLU:** Если взвешенная сумма входов нейрона всегда отрицательна, ReLU всегда выдаёт 0. Градиент тоже 0. Веса перестают обновляться. Нейрон "мёртв" навсегда. Это может произойти из-за: - Слишком большого learning rate (веса "улетают" в отрицательную зону) - Неудачной инициализации весов - Нехватки нормализации (BatchNorm помогает) На практике 10-40% нейронов в глубокой сети могут "умереть". Сеть всё ещё работает, но теряет ёмкость.
- Производная = 1 для положительных значений - градиент не затухает при прохождении через слои
- Вычислительно дешёвый: max(0, x) - одна операция сравнения вместо экспоненты
- Разреженные активации (~50% нулей) - эффективное представление и устойчивость к шуму
- Dying ReLU - нейроны могут необратимо "умереть", если все входы всегда отрицательны
- Неограниченный выход сверху - при больших значениях может привести к числовой нестабильности без BatchNorm
**Инициализация весов критична для ReLU!** Стандартная инициализация Xavier/Glorot рассчитана на симметричные активации (sigmoid, tanh). Для ReLU используйте инициализацию **He (Kaiming)**: веса из N(0, sqrt(2/n)), где n - число входов нейрона. Без этого в глубоких сетях сигнал может затухнуть или взорваться уже после нескольких слоёв.
Почему замена sigmoid на ReLU стала одним из ключевых факторов успеха глубоких нейронных сетей?
Sigmoid и Tanh
До эпохи ReLU именно **sigmoid** и **tanh** были стандартными функциями активации. И хотя в скрытых слоях их вытеснил ReLU, они по-прежнему незаменимы в определённых ситуациях. Sigmoid сжимает любое число в диапазон **(0, 1)** - идеально для выходного слоя бинарной классификации, где нужна вероятность. Tanh сжимает в диапазон **(-1, 1)** - центрирован вокруг нуля, что лучше для скрытых слоёв, если вы не используете ReLU.
Главная проблема sigmoid и tanh - **vanishing gradient (затухающий градиент)**. Максимальная производная sigmoid - всего 0.25 (при x=0). При обратном распространении через 10 слоёв градиент уменьшается в 0.25^10 - примерно в миллион раз. Первые слои сети почти не обучаются - их веса обновляются микроскопическими шагами. Tanh чуть лучше: его максимальная производная = 1 (при x=0), но при |x| > 2 производная быстро падает к нулю.
| Свойство | Sigmoid | Tanh | ReLU |
|---|---|---|---|
| Диапазон выхода | (0, 1) | (-1, 1) | [0, +inf) |
| Центрирован вокруг нуля | Нет (всегда > 0) | Да | Нет (всегда >= 0) |
| Макс. производная | 0.25 | 1.0 | 1.0 |
| Vanishing gradient | Сильный | Умеренный | Нет (для x > 0) |
| Вычислительная стоимость | Дорого (exp) | Дорого (exp) | Дёшево (max) |
| Dying neurons | Нет | Нет | Да |
| Типичное применение | Выход (бинарная) | LSTM/GRU gates | Скрытые слои |
**Когда использовать sigmoid и tanh сегодня:** - **Sigmoid на выходе:** бинарная классификация ("спам или не спам"), предсказание вероятности, attention weights, gate-механизмы (LSTM, GRU) - **Tanh:** скрытые слои LSTM и GRU (стандарт), нормализация выхода в диапазон [-1, 1], генеративные модели (выход генератора в GAN) В обычных скрытых слоях feedforward-сетей sigmoid и tanh практически не используются - ReLU и его варианты доминируют с 2012 года.
Интересный факт: tanh(x) = 2 * sigmoid(2x) - 1. Они математически связаны, tanh - это масштабированный и сдвинутый sigmoid. Центрированность tanh вокруг нуля - важное преимущество для скрытых слоёв: если все активации положительны (как у sigmoid), то все градиенты весов будут одного знака, что замедляет обучение зигзагообразной траекторией в пространстве параметров.
Почему sigmoid остаётся стандартным выбором для выходного слоя бинарной классификации, хотя в скрытых слоях его заменил ReLU?
Softmax для многоклассовой классификации
Sigmoid отвечает на вопрос "да или нет" - бинарная классификация. Но что если классов больше двух? Распознавание цифр (0-9), классификация изображений (кот, собака, птица), определение языка текста? Для этого существует **softmax** - обобщение sigmoid на несколько классов. Softmax принимает вектор произвольных чисел (logits) и превращает его в **распределение вероятностей**: все значения от 0 до 1, а их сумма равна точно 1.
Ключевое свойство softmax: экспонента **усиливает различия**. Класс с наибольшим logit получает непропорционально большую долю вероятности. Это желаемое поведение для классификации - модель должна быть уверена в своём предсказании. Но иногда хочется контролировать "уверенность" модели. Для этого вводят **температуру T**: softmax(z_i / T). Высокая температура (T >> 1) делает распределение более равномерным, низкая (T << 1) - более "острым".
**Числовая стабильность softmax:** e^(1000) = Inf (переполнение float). Если logits большие, softmax "взрывается". Решение: вычесть max(z) из всех logits перед экспонентой. softmax(z_i - max(z)) = softmax(z_i) - математически эквивалентно! Почему работает: e^(z_i - max(z)) / sum(e^(z_j - max(z))) Максимальный logit становится 0, e^0 = 1 - нет переполнения. Все современные фреймворки (PyTorch, TensorFlow) делают это автоматически.
**Softmax + Cross-Entropy = стандарт для классификации:** Softmax на выходном слое почти всегда используется вместе с функцией потерь **categorical cross-entropy**: L = -sum(y_i * log(p_i)), где y_i - one-hot метка, p_i - предсказанная вероятность. На практике вычисляют **log-softmax** напрямую (без отдельного softmax), потому что log(softmax(z)) упрощается и становится численно стабильнее: log_softmax(z_i) = z_i - log(sum(e^(z_j))) В PyTorch: `nn.CrossEntropyLoss` принимает сырые logits и сам вычисляет log-softmax + NLL loss.
Зачем перед вычислением softmax вычитают максимальное значение из всех logits?
Продвинутые активации
ReLU решил проблему vanishing gradient, но создал новую - dying neurons. Исследователи предложили множество модификаций, каждая из которых пытается сохранить преимущества ReLU и исправить его недостатки. **Leaky ReLU** - самое простое решение: вместо нуля для отрицательных входов использовать маленький наклон. **ELU** и **SELU** идут дальше, добавляя самонормализующие свойства. А **GELU** и **Swish** стали стандартом в трансформерах и современных архитектурах.
**Leaky ReLU** - самое простое улучшение. Для x < 0 вместо 0 возвращаем 0.01 * x. Маленький, но ненулевой градиент позволяет "мёртвым" нейронам восстановиться. Параметрический вариант - **PReLU** - обучает наклон для отрицательной области как параметр сети. **ELU (Exponential Linear Unit)** для отрицательных входов использует alpha * (e^x - 1), что сглаживает функцию в точке 0 и сдвигает среднее активаций к нулю, ускоряя обучение.
**GELU - стандарт трансформеров:** GELU (Gaussian Error Linear Unit): f(x) = x * Phi(x), где Phi(x) - функция распределения стандартного нормального распределения. Интуиция: GELU "стохастически" решает, пропускать ли вход. Для больших положительных x - почти всегда пропускает (как ReLU). Для отрицательных - почти всегда обнуляет. Но переход плавный, без излома. GELU используется в BERT, GPT, ViT и большинстве современных трансформеров. Его гладкость помогает оптимизации, а небольшие отрицательные значения на выходе (в отличие от ReLU) улучшают обучение.
| Активация | Где применять | Плюсы | Минусы |
|---|---|---|---|
| ReLU | Скрытые слои CNN, MLP | Простота, скорость, нет vanishing gradient | Dying neurons, не гладкая |
| Leaky ReLU | Скрытые слои (если dying ReLU - проблема) | Нет мёртвых нейронов, почти бесплатно | Наклон 0.01 выбран эвристически |
| ELU / SELU | Полносвязные сети без BatchNorm | Самонормализация, центрирует активации | Дороже ReLU (exp), медленнее |
| GELU | Трансформеры (BERT, GPT, ViT) | Гладкая, лучше оптимизация, стандарт | Дороже ReLU (erf/approx) |
| Swish/SiLU | EfficientNet, современные CNN | Гладкая, обучаемый beta | Дороже ReLU (sigmoid) |
| Sigmoid | Выходной слой (бинарный) | Выход в (0, 1), вероятность | Vanishing gradient в скрытых |
| Softmax | Выходной слой (многоклассовый) | Вероятности, сумма = 1 | Только для выходного слоя |
Итоги
- **ReLU = max(0, x):** производная 1 для положительных значений решает проблему vanishing gradient, вычисление молниеносно быстрое, но "мёртвые нейроны" - цена простоты
- **Sigmoid и Tanh:** sigmoid сжимает в (0, 1) для вероятностей на выходе, tanh в (-1, 1) для LSTM/GRU; оба страдают от затухания градиента в глубоких скрытых слоях
- **Softmax:** обобщение sigmoid на множество классов, превращает logits в распределение вероятностей с суммой 1; трюк с вычитанием максимума предотвращает числовое переполнение
- **Продвинутые активации:** Leaky ReLU чинит мёртвые нейроны, GELU стала стандартом трансформеров, Swish используется в современных CNN - выбор зависит от архитектуры
- **Одна функция решает всё:** как замена sigmoid на ReLU в AlexNet привела к победе на ImageNet 2012, так и сегодня правильный выбор активации может превратить неработающую модель в прорывную - три символа кода, которые определяют судьбу нейронной сети
Связанные темы
Функции активации - связующее звено между линейной алгеброй нейронных сетей и нелинейными закономерностями в данных:
- Перцептрон — Перцептрон использовал ступенчатую функцию активации (0 или 1), что не позволяло обучать многослойные сети градиентным спуском. Переход к дифференцируемым активациям (sigmoid, tanh, ReLU) сделал backpropagation возможным
- Свёрточные нейронные сети (CNN) — ReLU стал стандартом для скрытых слоёв CNN после успеха AlexNet. Выбор активации в CNN критичен: ReLU с BatchNorm позволяет тренировать сети в сотни слоёв (ResNet-152), а Swish используется в EfficientNet
Вопросы для размышления
- Почему проблема vanishing gradient критична именно для глубоких сетей (10+ слоёв), но не является серьёзной проблемой для мелких сетей с 1-2 скрытыми слоями?
- GELU и Swish вычислительно дороже ReLU, но при этом используются в огромных моделях с миллиардами параметров. Как это оправдано экономически, если вычисления стоят денег?
- Представьте, что вы проектируете нейронную сеть для бортового компьютера беспилотного автомобиля, где скорость inference критична. Какую функцию активации вы выберете для скрытых слоёв и почему?
Связанные уроки
- ml-24-perceptron — Активации заменяют ступенчатую функцию перцептрона
- ml-26-backpropagation — Их производные определяют поток градиента
- ml-25-neural-networks — Нелинейность делает глубокие слои полезными
- calc-06-derivative-intro — Затухание градиента - вопрос величины производной
- ml-29-cnn — ReLU стал стандартом для свёрточных сетей
- calc-05-continuity
- la-13-eigenvectors