Зачем она нужна
У ReLU два недостатка: в нуле у неё излом, а слева она выбрасывает весь сигнал вместе с градиентом. SiLU (Sigmoid Linear Unit) устроена иначе: вход $x$ умножается на сигмоиду от самого себя. Большой положительный вход проходит почти целиком, большой отрицательный почти полностью гасится, а около нуля пропускается «частично» — плавно, без изломов.
Ту же функцию с параметром, $x\,\sigma(\beta x)$, называют Swish. При $\beta=1$ это ровно SiLU; в PyTorch и других библиотеках так и пишут: nn.SiLU.
Где она встречается:
- большие языковые модели — LLaMA, Qwen, Mistral и PaLM используют SiLU внутри блока SwiGLU (раздел 7); в конфигурациях моделей это строка
hidden_act = "silu"; - компьютерное зрение — EfficientNet (2019) построен на Swish, детекторы YOLOv5 и YOLOv8 — на SiLU;
- мобильные сети — MobileNetV3 использует «жёсткий» Swish, дешёвое кусочно-полиномиальное приближение $x\cdot\operatorname{ReLU6}(x+3)/6$;
- обучение с подкреплением — Элфвинг, Утибе и Дойя (2017) применили её для аппроксимации функций ценности под именем SiLU.
$\operatorname{SiLU}(x)=x\,\sigma(x)$. Далеко справа она почти равна $x$, далеко слева — почти 0, как ReLU, но гладкая. Она немонотонна: минимум $\approx-0{,}278$ в точке $x\approx-1{,}278$. Производная $\sigma(x)\bigl(1+x(1-\sigma(x))\bigr)$ равна $0{,}5$ в нуле и превышает 1 при $x>1{,}278$ (максимум $\approx1{,}100$). В LLM SiLU работает вентилем в SwiGLU: $\operatorname{SiLU}(W_1x)\odot W_3x$.
Интуиция: вход сам решает, сколько себя пропустить
Представьте кран, ручку которого крутит сам поток. Сигмоида $\sigma(x)$ — это степень открытия крана, от 0 до 1. Если вход большой и положительный, кран открыт почти полностью ($\sigma\approx1$) и выход почти равен входу. Если вход сильно отрицательный, кран почти закрыт, и выход близок к нулю. Такой механизм называют самовентилем (self-gating): вход одновременно и сигнал, и решение о том, сколько сигнала пропустить.
Потяните синюю точку. Бирюзовая кривая — вентиль $\sigma(x)$, синяя — произведение $x\cdot\sigma(x)$. Обратите внимание на область около $x=-1$: вентиль уже прикрыт, но не до конца, а вход отрицательный — и выход проваливается ниже нуля.
Справа синяя кривая прижимается к прямой $y=x$, слева — к нулю: в этих областях SiLU почти не отличается от ReLU. Вся разница сосредоточена в полосе примерно $-5<x<5$, где вентиль открыт частично. Именно там ReLU делает резкий излом, а SiLU — плавный изгиб с небольшой «ямкой» слева.
Формула по косточкам
Соберём SiLU из двух знакомых деталей и посмотрим на неё в нескольких записях.
- $x$
- вход нейрона (пре-активация); он же — сигнал, который нужно пропустить;
- $\sigma(x)=\frac{1}{1+e^{-x}}$
- сигмоида, число из $(0;\,1)$ — доля сигнала, которая пройдёт;
- $x\cdot\sigma(x)$
- результат: при $\sigma\approx1$ выход $\approx x$, при $\sigma\approx0$ выход $\approx0$.
Через гиперболический тангенс ($\sigma(x)=\tfrac12(1+\tanh\tfrac x2)$) получается запись, которая многое объясняет:
Сравните с ReLU: $\operatorname{ReLU}(x)=\frac{x}{2}+\frac{|x|}{2}$. Нечётные части у них одинаковые, а чётная часть SiLU, $\frac x2\tanh\frac x2$, — это сглаженный модуль $\frac{|x|}{2}$: при больших $|x|$ тангенс равен $\pm1$, и они совпадают, а около нуля вместо угла получается парабола $\approx\frac{x^2}{4}$.
| $x$ | $\sigma(x)$ | $\operatorname{SiLU}(x)$ | $\operatorname{SiLU}'(x)$ |
|---|---|---|---|
| −5 | 0,0067 | −0,0335 | −0,0265 |
| −3 | 0,0474 | −0,1423 | −0,0881 |
| −1,2785 | 0,2178 | −0,2785 | 0,0000 |
| −1 | 0,2689 | −0,2689 | 0,0723 |
| 0 | 0,5000 | 0,0000 | 0,5000 |
| 1 | 0,7311 | 0,7311 | 0,9277 |
| 2 | 0,8808 | 1,7616 | 1,0908 |
| 3 | 0,9526 | 2,8577 | 1,0881 |
| 5 | 0,9933 | 4,9665 | 1,0265 |
В таблице видны три особенности: отрицательные значения слева (самое глубокое — $-0{,}2785$), производная $0{,}5$ в нуле и производная больше 1 при $x=2$ и $x=3$.
Свойства
- Гладкость: SiLU бесконечно дифференцируема — нет ни одного излома.
- Асимптоты: $\operatorname{SiLU}(x)-x\to0$ при $x\to+\infty$ и $\operatorname{SiLU}(x)\to0$ при $x\to-\infty$, причём в обоих случаях экспоненциально быстро.
- Немонотонность: функция убывает на $(-\infty;\,x^*)$ и возрастает на $(x^*;\,+\infty)$, где $x^*\approx-1{,}2785$.
- Ограниченность снизу: область значений $[-0{,}2785;\,+\infty)$. Сверху не ограничена.
- Связь с ReLU: $\operatorname{ReLU}(x)-\operatorname{SiLU}(x)=|x|\,\sigma(-|x|)$ — чётная функция от 0 до $0{,}2785$. SiLU всегда лежит ниже ReLU, но не дальше чем на $0{,}2785$.
- Антисимметрия разности: $\operatorname{SiLU}(x)-\operatorname{SiLU}(-x)=x$, потому что $\sigma(x)+\sigma(-x)=1$.
- Выпуклость: функция выпукла на интервале $(-2{,}3994;\,2{,}3994)$ и вогнута вне его; концы интервала $\pm2{,}3994$ — точки перегиба.
Минимум: где и почему −0,278
Минимум находится там, где производная равна нулю. Результат удобно записать через W-функцию Ламберта — решение уравнения $We^{W}=c$:
Вывод через W-функцию Ламберта
Производная (раздел 5) равна $\sigma(x)\bigl(1+x(1-\sigma(x))\bigr)$. Сигмоида положительна, поэтому ноль даёт только скобка: $1+x(1-\sigma)=0$, то есть $1-\sigma(x)=-1/x$.
Сразу получаем значение минимума: $\sigma(x^*)=1+1/x^*$, и $\operatorname{SiLU}(x^*)=x^*\sigma(x^*)=x^*+1$.
Теперь найдём $x^*$. Так как $1-\sigma(x)=\sigma(-x)=\frac{1}{1+e^{x}}$, уравнение принимает вид $1+e^{x}=-x$. Положим $u=-x-1$; тогда $x=-u-1$ и
Отсюда $x^*=-1-W(e^{-1})\approx-1{,}2785$ и $\operatorname{SiLU}(x^*)=x^*+1=-W(e^{-1})\approx-0{,}2785$. Красивое совпадение: глубина ямы и её расстояние от точки $x=-1$ — одно и то же число.
Семейство Swish-β
Если добавить в вентиль крутизну $\beta$, получится семейство Swish:
При $\beta=0$ вентиль всегда открыт наполовину, и функция линейна. При $\beta\to\infty$ сигмоида превращается в ступеньку, и получается ReLU. Swish-β — это мост между линейной функцией и ReLU, а SiLU — точка $\beta=1$ на этом мосту. Замена $u=\beta x$ показывает, что все члены семейства — один и тот же график в другом масштабе: $\operatorname{Swish}_\beta(x)=\frac{1}{\beta}\operatorname{SiLU}(\beta x)$.
Название SiLU (Sigmoid Linear Unit) впервые появилось в статье Хендрикса и Гимпела о GELU (2016). Элфвинг, Утибе и Дойя (2017) применили $x\,\sigma(x)$ в обучении с подкреплением. Рамачандран, Зоф и Ле (2017) независимо нашли $x\,\sigma(\beta x)$ автоматическим поиском по пространству формул-кандидатов и назвали Swish; обучаемое $\beta$ мало что добавило, и на практике закрепилось $\beta=1$. Отсюда два имени одной функции: silu в PyTorch и Hugging Face, swish в Keras.
Производная: больше единицы и меньше нуля
По правилу произведения производная SiLU складывается из двух частей: вентиля и того, как быстро вентиль открывается.
Вывод по шагам
Правило произведения: $(x\cdot\sigma(x))'=1\cdot\sigma(x)+x\cdot\sigma'(x)$.
Производная сигмоиды известна: $\sigma'(x)=\sigma(x)(1-\sigma(x))$ (вывод — на странице сигмоиды). Подставляем и выносим $\sigma(x)$:
Ещё одна полезная форма — через значение самой функции $f=\operatorname{SiLU}(x)$: раскрыв скобки, получим $\sigma+x\sigma-x\sigma^2=f+\sigma(1-f)$. Её используют реализации: на обратном проходе нужны только уже посчитанные $f$ и $\sigma$.
Свойства производной:
- $\operatorname{SiLU}'(0)=\sigma(0)=\tfrac12$ — в нуле наклон ровно половина;
- $\operatorname{SiLU}'(x)+\operatorname{SiLU}'(-x)=1$ — это производная тождества $\operatorname{SiLU}(x)-\operatorname{SiLU}(-x)=x$;
- производная отрицательна при $x<-1{,}2785$ (левее минимума) с наименьшим значением $\approx-0{,}0998$ при $x\approx-2{,}3994$;
- производная больше 1 при $x>1{,}2785$ — по симметрии из предыдущего пункта — с максимумом $\approx1{,}0998$ при $x\approx2{,}3994$; затем она стремится к 1 сверху.
Точки $\pm2{,}3994$ — корни уравнения $x\tanh\frac{x}{2}=2$: там обращается в ноль вторая производная
Наклон больше 1 значит, что на участке $x>1{,}28$ SiLU «догоняет» прямую $y=x$, от которой отстала около нуля. Выход SiLU никогда не превышает вход при $x>0$ ($\sigma<1$), так что взрыва нет: наклон лишь ненамного больше 1 и быстро возвращается к 1.
Гладкость и родственники: ReLU и GELU
Три функции на одном графике: ReLU, SiLU и GELU $=x\,\Phi(x)$, где $\Phi$ — функция распределения стандартного нормального закона. Посмотрите не только на сами функции, но и на первую и вторую производные: именно там видна разница в гладкости.
- ReLU: первая производная — ступенька, вторая — дельта-функция. Для оптимизатора поверхность ошибки состоит из плоских кусков с резкими рёбрами.
- SiLU и GELU: производные непрерывны, вторые производные — гладкие «горбы» с максимумом в нуле ($0{,}5$ у SiLU, $2\varphi(0)\approx0{,}798$ у GELU). Ландшафт ошибки становится гладким, и градиент меняется постепенно.
- GELU ≈ Swish с $\beta=1{,}702$: $x\,\Phi(x)\approx x\,\sigma(1{,}702x)$ с наибольшей ошибкой около $0{,}02$. Поэтому GELU похожа на уменьшенную в $1{,}702$ раза копию SiLU: минимум мельче и ближе к нулю ($-0{,}170$ при $x\approx-0{,}752$ против $-0{,}278$ при $x\approx-1{,}278$; у самой Swish-1,702 было бы $-0{,}164$). А вот максимум производной у GELU выше ($1{,}129$ против $1{,}100$), и масштабом это не объяснить: у всех Swish-β он один и тот же, $1{,}0998$. Это уже разница между нормальным и логистическим законом (см. ниже).
Вероятностный смысл: случайный вентиль
У SiLU и GELU есть общее объяснение. Пусть нейрон пропускает вход целиком, если вход больше случайного шума $\varepsilon$, и полностью блокирует, если меньше: $y=x\cdot[\varepsilon\le x]$. Тогда среднее значение выхода
Сигмоида — функция распределения логистического закона, $\Phi$ — нормального. Значит, SiLU — это «усреднённый ReLU со случайным порогом»: вместо того чтобы резать ровно в нуле, нейрон режет в случайной точке около нуля, а в среднем получается гладкая кривая.
SwiGLU: SiLU в больших языковых моделях
В трансформере после блока внимания стоит полносвязный блок (feed-forward network, FFN). Классический вариант — $W_2\,\operatorname{ReLU}(W_1x)$ (или GELU вместо ReLU). Шазир (2020) предложил заменить его на вентильный блок (gated linear unit), где одна ветка решает, сколько пропустить из другой:
- $x\in\mathbb R^{d}$
- вектор токена размерности $d$ (у LLaMA-7B $d=4096$);
- $W_1x$
- ветка вентиля: через SiLU решает, какие компоненты пропускать и насколько;
- $W_3x$
- ветка значения: линейная, без активации — то, что пропускается;
- $\odot$
- поэлементное произведение двух векторов размерности $h$ (скрытый размер);
- $W_2$
- проекция обратно в размерность $d$.
Для одной компоненты это функция двух чисел: $g(a,b)=\operatorname{SiLU}(a)\cdot b$, где $a$ — компонента ветки вентиля, $b$ — ветки значения. Её и стоит увидеть в 3D.
Градиенты здесь простые и поучительные: $\frac{\partial g}{\partial b}=\operatorname{SiLU}(a)$ — ветка значения учится пропорционально тому, насколько открыт вентиль; $\frac{\partial g}{\partial a}=\operatorname{SiLU}'(a)\cdot b$ — вентиль учится, только если через него есть что пропускать.
Почему скрытый размер 8/3·d
В SwiGLU три матрицы вместо двух. Чтобы число параметров осталось как у обычного FFN с $h=4d$ ($2\cdot d\cdot4d=8d^2$), скрытый размер уменьшают до $h=\frac{2}{3}\cdot4d=\frac83 d$: тогда $3\cdot d\cdot\frac83d=8d^2$. У LLaMA-7B $\frac83\cdot4096\approx10923$ округлено вверх до кратного 256: $h=11008$. Получается $3\cdot4096\cdot11008=135\,266\,304$ параметра на блок против $134\,217\,728$ у FFN с $h=4d$ — всего на $0{,}8\%$ больше.
Вентильные линейные блоки (GLU, $\sigma(W_1x)\odot W_3x$) предложили Дофин и др. (2017) для свёрточных языковых моделей. Шазир (2020) сравнил варианты с разными вентилями — ReGLU, GEGLU, SwiGLU — и все они обошли обычный FFN. SwiGLU выбрали для PaLM (2022), затем для LLaMA (2023), и с тех пор он стал стандартом открытых LLM: Qwen, Mistral и многие другие.
SiLU в обучении
Чем гладкая активация помогает на практике? Сеть из нейронов ReLU собирает функцию из отрезков прямых, сеть из SiLU — из гладких «изгибов». Если целевая зависимость гладкая, SiLU-нейронам проще её повторить. Кроме того, у SiLU нет «мёртвой» зоны: производная обращается в ноль лишь в одной точке $x^*\approx-1{,}278$, а при остальных отрицательных входах она маленькая, но не нулевая, так что нейрон не «умирает», как ReLU с отрицательным входом.
Эксперимент: сеть $1\to6\to1$ приближает кривую $y=\sin1{,}5x+0{,}3x$ по 40 точкам. Две сети стартуют с одинаковых весов, отличаются только активацией; обучение — Adam с шагом $0{,}03$, 2000 шагов.
Чтобы не делать выводов по одному запуску, мы повторили опыт для восьми разных инициализаций. SiLU оказалась точнее во всех восьми, с выигрышем от $1{,}4$ до $5{,}2$ раза. Но это свойство гладкой цели: на кусочно-линейной зависимости ReLU может оказаться не хуже. Поэтому выбор активации — эмпирический вопрос, и в больших моделях его решают экспериментом.
SiLU дороже ReLU: нужна экспонента (или tanh), а для обратного прохода приходится хранить вход. На GPU это обычно незаметно на фоне матричных умножений, но на мобильных устройствах используют «жёсткий» Swish $x\cdot\operatorname{ReLU6}(x+3)/6$ — кусочно-полиномиальное приближение без экспонент.
В коде
Наивная запись x / (1 + np.exp(-x)) при $x=-1000$ вычисляет $e^{1000}$ и выдаёт предупреждение о переполнении (результат всё равно $-0$). Аккуратнее считать сигмоиду через $\tanh$: $\sigma(x)=\tfrac12(1+\tanh\tfrac x2)$ — тангенс никогда не переполняется.
pythonimport numpy as np
def sigmoid(x):
# σ(x) = (1 + tanh(x/2)) / 2 — без переполнения при любом x
return 0.5 * (1.0 + np.tanh(0.5 * x))
def silu(x):
return x * sigmoid(x)
def silu_grad(x):
s = sigmoid(x)
return s * (1.0 + x * (1.0 - s)) # = SiLU(x) + σ(x)·(1 − SiLU(x))
def swish(x, beta=1.0):
return x * sigmoid(beta * x)
np.set_printoptions(precision=4, suppress=True)
x = np.array([-1000.0, -1.0, 0.0, 1.0, 2.3994])
print(silu(x)) # [-0. -0.2689 0. 0.7311 2.1997]
print(silu_grad(x)) # [-0. 0.0723 0.5 0.9277 1.0998]
pythonimport torch
import torch.nn as nn
import torch.nn.functional as F
z = torch.tensor([-2.0, 0.0, 2.0], requires_grad=True)
y = F.silu(z) # tensor([-0.2384, 0.0000, 1.7616])
y.sum().backward()
print(z.grad) # tensor([-0.0908, 0.5000, 1.0908])
class SwiGLU(nn.Module):
"""FFN-блок LLaMA и Qwen: W2 · (SiLU(W1 x) ⊙ W3 x)."""
def __init__(self, d, hidden):
super().__init__()
self.w1 = nn.Linear(d, hidden, bias=False) # ветка вентиля
self.w3 = nn.Linear(d, hidden, bias=False) # ветка значения
self.w2 = nn.Linear(hidden, d, bias=False) # обратно в размер d
def forward(self, x):
return self.w2(F.silu(self.w1(x)) * self.w3(x))
ffn = SwiGLU(4096, 11008) # размеры LLaMA-7B
print(sum(p.numel() for p in ffn.parameters())) # 135266304
PyTorch: nn.SiLU, F.silu. TensorFlow/Keras: tf.nn.silu, activation="swish" (это та же функция с $\beta=1$). В конфигурациях Hugging Face: hidden_act="silu". Встроенная функция инициализации nn.init.calculate_gain не знает SiLU: обычно берут инициализацию по умолчанию или как для ReLU.
Частые ошибки
- «SiLU неотрицательна, как ReLU». Нет: при $x<0$ она отрицательна, минимум $-0{,}278$. Если дальше идёт что-то, что требует неотрицательного входа (например, логарифм или корень), это важно.
- «SiLU монотонна». Нет: левее $x\approx-1{,}278$ она убывает, и её производная там отрицательна. Обратной функции на всей прямой нет.
- Путаница SiLU и GELU. Это разные функции: $x\sigma(x)$ и $x\Phi(x)$. Подменять одну другой в предобученной модели нельзя — веса подобраны под конкретную активацию.
- Активация на обеих ветках SwiGLU. SiLU стоит только на ветке вентиля $W_1x$; ветка значения $W_3x$ линейна. Лишняя активация меняет модель.
- Скрытый размер $4d$ в SwiGLU. С тремя матрицами это даёт в $1{,}5$ раза больше параметров, чем у обычного FFN. Для честного сравнения берут $h\approx\frac83d$.
- Наивная формула с
exp(-x)в самописных ядрах: переполнение при больших отрицательных $x$ и потеря точности в половинной точности. ПользуйтесьF.siluили формой через tanh.
Связи с другими формулами
- Сигмоида: вентиль SiLU; производная $\sigma'=\sigma(1-\sigma)$ входит в $\operatorname{SiLU}'$.
- ReLU: предел $x\sigma(\beta x)$ при $\beta\to\infty$; $\operatorname{ReLU}-\operatorname{SiLU}=|x|\sigma(-|x|)\le0{,}2785$.
- GELU: $x\Phi(x)\approx x\sigma(1{,}702x)$ — тот же самовентиль с нормальным шумом вместо логистического.
- Leaky ReLU: другой способ не обнулять отрицательную часть — прямая $\alpha x$ вместо гладкой «ямки».
- tanh: $\operatorname{SiLU}(x)=\frac x2\bigl(1+\tanh\frac x2\bigr)$.
- Softmax и Adam: соседи SwiGLU в трансформере — механизм внимания и оптимизатор, которым такие модели обучают.
Итоги
1) $\operatorname{SiLU}(x)=x\,\sigma(x)=\frac x2\bigl(1+\tanh\frac x2\bigr)$ — самовентиль: вход решает, какую долю себя пропустить. 2) Гладкая, немонотонная, минимум $-W(e^{-1})\approx-0{,}278$ в точке $\approx-1{,}278$; всегда ниже ReLU не более чем на $0{,}278$. 3) $\operatorname{SiLU}'=\sigma(1+x(1-\sigma))$: $0{,}5$ в нуле, больше 1 при $x>1{,}278$, максимум $\approx1{,}100$. 4) Swish-β связывает линейную функцию ($\beta=0$) и ReLU ($\beta\to\infty$); GELU $\approx$ Swish-1,702. 5) Вероятностно — ReLU со случайным логистическим порогом, усреднённый. 6) В LLM — вентиль SwiGLU: $W_2(\operatorname{SiLU}(W_1x)\odot W_3x)$ со скрытым размером $\approx\frac83d$.