Функции активации: sigmoid, tanh, ReLU
Урок разбирает три главные функции активации и объясняет, почему без нелинейности сеть бесполезна.
Функция активации — это нелинейное преобразование взвешенной суммы; именно она даёт сети способность выражать сложные зависимости.
Зачем вообще нелинейность
Представим, что активации нет: каждый слой просто считает W·x + b. Тогда два слоя подряд — это W2·(W1·x + b1) + b2, что после раскрытия снова сводится к одному линейному преобразованию W·x + b. Сколько ни ставь линейных слоёв, получится один линейный слой. Нелинейная активация между слоями ломает это схлопывание — и сеть начинает выражать кривые границы (вспомните XOR).
Три рабочие лошадки
- sigmoid: сжимает вход в (0, 1). Хороша для вероятностей на выходе. Минус — на больших по модулю входах почти плоская, градиент близок к нулю (это вредит обучению глубоких сетей).
- tanh: сжимает в (-1, 1), центрирована в нуле. Часто учится лучше sigmoid в скрытых слоях, но страдает тем же затуханием градиента на краях.
- ReLU (
max(0, x)): пропускает положительные значения как есть, отрицательные обнуляет. Простая, быстрая, не насыщается для положительных входов — сегодня дефолт для скрытых слоёв глубоких сетей.
Считаем и сравниваем
import math
def sigmoid(x):
return 1.0 / (1.0 + math.exp(-x))
def tanh(x):
return math.tanh(x)
def relu(x):
return x if x > 0 else 0.0
print("x sigmoid tanh relu")
for x in [-2, -1, 0, 1, 2]:
print(f"{x:>2} {sigmoid(x):>7.3f} {tanh(x):>7.3f} {relu(x):>5.1f}")
Вывод:
x sigmoid tanh relu -2 0.119 -0.964 0.0 -1 0.269 -0.762 0.0 0 0.500 0.000 0.0 1 0.731 0.762 1.0 2 0.881 0.964 2.0
Видно главное: sigmoid и tanh «прижимаются» к границам на краях (их выход почти не меняется при больших входах), а ReLU для отрицательных входов жёстко обнуляется, для положительных — линейна.
Какую выбрать
| Функция | Диапазон | Где применять |
| ReLU | [0, +∞) | скрытые слои по умолчанию |
| sigmoid | (0, 1) | выход бинарной классификации |
| tanh | (-1, 1) | скрытые слои, рекуррентные сети |
У ReLU есть проблема «мёртвых нейронов»: если вход постоянно отрицательный, нейрон всегда выдаёт 0 и перестаёт учиться. Поэтому придумали варианты вроде Leaky ReLU (max(0.01*x, x)), которые оставляют маленький наклон для отрицательной части.
При чём тут производная
Выбор активации напрямую влияет на обучение через её производную — ту самую, что backprop перемножает по слоям. У sigmoid производная не больше 0.25 и почти зануляется на краях, поэтому в глубокой сети сигнал ошибки быстро гаснет (мы посчитаем это в разделе про затухание градиента). У ReLU производная для положительных входов равна ровно 1 — она ничего не сжимает и пропускает градиент без потерь. Это и есть главная причина, по которой ReLU вытеснила sigmoid из скрытых слоёв: дело не столько в самих значениях активации, сколько в том, как ведёт себя её производная при обратном проходе.
Есть и современные «гладкие» активации — GELU и SiLU (swish), — которые используют в трансформерах. Они похожи на ReLU, но плавно сглажены около нуля, что иногда чуть улучшает обучение больших моделей. Для начала же достаточно правила: скрытые слои — ReLU, выход — sigmoid (бинарная задача) или softmax (много классов).
Итог
- Без нелинейной активации стопка слоёв схлопывается в один линейный слой.
- sigmoid и tanh насыщаются на краях; ReLU — нет (для положительных входов).
- ReLU — стандарт для скрытых слоёв, sigmoid/softmax — для выхода.