Зачем он нужен
ReLU — самая популярная активация глубокого обучения: $\max(0,x)$ считается мгновенно, а справа от нуля градиент не затухает. Но у него есть слабое место. Слева от нуля ReLU не приглушает сигнал, а обнуляет его — и вместе с ним градиент. Нейрон, у которого вход отрицателен на всех примерах, выдаёт 0, получает нулевой градиент и больше никогда не учится. Это «умирающий ReLU» (dying ReLU).
Leaky ReLU — минимальная поправка: слева от нуля график не горизонтален, а слегка наклонён, $\alpha x$ с маленьким $\alpha$ (обычно от $0{,}01$ до $0{,}3$). Сигнал «протекает» сквозь закрытую дверь — отсюда и название (leaky — «протекающий»).
Где он встречается:
- дискриминаторы GAN — в DCGAN (Рэдфорд и др., 2015) все слои дискриминатора используют Leaky ReLU с $\alpha=0{,}2$;
- детекторы YOLO — сеть Darknet в YOLOv2 и YOLOv3 построена на Leaky ReLU с $\alpha=0{,}1$;
- графовые сети — коэффициенты внимания в GAT считаются через Leaky ReLU с $\alpha=0{,}2$;
- свёрточные сети с PReLU — вариант с обучаемым $\alpha$ (Хе и др., 2015) помог впервые опустить ошибку top-5 на ImageNet ниже оценки человеческой ошибки;
- любая сеть, где ReLU «умирает» — замена занимает одну строку и почти ничего не стоит.
$\operatorname{LReLU}(x)=x$ при $x>0$ и $\alpha x$ при $x\le0$. Производная — ступенька: $1$ справа и $\alpha$ слева, поэтому градиент никогда не обнуляется целиком. Функция остаётся кусочно-линейной, монотонной и почти такой же дешёвой, как ReLU. При $\alpha=0$ это ReLU, при $\alpha=1$ — тождественная функция, при обучаемом $\alpha$ — PReLU.
Интуиция: дверь, которая не закрывается до конца
ReLU похож на дверь: положительный сигнал проходит целиком, отрицательный упирается в закрытую створку. Leaky ReLU оставляет щель — отрицательный сигнал проходит, но ослабленным в $1/\alpha$ раз. При $\alpha=0{,}1$ вход $-2$ превращается в $-0{,}2$.
Потяните точку по графику. Оранжевый «треугольник наклона» показывает производную: шаг на 1 вдоль оси $x$ меняет значение на $\alpha$ слева от нуля и на 1 справа. Ниже — сама производная: две горизонтальные ступеньки с разрывом в нуле. Подвигайте ползунок $\alpha$: от ReLU ($\alpha=0$) через «протекающий» вариант к прямой $y=x$ ($\alpha=1$).
Слева график не плоский, но очень пологий: при $\alpha=0{,}01$ вход $-100$ даёт всего $-1$. Вся нелинейность Leaky ReLU сосредоточена в одной точке — изломе в нуле, где наклон меняется с $\alpha$ на 1. Выразительная сила сети из таких нейронов берётся именно из этих изломов.
Формула по косточкам
Одну и ту же функцию полезно уметь записывать тремя способами — каждый пригодится в своём месте.
1. По случаям
- $x$
- вход нейрона — обычно пре-активация $z=w^\top h+b$;
- $\alpha$
- наклон отрицательной части, гиперпараметр; обычно $0<\alpha<1$;
- $\alpha x$
- «протечка»: отрицательный вход не обнуляется, а сжимается в $1/\alpha$ раз.
В точке $x=0$ обе ветки дают ноль, поэтому неважно, к какой из них отнести ноль: функция непрерывна.
2. Через максимум
При $x>0$ и $\alpha\le1$ выполняется $x\ge\alpha x$, а при $x<0$ — наоборот, $\alpha x\ge x$. Значит, максимум сам выбирает нужную ветку. Но только при $\alpha\le1$: при $\alpha=2$ справа победит $2x$, и получится другая функция. Запись удобна в коде (np.maximum(alpha * x, x)), но про условие легко забыть.
3. Линейная часть плюс модуль
Проверка: при $x>0$ получаем $\frac{1+\alpha}{2}x+\frac{1-\alpha}{2}x=x$, при $x<0$ — $\frac{1+\alpha}{2}x-\frac{1-\alpha}{2}x=\alpha x$. Эта форма верна при любом $\alpha$ и объясняет главное: Leaky ReLU — это линейная функция плюс «немного модуля». Вся нелинейность сидит во втором слагаемом, и её доля $\frac{1-\alpha}{2}$ уменьшается с ростом $\alpha$. При $\alpha=1$ нелинейность исчезает полностью.
| $x$ | $\alpha=0{,}01$ | $\alpha=0{,}2$ | $\operatorname{LReLU}'(x)$ |
|---|---|---|---|
| −5 | −0,05 | −1 | $\alpha$ |
| −2 | −0,02 | −0,4 | $\alpha$ |
| −0,5 | −0,005 | −0,1 | $\alpha$ |
| 0,5 | 0,5 | 0,5 | $1$ |
| 2 | 2 | 2 | $1$ |
| 5 | 5 | 5 | $1$ |
Справа от нуля все варианты совпадают с ReLU; они различаются только тем, сколько отрицательного сигнала «протекает».
Свойства
- Область определения и значений — вся числовая прямая $\mathbb R$ (при $\alpha>0$). У ReLU значения только $[0;\,+\infty)$.
- Непрерывность и кусочная линейность: две прямые, склеенные в нуле. Функция дифференцируема везде, кроме $x=0$.
- Строгая монотонность при $\alpha>0$: больший вход даёт больший выход. Поэтому функция обратима: $\operatorname{LReLU}_\alpha^{-1}(y)=y$ при $y>0$ и $y/\alpha$ при $y\le0$, то есть $\operatorname{LReLU}_{1/\alpha}$. У ReLU обратной нет: все отрицательные входы склеены в ноль.
- Положительная однородность: $\operatorname{LReLU}(cx)=c\,\operatorname{LReLU}(x)$ при $c\ge0$. Масштаб входа просто переносится на выход — отсюда простые формулы инициализации.
- Липшицевость с константой $\max(1,|\alpha|)$, то есть 1 при $\alpha\le1$: $|\operatorname{LReLU}(a)-\operatorname{LReLU}(b)|\le|a-b|$.
- Неограниченность сверху и снизу, но вниз функция растёт в $1/\alpha$ раз медленнее.
- Частные случаи: $\alpha=0$ — ReLU, $\alpha=1$ — тождественная функция, $\alpha=-1$ — модуль $|x|$ (уже не монотонный).
Среднее и разброс выхода
Пусть вход нейрона $z\sim N(0,1)$. Тогда
При $\alpha=0{,}01$ среднее равно $0{,}395$ (у ReLU — $0{,}399$), при $\alpha=0{,}2$ — $0{,}319$. Чем больше $\alpha$, тем ближе выходы к нулевому среднему; это немного облегчает обучение следующего слоя. Второй момент $\frac{1+\alpha^2}{2}$ понадобится в разделе об инициализации.
Откуда эти формулы
Для $z\sim N(0,1)$ известно, что $\mathbb E[z\,\mathbf 1_{z>0}]=\varphi(0)=1/\sqrt{2\pi}$, а по симметрии $\mathbb E[z\,\mathbf 1_{z<0}]=-1/\sqrt{2\pi}$. Поэтому
Аналогично $\mathbb E[z^2\mathbf 1_{z>0}]=\mathbb E[z^2\mathbf 1_{z<0}]=\tfrac12$, откуда $\mathbb E[\operatorname{LReLU}(z)^2]=\tfrac12+\tfrac{\alpha^2}{2}$. Вторая формула верна для любого симметричного распределения с единичной дисперсией, первая — только для нормального.
Производная: ступенька вместо обрыва
На каждой ветке функция линейна, поэтому производная — просто наклон ветки:
Вывод по определению
При $x>0$ для достаточно малых $h$ точка $x+h$ тоже положительна, и $\frac{\operatorname{LReLU}(x+h)-\operatorname{LReLU}(x)}{h}=\frac{(x+h)-x}{h}=1$. При $x<0$ так же получаем $\frac{\alpha(x+h)-\alpha x}{h}=\alpha$.
В нуле односторонние пределы разные:
При $\alpha\ne1$ они не совпадают, поэтому производной в нуле нет — это точка излома.
Что делать с нулём на практике? В точке излома есть субградиент (subgradient): при $0\le\alpha\le1$ любое число $g\in[\alpha;\,1]$ задаёт прямую $y=gx$, которая лежит не выше графика. Библиотеки выбирают одно значение по соглашению — в PyTorch при $x=0$ берётся $\alpha$. Точно в ноль вход попадает редко, так что выбор почти ни на что не влияет.
Почему ступенька лучше обрыва
По цепному правилу градиент по весу $w_j$ нейрона $a=\operatorname{LReLU}(z)$, $z=\sum_j w_jx_j+b$, равен
У ReLU средний множитель равен 0 при $z<0$, у Leaky ReLU — $\alpha$. Слева градиент в $1/\alpha$ раз слабее, но не равен нулю: нейрон, «застрявший» в отрицательной зоне, продолжает получать сигнал об ошибке.
Производная по α: шаг к PReLU
Если сделать $\alpha$ обучаемым параметром, понадобится производная по нему. Она тоже простая:
Наклон $\alpha$ учится только на примерах, попавших в левую ветку, — так устроен PReLU (раздел 9). Вторая производная по $x$ равна нулю везде, кроме нуля: вся кривизна сосредоточена в изломе, и в смысле обобщённых функций $\operatorname{LReLU}''(x)=(1-\alpha)\,\delta(x)$.
Умирающий ReLU и как Leaky его лечит
Как умирает нейрон. Пусть после неудачного большого шага (слишком большой темп обучения, выброс в данных, неудачная инициализация) сдвиг $b$ нейрона стал сильно отрицательным. Тогда $z=w^\top x+b<0$ на всех примерах, ReLU выдаёт 0, производная $\operatorname{ReLU}'(z)=0$ — и градиенты по $w$, $b$ и по выходному весу $v$ обнуляются одновременно. Градиентный спуск больше не сдвинет этот нейрон: он мёртв (строго навсегда — для нейрона первого слоя при обычном SGD; в глубоких слоях вход нейрона меняется вместе с предыдущими слоями, и изредка нейроны оживают). В конспектах курса CS231n отмечают, что при слишком большом темпе обучения мёртвой может оказаться до 40% сети.
Ниже — самый чистый эксперимент. Один нейрон $f(x)=v\cdot\operatorname{act}(wx+b)$ должен выучить «шарнир» $y=1{,}5\max(0,\,x-1)$ по 41 точке отрезка $[-3;\,3]$. Старт: $w=1$, $b=-4$, $v=1$ — излом в точке $x=4$, за пределами данных, поэтому на всех примерах $z<0$. Обучение — градиентный спуск по MSE с шагом $0{,}1$.
Обратите внимание на компромисс. Большой $\alpha$ быстро возвращает нейрон к жизни, но левая ветка остаётся наклонной: при $\alpha=0{,}1$ итоговая модель слева имеет наклон $\alpha v w\approx0{,}116$ вместо нуля, отсюда остаточная ошибка. Маленький $\alpha$ почти не искажает форму функции, но оживляет медленнее.
Ненулевой градиент не означает, что нейрон обязательно вернётся: он может так и остаться на левой ветке, работая как линейная функция $\alpha(w^\top x+b)$. Leaky ReLU гарантирует другое — нейрон никогда не замерзает намертво и продолжает учиться. Против самой причины гибели помогают умеренный темп обучения, разогрев (warmup), нормализация и правильная инициализация.
Сеть из Leaky ReLU: кусочно-линейный рельеф
В сети с двумя входами каждый нейрон $\operatorname{LReLU}(w_k^\top x+b_k)$ «сгибает» плоскость вдоль прямой $w_k^\top x+b_k=0$: по одну сторону от неё вклад нейрона в $1/\alpha$ раз положе, чем по другую. Сумма нейронов $f(x)=\sum_k v_k\operatorname{LReLU}(w_k^\top x+b_k)$ — многогранная поверхность: внутри каждой области, где набор включённых нейронов не меняется, она плоская, а на прямых-изломах меняет наклон.
Число областей не зависит от $\alpha$ (пока $\alpha\ne1$): его задают только прямые изломов. Зато от $\alpha$ зависит, что происходит там, где все нейроны выключены. У ReLU там плато с нулевым градиентом, и примеры, попавшие на него, ничего не сообщают сети. У Leaky ReLU плато наклонено, и градиент там, как правило, не нулевой.
$n$ прямых общего положения делят плоскость не более чем на $1+n+\binom n2$ частей: для $n=6$ это 22. В квадрате на рисунке видно 19 из них. У глубоких сетей число линейных областей может расти с глубиной экспоненциально — это одно из объяснений их выразительной силы.
Глубокие сети: инициализация Хе для Leaky ReLU
В глубокой сети сигнал проходит через десятки слоёв $z_{l+1}=W_{l+1}\operatorname{LReLU}(z_l)$. Если на каждом слое дисперсия умножается на число, хоть немного отличное от 1, через 50 слоёв это превратится во взрыв или исчезновение сигнала. Посчитаем этот множитель.
Вывод множителя
Пусть веса $W_{ij}$ независимы, $\mathbb E W_{ij}=0$, $\operatorname{Var}W_{ij}=s^2$, а входы $z_l$ симметричны относительно нуля. Для одного выхода $z_{l+1,i}=\sum_{j=1}^{n}W_{ij}h_j$, где $h_j=\operatorname{LReLU}(z_{l,j})$:
Последнее равенство — второй момент из раздела о свойствах: половина $z_l^2$ приходит с положительной ветки целиком, половина — с отрицательной, умноженная на $\alpha^2$. Чтобы дисперсия сохранялась, множитель должен быть равен 1:
На обратном проходе градиент умножается на $W^\top$ и на $\operatorname{LReLU}'(z)$, а $\mathbb E[\operatorname{LReLU}'(z)^2]=\frac{1+\alpha^2}{2}$ — тот же множитель. Поэтому одна и та же инициализация сохраняет и прямой сигнал, и градиенты.
При $\alpha=0$ получается знаменитое $g=\sqrt2$ инициализации Хе (Kaiming) для ReLU. Для Leaky ReLU коэффициент чуть меньше: $1{,}414$ при $\alpha=0{,}01$, $1{,}387$ при $\alpha=0{,}2$, $1{,}355$ при $\alpha=0{,}3$.
Ровно это делает nn.init.kaiming_normal_(w, a=alpha, nonlinearity='leaky_relu'): стандартное отклонение $\sqrt{2/((1+a^2)\,n_{\text{in}})}$. По умолчанию там a=0, то есть инициализация для обычного ReLU, — для Leaky ReLU параметр a нужно передать явно.
PReLU, RReLU и вся семья
Как выбрать $\alpha$? Есть три ответа.
- Фиксированный $\alpha$ — классический Leaky ReLU (Маас, Ханнун, Ын, 2013, $\alpha=0{,}01$). Сегодня часто берут $0{,}1$–$0{,}3$: в сравнении Сюй и др. (2015) «сильно протекающий» вариант с $\alpha=1/5{,}5\approx0{,}18$ работал лучше, чем $0{,}01$.
- Обучаемый $\alpha$ — PReLU (Parametric ReLU, Хе и др., 2015). $\alpha$ становится параметром — один на слой или по одному на канал — и учится градиентным спуском вместе с весами. Начальное значение в PyTorch — $0{,}25$.
- Случайный $\alpha$ — RReLU (Randomized ReLU): при обучении $\alpha$ заново берётся для каждого элемента входа из равномерного распределения $U(1/8;\,1/3)$ (границы по умолчанию в PyTorch), при выводе — среднее $\frac{1/8+1/3}{2}=\frac{11}{48}\approx0{,}229$. Шум действует как регуляризация.
У PReLU градиент по $\alpha$ — это $\min(0,\,z)$ из раздела о производной: наклон учится только на отрицательных входах. Посмотрим, как градиентный спуск находит сразу и вес, и наклон.
PReLU добавляет всего по одному параметру на канал, но в работе Хе и др. он вместе с новой инициализацией позволил обучить очень глубокие свёрточные сети и получить ошибку top-5 $4{,}94\%$ на ImageNet — ниже оценки человеческой ошибки $5{,}1\%$. Авторы отмечают, что к $\alpha$ не стоит применять затухание весов (weight decay): оно тянет $\alpha$ к нулю, то есть обратно к ReLU.
Гладкие родственники
Излом в нуле можно сгладить. ELU заменяет левую прямую экспонентой $\alpha(e^x-1)$, которая насыщается на уровне $-\alpha$ (здесь $\alpha$ — свой параметр ELU, обычно 1). SELU добавляет масштаб: $\lambda\approx1{,}0507$ и $\alpha\approx1{,}6733$ подобраны так, чтобы в полносвязной сети с инициализацией LeCun активации сами поддерживали нулевое среднее и единичную дисперсию. GELU и SiLU — гладкие и даже немонотонные функции, которые сегодня стоят в трансформерах.
| Функция | При $x\le0$ | Производная слева | Особенность |
|---|---|---|---|
| ReLU | $0$ | $0$ | нулевой градиент, «мёртвые» нейроны |
| Leaky ReLU | $\alpha x$ | $\alpha$ | фиксированный наклон, обычно $0{,}01$–$0{,}3$ |
| PReLU | $\alpha x$, $\alpha$ обучается | $\alpha$ | +1 параметр на слой или канал |
| RReLU | $\alpha x$, $\alpha\sim U(\tfrac18;\,\tfrac13)$ | $\alpha$ | шум как регуляризация |
| ELU | $\alpha(e^{x}-1)$ | $\alpha e^{x}$ | производная непрерывна при $\alpha=1$, насыщение на $-\alpha$ |
| SELU | $\lambda\alpha(e^{x}-1)$ | $\lambda\alpha e^{x}$ | самонормализация, $\lambda\approx1{,}0507$ |
В коде
В NumPy Leaky ReLU — одна строка. Надёжнее писать np.where, чем np.maximum(alpha * x, x): вторая запись тихо ломается при $\alpha>1$.
pythonimport numpy as np
def leaky_relu(x, alpha=0.01):
# where, а не maximum(alpha * x, x): эта запись верна при любом alpha
return np.where(x > 0, x, alpha * x)
def leaky_relu_grad(x, alpha=0.01):
return np.where(x > 0, 1.0, alpha) # в нуле берём alpha, как PyTorch
def he_std(n_in, alpha=0.01):
# инициализация Хе для Leaky ReLU: Var w = 2 / ((1 + alpha²) · n_in)
return np.sqrt(2.0 / ((1.0 + alpha**2) * n_in))
x = np.array([-3.0, -0.5, 0.0, 2.0])
print(leaky_relu(x)) # [-0.03 -0.005 0. 2. ]
print(leaky_relu_grad(x)) # [0.01 0.01 0.01 1. ]
print(he_std(256, 0.2)) # 0.08667190566019205
pythonimport torch
import torch.nn as nn
act = nn.LeakyReLU(negative_slope=0.01) # 0.01 — значение по умолчанию
x = torch.tensor([-3.0, 0.0, 2.0], requires_grad=True)
act(x).sum().backward()
print(x.grad) # tensor([0.0100, 0.0100, 1.0000]) — в нуле α
prelu = nn.PReLU(num_parameters=1, init=0.25) # α — обучаемый параметр
print(prelu(torch.tensor([-2.0, 3.0])).detach()) # tensor([-0.5000, 3.0000])
lin = nn.Linear(256, 256)
# std = √(2 / ((1 + a²) · 256)); по умолчанию a=0, то есть «как для ReLU»
nn.init.kaiming_normal_(lin.weight, a=0.2, nonlinearity="leaky_relu")
print(nn.init.calculate_gain("leaky_relu", 0.2)) # 1.3867504905630728
PyTorch nn.LeakyReLU: negative_slope=0.01. TensorFlow tf.nn.leaky_relu: alpha=0.2. Keras layers.LeakyReLU: $0{,}3$. Одна и та же «Leaky ReLU» в трёх фреймворках — три разные функции. При переносе модели указывайте $\alpha$ явно.
С численной точки зрения Leaky ReLU безопасен: ни экспонент, ни деления, ни переполнений. Единственная тонкость — inplace=True в PyTorch: он экономит память, но перезаписывает вход, который может понадобиться другим операциям графа.
Частые ошибки
- Запись
max(alpha * x, x)при $\alpha>1$. Формула верна только при $\alpha\le1$; при больших $\alpha$ получается другая функция. Безопасная запись —where(x > 0, x, alpha * x). - Слишком большой $\alpha$. При $\alpha\to1$ доля нелинейности $\frac{1-\alpha}{2}$ стремится к нулю, функция становится почти линейной, и глубокая сеть теряет выразительность. Разумный диапазон — от $0{,}01$ до $0{,}3$.
- Инициализация «как для ReLU» без поправки на $\alpha$. Множитель дисперсии $1+\alpha^2$ за слой: при $\alpha=0{,}3$ RMS сигнала с 1-го по 50-й слой вырастает примерно в $1{,}09^{24{,}5}\approx8{,}3$ раза (рисунок 5). Передавайте $\alpha$ в
kaiming_normal_(..., a=alpha). - Надежда, что Leaky ReLU сам вылечит нестабильное обучение. Он убирает нулевой градиент, но не причину: слишком большой темп обучения по-прежнему опасен.
- Затухание весов на $\alpha$ у PReLU. Оно тянет $\alpha$ к нулю, и PReLU превращается в ReLU. Исключайте $\alpha$ из группы параметров с weight decay.
- Разные значения по умолчанию в PyTorch ($0{,}01$), TensorFlow ($0{,}2$) и Keras ($0{,}3$): при переносе модели между фреймворками результат молча меняется.
Связи с другими формулами
- ReLU: частный случай $\alpha=0$; там же — подробнее об «умирающем ReLU».
- SiLU / Swish и GELU: гладкие активации, у которых слева тоже проходит небольшой отрицательный сигнал, но затем он гаснет.
- Сигмоида и tanh: насыщающиеся активации; у Leaky ReLU насыщения нет вовсе, а значит, нет и затухания градиента из-за насыщения.
- MSE: функция потерь в экспериментах на рисунках 3 и 6.
- SGD и Adam: слишком большой шаг оптимизатора — главная причина гибели ReLU-нейронов.
Итоги
1) $\operatorname{LReLU}_\alpha(x)=x$ при $x>0$ и $\alpha x$ при $x\le0$; это $\max(\alpha x,x)$ при $\alpha\le1$ и $\frac{1+\alpha}{2}x+\frac{1-\alpha}{2}|x|$ при любом $\alpha$. 2) Производная — ступенька из $\alpha$ и $1$: градиент не обнуляется, нейрон не замерзает. 3) Компромисс: больший $\alpha$ быстрее оживляет нейроны, но приближает функцию к линейной. 4) Сеть из Leaky ReLU — кусочно-линейная функция без плоских «мёртвых» плато. 5) Инициализация: $\operatorname{Var}w=\frac{2}{(1+\alpha^2)\,n_{\text{in}}}$. 6) PReLU учит $\alpha$ по градиенту $\min(0,z)$.