Шпаргалка формул нейросетей · Функции активации

ReLU: выпрямленная линейная функция

Самая простая нелинейность и рабочая лошадка глубокого обучения. Разбираем по косточкам: почему одного излома хватает, чтобы собрать любую ломаную, что такое производная в точке излома, как сеть из ReLU режет пространство на линейные куски, почему нейроны «умирают» и откуда в инициализации Хе двойка.

Javharbek Abdulatipov · 35 мин чтения
$$\operatorname{ReLU}(x)=\max(0,\,x)$$

Зачем он нужен

Без нелинейности нейросеть бесполезна: композиция линейных слоёв — снова линейная функция, сколько слоёв ни ставь. Нужна функция, которая «ломает» линейность, но при этом дёшево считается и не душит градиент. ReLU (rectified linear unit, «выпрямленная линейная функция») делает минимально возможное: положительное пропускает как есть, отрицательное заменяет нулём.

Где он встречается:

  • свёрточные сети — AlexNet, VGG, ResNet: ReLU — основная нелинейность после свёрток;
  • полносвязные сети и табличные модели — выбор по умолчанию для скрытых слоёв;
  • исходный Transformer (2017) — блок FFN: $\max(0,\,xW_1+b_1)W_2+b_2$; современные LLM перешли на его гладкие родственники GELU и SiLU (часто в составе вентильного блока SwiGLU);
  • мобильные сети — ReLU6 $=\min(\max(0,x),\,6)$ в MobileNet удобна для вычислений с малой разрядностью;
  • внутри других формул — $\max(0,\cdot)$ это и hinge-потеря SVM, и triplet loss, и положительная часть числа $x^+$.
Главное за минуту

$\operatorname{ReLU}(x)=\max(0,x)$: ноль слева, прямая $y=x$ справа. Производная — ступенька: 0 при $x<0$ и 1 при $x>0$; в нуле производной нет, библиотеки берут 0. Справа градиент проходит без ослабления — поэтому глубокие сети с ReLU учатся быстро. Плата — «мёртвые» нейроны, у которых вход всегда отрицателен.

Интуиция: выпрямитель

Название пришло из электроники: диод-выпрямитель пропускает ток в одну сторону и не пропускает в другую. Нейрон с ReLU — это датчик: пока признак ниже порога, он молчит; как только порог пройден, отвечает пропорционально тому, насколько сильно.

Потяните точку. Справа от нуля касательная совпадает с самой функцией (наклон 1), слева лежит на оси (наклон 0). В нуле единственной касательной нет: любая прямая с наклоном от 0 до 1 касается графика снизу — это опорные прямые.

Рисунок 1. ReLU, касательная и производная (снизу). При $x=1{,}5$: $\operatorname{ReLU}=1{,}5$, $\operatorname{ReLU}'=1$. Подведите точку к нулю: производная не определена, множество наклонов опорных прямых — отрезок $[0;\,1]$ (субдифференциал); PyTorch и TensorFlow берут из него 0.
Что заметить

У ReLU нет насыщения справа: при $x=100$ производная та же 1, что и при $x=0{,}1$. У сигмоиды и tanh при $|x|=5$ производная уже меньше $0{,}01$. Зато слева ReLU «насыщен» полностью: производная ровно 0.

Формула по косточкам

Одну и ту же функцию полезно узнавать в разных записях — каждая подсвечивает своё свойство:

$$\operatorname{ReLU}(x)=\max(0,x)=\begin{cases}x, & x>0\\0, & x\le0\end{cases}=\frac{x+|x|}{2}=x\cdot\mathbb 1[x>0]$$
$\max(0,x)$
сравнение с нулём — одна операция, без экспонент и делений;
$\frac{x+|x|}{2}$
при $x>0$ слагаемые равны и дают $x$, при $x<0$ они взаимно уничтожаются;
$x\cdot\mathbb 1[x>0]$
вентиль: вход умножается на 0 или 1 в зависимости от знака. Для каждого примера сеть с ReLU — это линейная сеть, в которой часть нейронов выключена.
$x$$\operatorname{ReLU}(x)$$\operatorname{ReLU}'(x)$
−300
−100
−0,500
00[0; 1]
0,50,51
111
2,52,51

Из изломов — любая ломаная

Нейрон $v\cdot\operatorname{ReLU}(x-c)$ — это «шарнир» (hinge): ноль до точки $c$, затем прямая с наклоном $v$. Складывая шарниры с разными $c$, получаем ломаную: в каждой точке $c_k$ наклон меняется ровно на $v_k$. Например, $\operatorname{ReLU}(x+1)-2\operatorname{ReLU}(x)+\operatorname{ReLU}(x-1)$ — «шапочка» высотой 1.

Рисунок 2. Сумма трёх шарниров с изломами в $-1$, $0$, $1$. При весах $(1;\,-2;\,1)$ получается шапочка: наклоны участков $0,\ 1,\ -1,\ 0$, высота $f(0)=1$. Снизу — производная: ступенчатая функция, которая в точке $c_k$ прыгает ровно на $v_k$.

Это и есть главный секрет ReLU-сетей: любая непрерывная кусочно-линейная функция на прямой с $m$ изломами — это $a+bx$ плюс $m$ шарниров, то есть сеть с одним скрытым слоем из $m$ нейронов (плюс выходной сдвиг $a$ и слагаемое $bx$, которое тоже можно выразить двумя нейронами: $x=\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$). А ломаными можно сколь угодно точно приблизить любую непрерывную функцию на отрезке.

Свойства

  • Область значений — $[0;\,+\infty)$: сверху не ограничена, в отличие от сигмоиды и tanh.
  • Кусочная линейность: два линейных куска, один излом в нуле.
  • Непрерывность и липшицевость с константой 1: $|\operatorname{ReLU}(a)-\operatorname{ReLU}(b)|\le|a-b|$.
  • Выпуклость: график лежит не выше любой хорды — максимум двух линейных функций всегда выпукл.
  • Положительная однородность: $\operatorname{ReLU}(\alpha x)=\alpha\operatorname{ReLU}(x)$ при $\alpha\ge0$. Масштаб можно переносить между слоями: умножив веса слоя на $\alpha>0$, а следующего — на $1/\alpha$, получим ту же сеть.
  • Идемпотентность: $\operatorname{ReLU}(\operatorname{ReLU}(x))=\operatorname{ReLU}(x)$.
  • Разложение числа: $x=\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$ и $|x|=\operatorname{ReLU}(x)+\operatorname{ReLU}(-x)$.
  • Разреженность (sparsity): если входы нейронов симметричны относительно нуля, примерно половина выходов — точные нули.
Доказательства: выпуклость и однородность

Выпуклость. Для $t\in[0;1]$ и любых $a,b$: $\max(0,\,ta+(1-t)b)\le\max\bigl(0,\,t\max(0,a)+(1-t)\max(0,b)\bigr)=t\max(0,a)+(1-t)\max(0,b)$, потому что $a\le\max(0,a)$, $b\le\max(0,b)$, а правая часть неотрицательна.

Однородность. При $\alpha>0$ знак $\alpha x$ совпадает со знаком $x$, поэтому $\max(0,\alpha x)=\alpha\max(0,x)$; при $\alpha=0$ обе части равны 0. При $\alpha<0$ равенство нарушается: $\operatorname{ReLU}(-x)\ne-\operatorname{ReLU}(x)$ — функция не нечётна.

Производная, субградиент и гладкие родственники

$$\operatorname{ReLU}'(x)=\begin{cases}1, & x>0\\0, & x<0\end{cases},\qquad \partial\operatorname{ReLU}(0)=[0,\,1]$$
Почему в нуле производной нет

Производная — предел разностного отношения. Справа и слева от нуля он разный:

$$\lim_{h\to0^+}\frac{\operatorname{ReLU}(h)-0}{h}=\lim_{h\to0^+}\frac{h}{h}=1,\qquad \lim_{h\to0^-}\frac{\operatorname{ReLU}(h)-0}{h}=\lim_{h\to0^-}\frac{0}{h}=0$$

Односторонние производные не совпадают, значит, обычной производной нет. Для выпуклых функций есть замена — субградиент: число $g$, для которого $f(y)\ge f(x)+g(y-x)$ при всех $y$, то есть прямая с наклоном $g$ лежит под графиком. В нуле так ведут себя все $g\in[0;1]$: это множество называют субдифференциалом $\partial\operatorname{ReLU}(0)$.

Почему это почти не мешает обучению: для непрерывных данных вход нейрона ровно равен нулю с вероятностью 0. В арифметике с плавающей точкой точные нули всё же случаются, но так редко, что выбор значения из $[0;1]$ почти ни на что не влияет (в 16-битной арифметике нули встречаются заметно чаще, и выбор $\operatorname{ReLU}'(0)$ иногда сказывается на обучении). Библиотеки по соглашению берут 0.

Вторая производная равна нулю везде, кроме нуля (в смысле обобщённых функций $\operatorname{ReLU}''=\delta(x)$). Поэтому внутри каждой линейной области сеть из ReLU — аффинная функция входа, а её градиент по входу кусочно-постоянен.

Softplus: сглаженный ReLU

Если излом мешает (например, нужна гладкая функция для оптимизации второго порядка или физической модели), его можно скруглить:

$$\operatorname{softplus}_\beta(x)=\frac1\beta\ln\bigl(1+e^{\beta x}\bigr),\qquad \operatorname{softplus}_\beta'(x)=\sigma(\beta x)$$

Разность $\operatorname{softplus}_\beta(x)-\operatorname{ReLU}(x)=\frac1\beta\ln\bigl(1+e^{-\beta|x|}\bigr)$ максимальна в нуле и равна $\frac{\ln2}{\beta}$; при $\beta\to\infty$ softplus стремится к ReLU, а производная-сигмоида — к ступеньке. В нуле она всегда равна $\sigma(0)=0{,}5$ — середине субдифференциала $[0;1]$.

Рисунок 3. Сверху ReLU и $\operatorname{softplus}_\beta$, снизу их производные. При $\beta=1$ наибольший разрыв $\ln2\approx0{,}693$, при $\beta=4$ — $0{,}173$, при $\beta=32$ — $0{,}022$. Производная softplus в нуле всегда $0{,}5$.

ReLU-сеть в пространстве: линейные области

Нейрон первого слоя с двумя входами выключен по одну сторону прямой $w^\top x+b=0$ и линеен по другую. Каждая такая прямая — линия сгиба. $H$ нейронов разрезают плоскость на области, и в каждой области набор включённых нейронов (паттерн активаций) постоянен, а значит, сеть — обычная аффинная функция. Поверхность выхода — многогранник, склеенный из плоских граней.

Рисунок 4. Слева — выход сети $f(x_1,x_2)=\sum_k v_k\operatorname{ReLU}(w_k^\top x+b_k)$ в 3D: плоские грани и рёбра-сгибы. Справа — вид сверху: цвет — номер линейной области, пунктир — прямые нейронов, тонкие линии — уровни $f$ (они ломаются на границах). При 4 нейронах в окне 10 областей из возможных 11 ($1+H+\tfrac{H(H-1)}{2}$); при 8 нейронах — 25 из 37. Два слоя по 4 нейрона дают уже 30 областей: границы второго слоя изгибаются на границах первого.

$H$ прямых общего положения делят плоскость максимум на $1+H+\binom H2$ частей — число областей одного слоя растёт полиномиально. Глубина работает иначе: каждый следующий слой «складывает» уже разрезанное пространство, и число областей может расти экспоненциально с числом слоёв (Монтуфар и др., 2014). Это одно из объяснений, почему глубокие сети выразительнее широких при том же числе нейронов.

Универсальная аппроксимация

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

ReLU в обучении: сеть рисует ломаную

Обучим один скрытый слой $\hat y(x)=\sum_{k=1}^{H}v_k\operatorname{ReLU}(w_kx+b_k)+c$ на точках синусоиды. Каждый нейрон — шарнир с изломом в $x=-b_k/w_k$; градиентный спуск сдвигает изломы туда, где кривая изгибается, и подбирает наклоны.

$$\frac{\partial\hat y}{\partial b_k}=v_k\,\mathbb 1[w_kx+b_k>0],\qquad \frac{\partial\hat y}{\partial w_k}=v_k\,x\,\mathbb 1[w_kx+b_k>0]$$

Градиент по параметрам нейрона приходит только от тех точек, где нейрон включён. Если таких точек нет совсем, нейрон перестаёт учиться — это и есть «умирание».

Рисунок 5. 40 точек $y=\sin(1{,}6x)$ с шумом ($\sigma=0{,}08$), полный градиент и Adam с шагом $0{,}02$. Бирюзовые линии — шарниры, точки внизу — их изломы, красный пунктир — мёртвые нейроны. С 6 нейронами MSE падает с $3{,}102$ до $0{,}267$ к шагу 100, $0{,}012$ к шагу 300 и $0{,}0090$ к шагу 1500; по дороге один нейрон умирает. С 3 нейронами один мёртв с самого начала, и ломаная из двух живых шарниров слишком грубая — $0{,}265$; с 12 итог $0{,}0101$, но мертвы 4 из 12 (три из них — уже при инициализации).
Что видно на рисунке

Сеть из ReLU не умеет рисовать гладкое — только ломаные. Из 6 нейронов к шагу 1500 живы 5, и их изломы стоят примерно в точках $-2{,}5$, $-1{,}2$, $-0{,}4$, $0{,}3$ и $1{,}0$: у вершин синусоиды (около $\pm1$ и у левого края) и по краям её почти прямого участка вокруг нуля. Лишние нейроны не обязательно помогают: при 12 нейронах часть умирает, а часть дублирует соседей (изломы в $-1{,}2$ и $-1{,}0$, в $-0{,}25$ и $-0{,}09$).

Умирающий ReLU

Нейрон «мёртв», если на всех обучающих примерах $w^\top x+b\le0$. Тогда его выход всегда 0, градиенты по $w$ и $b$ всегда 0 (см. формулу выше), и градиентный шаг сам по себе его не оживит. Для нейрона первого слоя, чьи входы — неизменные данные, это навсегда (при обычном SGD). В глубоких слоях вход нейрона меняется вместе с предыдущими слоями, а инерция momentum и Adam ещё какое-то время двигает параметры, поэтому нейроны изредка оживают — но рассчитывать на это нельзя.

Как это происходит: один большой шаг градиентного спуска сильно уменьшает сдвиг $b$ или поворачивает $w$ так, что гиперплоскость нейрона уходит за пределы облака данных. Чем больше шаг обучения, тем чаще это случается.

Рисунок 6. Сеть из 64 нейронов ReLU на 128 точках $y=\sin(3x_1)+x_2$, $x\in[-1;1]^2$, мини-батчи по 16, обычный SGD, 600 шагов, одна и та же инициализация Хе ($\operatorname{Var}w=2/2=1$ при двух входах, сдвиги 0). Справа — нейроны: синие живы (яркость — доля точек, где нейрон включён), красные мертвы. При $\eta=0{,}3$ уже за первые 5 шагов умирает $91\%$ нейронов, к концу — $97\%$, MSE застревает на $0{,}137$. При $\eta=0{,}2$ мертва четверть ($27\%$), MSE $0{,}004$; при $\eta=0{,}1$ и $0{,}03$ мёртвых нет (MSE $0{,}005$ и $0{,}041$ — малый шаг просто медленнее).

Как лечить:

  • умеренный шаг обучения, разогрев (warm-up) и обрезка градиента;
  • нормализация и адаптивные оптимизаторы: BatchNorm перед активацией центрирует вход каждого нейрона на батче, а Adam ограничивает шаг каждого параметра величиной порядка $\eta$, так что один огромный градиент не уносит сдвиг далеко (риск это снижает, но не исключает);
  • активации с ненулевым наклоном слева — Leaky ReLU, PReLU, ELU, GELU, SiLU: градиент слева не равен нулю, и нейрон может вернуться;
  • аккуратная инициализация: сдвиги 0 (иногда небольшой положительный), веса по Хе. Сильно отрицательные сдвиги убивают нейроны ещё до обучения.

Инициализация Хе: откуда двойка

Пусть $z=\sum_{j=1}^{n}w_jh_j$, веса независимы, $\mathbb Ew_j=0$, $\operatorname{Var}w_j=c/n$. Тогда $\operatorname{Var}z=c\cdot q$, где $q=\mathbb E[h^2]$ — средний квадрат входов. Если $z$ симметрична относительно нуля, ReLU обнуляет ровно половину её распределения, и

$$q_{l}=\mathbb E\bigl[\operatorname{ReLU}(z)^2\bigr]=\frac12\operatorname{Var}z=\frac c2\,q_{l-1}\qquad\Longrightarrow\qquad q_L=q_0\Bigl(\frac c2\Bigr)^{L}$$

При $c=1$ (как для tanh) сигнал вдвое слабеет на каждом слое, при $c=3$ — растёт в полтора раза. Сохраняет масштаб только $c=2$: это инициализация Хе (He et al., 2015), $\operatorname{Var}w=2/n_\text{in}$. Обратный проход устроен так же (с $n_\text{out}$ вместо $n_\text{in}$; при одинаковой ширине слоёв это одно и то же), поэтому градиенты тоже не затухают и не взрываются.

Рисунок 7. Средний квадрат активаций $q_l$ на каждом из 30 слоёв случайной сети ширины 100 (логарифмическая шкала), оранжевый пунктир — теория $q_0(c/2)^l$. При $c=2$ отношение $q_{30}/q_0=2{,}66$; при $c=1$ — $2{,}47\cdot10^{-9}$ (теория $9{,}3\cdot10^{-10}$); при $c=3$ — $5{,}1\cdot10^5$ (теория $1{,}9\cdot10^5$). Множитель $\approx2{,}66$ во всех трёх случаях один и тот же: веса одинаковые, а ReLU положительно однороден, поэтому $c$ лишь умножает весь сигнал на $(c/2)^{L/2}$; отклонение от теории — случайная флуктуация конечной ширины. Доля активных нейронов на последнем слое — $51\%$, почти ровно половина.
Немного истории

Идея выпрямителя давняя: её использовал ещё Фукусима (1969). В глубокое обучение ReLU вошёл в 2010–2011 годах (Наир и Хинтон; Глоро, Борд и Бенжио), а в статье об AlexNet (2012) четырёхслойная свёрточная сеть с ReLU дошла до ошибки 25% на обучающей выборке CIFAR-10 в 6 раз быстрее, чем такая же сеть с tanh. В 2015 году Хе и соавторы вывели инициализацию $2/n$ и показали, что с ней с нуля обучается даже 30-слойная ReLU-сеть, которая с инициализацией Ксавье не учится.

В коде

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

pythonimport numpy as np

def relu(x):
    return np.maximum(0.0, x)

def relu_grad(x):
    # субградиент: в точке 0 берём 0, как PyTorch и TensorFlow
    return (x > 0).astype(float)

x = np.array([-3.0, 0.0, 2.5])
print(relu(x), relu_grad(x))     # [0.  0.  2.5] [0. 0. 1.]

# «Мёртвые» нейроны: ни одного положительного входа на всём наборе данных
rng = np.random.default_rng(0)
X = rng.normal(size=(1000, 20))
W = rng.normal(size=(20, 64)) * np.sqrt(2 / 20)   # инициализация Хе
for b0 in (0.0, -5.0):
    Z = X @ W + b0
    dead = np.mean((Z > 0).sum(axis=0) == 0)
    print(b0, f"{dead:.0%}")     # 0.0 0%  и  -5.0 66%
pythonimport torch
import torch.nn as nn

x = torch.tensor([-1.0, 0.0, 2.0], requires_grad=True)
torch.relu(x).sum().backward()
print(x.grad)                    # tensor([0., 0., 1.]) — в нуле 0

# Инициализация Хе: Var w = 2 / fan_in
layer = nn.Linear(512, 512)
nn.init.kaiming_normal_(layer.weight, mode="fan_in", nonlinearity="relu")
nn.init.zeros_(layer.bias)

# Блок FFN исходного Transformer: Linear → ReLU → Linear
ffn = nn.Sequential(nn.Linear(512, 2048), nn.ReLU(), nn.Linear(2048, 512))
# nn.ReLU(inplace=True) экономит память, но портит вход, если он ещё нужен
Правило

ReLU — плюс инициализация Хе (kaiming_normal_ с nonlinearity='relu'), сдвиги 0, разумный шаг обучения. Время от времени проверяйте долю нейронов, которые ни разу не включились на батче: если она растёт, уменьшите шаг или перейдите на Leaky ReLU / GELU.

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

  1. ReLU на выходе регрессии, где цель может быть отрицательной. Сеть физически не сможет выдать $y<0$. На выходе регрессии — линейный слой; ReLU на выходе уместен только для заведомо неотрицательных величин (и даже тогда часто лучше softplus: у ReLU на выходе при отрицательном входе нулевой градиент).
  2. Инициализация как для tanh. С $\operatorname{Var}w=1/n$ сигнал в глубокой ReLU-сети затухает как $2^{-L}$: через 30 слоёв в $2^{30}\approx10^9$ раз (рисунок 7). Берите инициализацию Хе.
  3. Слишком большой шаг обучения. Массово убивает нейроны, и восстановить их нельзя (рисунок 6). Симптом — потери застыли, а доля нулевых активаций близка к 100%.
  4. «Производная ReLU в нуле равна 1/2» или «не определена — значит, ошибка». Математически в нуле есть субдифференциал $[0;1]$, любое его значение допустимо; библиотеки берут 0. На обучение это практически не влияет.
  5. inplace=True там, где вход нужен дальше. Операция затирает вход; если он используется в остаточной связи или для обратного прохода другой операции, PyTorch выдаст ошибку или результат будет неверным.
  • Leaky ReLU: $\max(\alpha x,x)$ — ненулевой наклон $\alpha$ слева лечит умирание.
  • GELU и SiLU: $x\Phi(x)$ и $x\sigma(x)$ — гладкие «вентили» вместо жёсткого $x\cdot\mathbb 1[x>0]$; вдали от нуля ведут себя как ReLU.
  • Сигмоида: производная softplus — это $\sigma(\beta x)$; ReLU вытеснил сигмоиду из скрытых слоёв из-за насыщения.
  • tanh: насыщается с обеих сторон; для tanh — инициализация Ксавье, для ReLU — Хе.
  • Huber и Triplet loss: срезка $\max(0,\cdot)$ встречается и в функциях потерь.
  • Adam и SGD: от выбора оптимизатора и шага зависит, сколько нейронов умрёт.

Итоги

1) $\operatorname{ReLU}(x)=\max(0,x)=\frac{x+|x|}2$ — вентиль: вход умножается на $\mathbb 1[x>0]$. 2) Производная — ступенька 0/1, в нуле субдифференциал $[0;1]$, на практике 0; справа нет насыщения. 3) Сумма шарниров $v_k\operatorname{ReLU}(x-c_k)$ — любая ломаная; на плоскости сеть из ReLU — многогранник из линейных областей, глубина умножает их число. 4) softplus — гладкий ReLU, его производная — сигмоида. 5) Большой шаг обучения убивает нейроны навсегда. 6) Инициализация Хе $\operatorname{Var}w=2/n_\text{in}$ компенсирует то, что ReLU обнуляет половину сигнала.

Проверь себя

1. Чему равно $\operatorname{ReLU}(x)-\operatorname{ReLU}(-x)$?
2. Что вернёт PyTorch как градиент ReLU в точке $x=0$?
3. Сеть с одним скрытым слоем из 5 нейронов ReLU и одним входом $x$. Каким может быть её график?
4. Почему нейрон ReLU может «умереть» навсегда?
5. Какую дисперсию весов предлагает инициализация Хе для слоя с $n_\text{in}$ входами?