本文系统梳理深度学习中常见的激活函数,从经典的 Sigmoid、Tanh,到 ReLU 家族、ELU 家族,再到 Transformer 中常见的 GELU、SiLU,以及 Softmax、GLU 等输出层和门控结构。
重点不仅介绍公式,还会从函数形状、导数、梯度传播、优缺点、适用场景以及 PyTorch 实现几个角度理解为什么要使用某一种激活函数。
1. 为什么神经网络需要激活函数?
假设一个神经网络只有线性层:
连续堆叠两个线性层:
代入:
整理:
本质上仍然可以写成:
也就是说:
无论堆叠多少层线性层,只要中间没有非线性函数,整个网络最终仍然只是一个线性变换。
因此神经网络通常采用:
这里的 就是激活函数(Activation Function)。
激活函数的核心作用就是:
给神经网络引入非线性表达能力。
2. 激活函数到底应该关注什么?
评价一个激活函数,通常需要关注以下几个方面。
2.1 是否具有非线性
这是最基本的要求。
如果:,那么它实际上没有引入任何非线性。
2.2 梯度是否容易消失
训练神经网络时需要反向传播。
假设:
那么:
如果连续多层网络的梯度 都非常小:
随着网络深度增加,可能出现:
这就是++梯度消失(Vanishing Gradient)++。
2.3 是否容易出现梯度爆炸
相反,如果:
在深层网络中也可能导致梯度不断放大:
因此一个好的激活函数通常希望++梯度传播比较稳定++。
2.4 是否存在饱和区
所谓饱和,就是输入继续变化,但输出几乎不变。
例如 :
当:
有:
当:
有:
因此两边都会进入饱和区。
2.5 是否零中心
如果激活函数输出全部为正 ,例如 的输出范围:
那么神经元输出不是零中心的。
相比之下:
**是零中心的。**这会影响优化过程。
3. 激活函数整体分类
可以把常见激活函数大致分成下面几类:
激活函数
│
├── 经典激活函数
│ ├── Sigmoid
│ └── Tanh
│
├── ReLU 家族
│ ├── ReLU
│ ├── Leaky ReLU
│ ├── PReLU
│ ├── RReLU
│ └── ReLU6
│
├── ELU 家族
│ ├── ELU
│ ├── SELU
│ └── CELU
│
├── 平滑激活函数
│ ├── Softplus
│ ├── GELU
│ ├── SiLU / Swish
│ └── Mish
│
├── Hard 激活函数
│ ├── HardTanh
│ ├── HardSigmoid
│ └── HardSwish
│
├── 收缩类激活函数
│ ├── Softshrink
│ ├── Hardshrink
│ └── Tanhshrink
│
├── 特殊激活函数
│ ├── Softsign
│ ├── LogSigmoid
│ └── Threshold
│
└── 输出/门控函数
├── Softmax
├── LogSoftmax
├── GLU
└── Gumbel-Softmax
PyTorch 当前文档中的非线性函数覆盖了上述大部分函数。
下面逐个分析。
4. Sigmoid:最经典的激活函数
Sigmoid 又称 Logistic Function。
公式:
输出范围:
sigmoid 函数
4.1 Sigmoid 的导数
Sigmoid 的导数:
因为:
所以:
最大梯度只有:
这意味着当网络很深时,++梯度连续相乘,很容易变得非常小++。
4.2 Sigmoid 的优点
最大的优点是:
因为输出范围在(0,1)之间,输出可以直接解释为概率。
例如二分类:
因此 Sigmoid 非常适合:
- 二分类输出层
- 多标签分类输出层
- 概率建模
4.3 Sigmoid 的缺点
缺点 1:梯度消失
当 很大或者很小时:
导致梯度消失。
缺点 2:不是零中心
输出范围:
始终大于 0。
缺点 3:计算涉及指数函数
相比 ReLU:
Sigmoid 计算成本更高。
4.4 PyTorch 实现
import torch
import torch.nn as nn
activation = nn.Sigmoid()
x = torch.tensor([-2., -1., 0., 1., 2.])
y = activation(x)
print(y)
5. Tanh:零中心版本的 Sigmoid
Tanh 公式:
输出范围:
tanh 函数
5.1 Tanh 和 Sigmoid 的关系
两者存在关系:
所以可以理解为:
Tanh 本质上是经过缩放和平移后的 Sigmoid。
5.2 Tanh 导数
当:
时:
相比 Sigmoid 最大导数:
Tanh ++在零点附近梯度更大++。
5.3 Tanh 的优点
最大优点:
零中心。
因为:
因此相比 Sigmoid,++更适合隐藏层中的特征表示++。
5.4 Tanh 的缺点
依然存在饱和问题:
所以++深层网络仍然可能产生梯度消失++。
6. ReLU:深度学习最重要的激活函数之一
ReLU:
也就是:
ReLU 函数
6.1 ReLU 的导数
因此正数区域:
++不会产生梯度衰减。++
6.2 ReLU 为什么这么成功?
核心原因可以概括为:
计算简单
+
正区间梯度为 1
+
稀疏激活
+
训练速度快
尤其是:
这对深层网络的梯度传播非常重要。
6.3 ReLU 最大的问题:死亡 ReLU
如果:
那么:
并且:
如果++某个神经元长期处于负区间++:
输入
↓
负数
↓
ReLU = 0
↓
梯度 = 0
↓
参数无法更新
↓
神经元"死亡"
这就是:
Dying ReLU Problem
7. Leaky ReLU:解决死亡 ReLU
Leaky ReLU 给负数区域留了一条"小通道"。
公式:
其中:
通常是一个很小的常数,例如:
7.1 和 ReLU 的区别
ReLU:
Leaky ReLU:
因此:
++负数区域依然存在梯度。++
7.2 PyTorch
nn.LeakyReLU(negative_slope=0.01)
PyTorch 的定义也是:
8. PReLU:让负区间斜率自己学习
PReLU:
和 Leaky ReLU 最大区别:
Leaky ReLU 的
是人为指定的,而 PReLU 的
是++可学习参数++。
也就是说:
Leaky ReLU
alpha = 固定
PReLU
a = 神经网络自己学习
PyTorch 官方定义中,PReLU 的 negative slope 是 learnable parameter。
8.1 优点
模型可以自动学习:
负数区域应该保留多少信息。
8.2 缺点
增加了可学习参数。虽然参数量很少,但也增加了模型复杂度。
9. RReLU:随机化 Leaky ReLU
RReLU:Randomized Leaky ReLU。
它和 Leaky ReLU 类似,但是负区间斜率不是固定的,而是从一个随机分布中采样。
因此训练过程中:
其中 是随机变量。它具有一定正则化效果。
10. ReLU6:把 ReLU 限制到 6
公式:
即:
PyTorch 当前文档也采用这一形式。
10.1 为什么是 6?
ReLU6 最经典的应用之一是移动端网络,例如 MobileNet。
限制最大值可以让激活值处于:
这样的有限范围中,有利于某些低精度量化和移动端计算。
11. ELU:让负数区域更加平滑
ELU:
11.1 ReLU 和 ELU 的区别
ReLU:
ELU:
因此 ELU 在负数区域不是直接截断,而是逐渐趋向:
11.2 ELU 的优点
相比 ReLU:
- 负区间仍然有梯度
- 输出可以为负
- 均值更容易靠近 0
- 函数更加平滑
12. SELU:Self-Normalizing Neural Network
SELU:Self-normalizing ELU。
公式:
经典参数:
,
PyTorch 当前实现也使用这些参数。
12.1 SELU 的核心思想
普通神经网络可能出现:
层数增加
↓
均值/方差逐渐偏移
↓
激活值分布不稳定
↓
训练困难
SELU 希望通过激活函数自身的性质,使网络中的激活分布趋向稳定。
所以叫:
Self-Normalizing Neural Network
12.2 SELU 使用时需要注意什么?
SELU 并不是简单地:
"比 ReLU 更好,所以所有地方都应该换 SELU。"
它依赖特定的网络结构和初始化条件。PyTorch 的初始化文档指出,自归一化网络场景下使用 SELU 时,初始化应考虑相应的线性增益设置。
13. CELU:Continuously Differentiable ELU
CELU:
与 ELU 相似,但设计目标之一是让函数在参数变化下具有更好的连续可微性质。PyTorch 当前文档提供了 CELU。
14. Softplus:ReLU 的平滑版本
Softplus:
当:
时:
14.1 为什么叫 Softplus?
因为它可以看作 ReLU 的平滑版本:
而:
PyTorch 官方将 Softplus 描述为 ReLU 的 smooth approximation。
14.2 Softplus 的导数
非常重要:
也就是说:
Softplus 的梯度就是 Sigmoid。
15. GELU:Transformer 中非常重要的激活函数
GELU:Gaussian Error Linear Unit。
公式:
其中:
是标准高斯分布的累积分布函数。
GELU 函数
PyTorch 官方也是采用:
的定义。
15.1 GELU 的近似公式
实际计算中经常使用:
PyTorch 支持精确形式和 tanh approximation。
15.2 GELU 和 ReLU 的区别
ReLU:
GELU:
不会简单地把负数全部砍掉,而是根据输入大小进行平滑的概率式"门控"。
因此 GELU:
- 更加平滑
- 梯度更加连续
- 不存在传统 ReLU 的硬截断
GELU 在 Transformer 系列模型中非常常见。
16. SiLU / Swish:自门控激活函数
SiLU:
也就是:
PyTorch 中 SiLU 也称为 Swish。
16.1 为什么叫自门控?
因为:
里面的:
因此可以理解为:
输入自己决定应该保留多少信息。
16.2 SiLU 的特点
SiLU:
- 非单调
- 平滑
- 可导
- 没有 ReLU 的硬截断
- 负区间仍有输出
因此在很多现代神经网络中表现优秀。
17. Mish:比 SiLU 更复杂的平滑激活
Mish:
展开:
PyTorch 官方当前实现也采用这一形式。
17.1 Mish 的特点
Mish 属于:
平滑、非单调、自正则化风格的激活函数。
相比 ReLU:
ReLU
负数 → 直接变 0
Mish
负数 → 保留一部分信息
相比 SiLU:
SiLU = x × sigmoid(x)
Mish = x × tanh(softplus(x))
18. GELU、SiLU、Mish 三者怎么理解?
这三个是现代深度学习中非常重要的一组函数。
| 激活函数 | 核心公式 | 特点 |
|---|---|---|
| GELU | 平滑概率式门控 | |
| SiLU | Sigmoid 自门控 | |
| Mish | 更复杂的平滑非单调函数 |
可以简单记忆:
ReLU
↓
"硬截断"
GELU
↓
"平滑选择"
SiLU
↓
"Sigmoid 自门控"
Mish
↓
"Softplus + Tanh 自门控"
19. HardTanh
HardTanh 是 Tanh 的分段线性近似。
典型形式:
优点:
- 计算简单
- 没有指数运算
- 容易硬件实现
缺点:
- 两端饱和
- 梯度为 0
20. HardSigmoid
HardSigmoid 是 Sigmoid 的分段线性近似。
常见形式:
不同框架的具体截断参数可能不同。
主要思想:
用简单的线性函数近似 Sigmoid。
因此适合:
- 移动端
- 嵌入式设备
- 低计算量模型
21. HardSwish
HardSwish 是 Swish/SiLU 的高效近似。
常见形式:
即:
它的目标是:
保留 Swish 的效果,同时降低计算成本。
MobileNetV3 等轻量网络中经常使用。
PyTorch 当前函数接口中也包含 hardswish。
22. Softsign
Softsign:
输出范围:
和 Tanh 类似,也是有界的零中心函数。区别在于 Softsign 不使用指数函数,因此计算形式更加简单。PyTorch 当前文档定义也是:
23. LogSigmoid
LogSigmoid:
也就是:
相比直接计算:
实际实现通常会采用数值稳定的方式。PyTorch 当前提供 LogSigmoid。
24. Threshold
Threshold 是一个非常简单的阈值函数:
其中:
-
:threshold
-
:替代值
它更多用于特殊的神经网络结构,而不是现代深度网络的默认激活函数。
25. Shrink 类激活函数
这类函数的思想不是单纯进行非线性变换,而是:
将较小的响应压缩或者直接置零。
25.1 Hardshrink
也可以理解为:
大于阈值 → 保留
小于负阈值 → 保留
中间区域 → 置零
25.2 Softshrink
Softshrink 更平滑:
它和稀疏表示、信号处理中的 shrinkage 思想存在联系。
25.3 Tanhshrink
也属于特殊的 shrinkage 激活函数。
26. Softmax:分类输出层最重要的函数之一
Softmax 与前面那些逐元素激活函数不太一样。
假设:
Softmax:
于是:
因此可以得到一个概率分布:
softmax 函数
26.1 例子
假设模型输出:
Softmax 后得到:
类别 A:较高概率
类别 B:中等概率
类别 C:较低概率
所以 Softmax 常用于:
多分类任务的输出层。
27. Sigmoid 和 Softmax 的区别
这是机器学习面试中的高频问题。
二分类
通常:
SigmoidSigmoid
例如:
猫 / 非猫
多分类
例如:
猫
狗
鸟
汽车
通常:
因为这些类别通常要求:
多标签分类
例如一张图片同时包含:
人
汽车
狗
树
这时每个类别相互独立。
通常使用:
SigmoidSigmoid
而不是 Softmax。
因此:
单标签二分类
→ Sigmoid
单标签多分类
→ Softmax
多标签分类
→ Sigmoid
28. LogSoftmax
LogSoftmax:
等价于:
它经常和:
NLLLoss
一起使用。
29. GLU:门控线性单元
GLU:
Gated Linear Unit。
如果输入:
XX
先沿某个维度拆成:
然后:
其中:表示逐元素乘法。
PyTorch 官方也采用:
的定义。
29.1 GLU 的核心思想
可以理解成:
输入
↓
拆成两部分
↓
A B
│ │
│ Sigmoid
│ │
└──── × ───┘
↓
Output
其中负责决定:
A 中哪些信息应该被保留。
这就是:
门控机制(Gating Mechanism)
30. Gumbel-Softmax
Gumbel-Softmax 用于解决一个经典问题:
如何让神经网络对离散类别进行采样,同时仍然可以进行梯度反向传播?
普通:
概率
↓
argmax
↓
离散类别
argmax 不可导。
Gumbel-Softmax 使用可微近似,使网络能够学习离散选择。
典型形式:
其中:
-
:类别概率
-
:Gumbel noise
-
:temperature
当:
输出会越来越接近 one-hot。
31. 为什么 ReLU 家族如此重要?
可以把激活函数的发展理解成一条路线:
Sigmoid
↓
梯度消失
↓
Tanh
↓
仍然存在饱和
↓
ReLU
↓
解决正区间梯度问题
↓
Dying ReLU
↓
Leaky ReLU / PReLU
↓
进一步平滑
↓
ELU / SELU
↓
现代平滑激活
↓
GELU / SiLU / Mish
这也是理解激活函数发展历史最重要的一条线。
32. 各激活函数核心对比
| 激活函数 | 输出范围 | 零中心 | 平滑 | 负区间有梯度 | 主要问题 |
|---|---|---|---|---|---|
| Sigmoid | × | ✓ | ✓ | 梯度消失 | |
| Tanh | ✓ | ✓ | ✓ | 梯度消失 | |
| ReLU | × | × | × | Dead ReLU | |
| Leaky ReLU | × | × | ✓ | 超参数 | |
| PReLU | × | × | ✓ | 增加参数 | |
| RReLU | × | × | ✓ | 随机性 | |
| ELU | 较接近 | ✓ | ✓ | 指数计算 | |
| SELU | 特定缩放 | 接近 | ✓ | ✓ | 使用条件较严格 |
| Softplus | × | ✓ | ✓ | 计算成本 | |
| GELU | 近似 | ✓ | ✓ | 计算复杂 | |
| SiLU | 近似 | ✓ | ✓ | 计算复杂 | |
| Mish | 近似 | ✓ | ✓ | 计算复杂 | |
| ReLU6 | × | × | × | 饱和 | |
| HardSwish | 有界/近似 | × | 分段 | 部分 | 非完全平滑 |
| Softsign | ✓ | ✓ | ✓ | 饱和 | |
| Softmax | --- | ✓ | --- | 不用于隐藏层常规激活 |
这类综合比较也与现有激活函数综述对 Sigmoid/Tanh、ReLU、ELU、学习型激活等类别的划分基本一致。
33. CNN 中应该使用什么激活函数?
传统 CNN:
Conv
↓
BatchNorm
↓
ReLU
这是非常经典的组合。
例如:
class CNNBlock(nn.Module):
def __init__(self, in_channels, out_channels):
super().__init__()
self.block = nn.Sequential(
nn.Conv2d(
in_channels,
out_channels,
kernel_size=3,
padding=1
),
nn.BatchNorm2d(out_channels),
nn.ReLU(inplace=True)
)
def forward(self, x):
return self.block(x)
现代 CNN 也可能使用:
- ReLU
- LeakyReLU
- SiLU
- GELU
- Mish
- HardSwish
34. Transformer 中为什么经常看到 GELU?
Transformer 的 FFN 通常类似:
这里的:
(.)
就是激活函数。经典 Transformer 系列中常见:GELU,现代架构中也越来越常见:SiLU以及 GLU 系列结构。读模型源码时,看到:
nn.GELU()
是非常正常的。
35. 为什么现代 LLM 中越来越多出现 SiLU / SwiGLU?
普通 FFN:
而门控 FFN 可以写成:
如果使用 SiLU:
这就是典型的:
SwiGLU
核心思想不是单纯"换一个激活函数",而是:
让一部分神经元负责生成内容,另一部分负责生成门控信号。
这比传统:
具有更强的表达能力。
36. 初始化和激活函数为什么有关系?
这是很多初学者容易忽略的问题。
假设:
如果激活函数会改变信号的方差,那么网络层层传播之后:
可能越来越大或者越来越小。
因此权重初始化需要考虑激活函数。
例如 PyTorch calculate_gain() 给出了不同非线性函数对应的推荐 gain,包括:
,
以及 Leaky ReLU 的对应形式。
这就是为什么:
ReLU
→ He/Kaiming Initialization
Tanh
→ Xavier Initialization
经常被一起讨论。
37. 为什么 ReLU 通常配 He 初始化?
假设:
ReLU 会把负数直接变成 0。
为了让经过网络之后的方差保持相对稳定,经典 Kaiming/He 初始化针对 ReLU 进行了专门设计。
常见形式:
因此:
ReLU
+
Kaiming Initialization
是非常经典的组合。
38. 为什么 Tanh 常和 Xavier 初始化一起出现?
Tanh 在接近 0 时:
为了让前向传播和反向传播过程中信号保持稳定,可以使用 Xavier/Glorot 初始化。
经典形式:
因此:
Tanh
+
Xavier Initialization
是经典组合。
39. 激活函数和梯度的关系总结
可以把不同激活函数的梯度传播理解为:
Sigmoid
负数区间 ── 梯度很小
中心区间 ── 梯度最大
正数区间 ── 梯度很小
Tanh
负数区间 ── 梯度很小
中心区间 ── 梯度最大
正数区间 ── 梯度很小
ReLU
负数区间 ── 0
正数区间 ── 1
Leaky ReLU
负数区间 ── α
正数区间 ── 1
GELU / SiLU / Mish
整个区域 ── 平滑变化
这也是为什么现代网络越来越偏爱:
这类梯度传播更加平滑的函数。
40. 实际项目到底应该怎么选择?
不要记成:
"最新的激活函数一定最好。"
正确的选择方式应该是根据任务和模型结构决定。
情况 1:普通 CNN
优先:
ReLU
或者:
SiLU
情况 2:现代视觉模型
可以考虑:
GELU
轻量模型可以考虑:
HardSwish
情况 3:Transformer
常见:
GELU
现代门控 FFN:
SwiGLU
情况 4:二分类输出层
使用:
Sigmoid
但是实际 PyTorch 训练时,通常更推荐直接输出 logits,并使用:
nn.BCEWithLogitsLoss()
而不是:
Sigmoid()
+
BCELoss()
这样通常具有更好的数值稳定性。
情况 5:多分类输出层
通常:
CrossEntropyLoss
直接接 logits。
不要手动:
Softmax
+
CrossEntropyLoss
因为 CrossEntropyLoss 已经包含了相应的 log-softmax + NLL 逻辑。
情况 6:多标签分类
通常:
BCEWithLogitsLoss
对应:
Sigmoid
每一个类别独立计算概率。
41. 一个非常实用的选择表
| 场景 | 推荐 |
|---|---|
| 普通 CNN | ReLU |
| CNN 想尝试现代激活 | SiLU |
| Transformer | GELU |
| LLM FFN | SwiGLU / GLU 类 |
| 移动端模型 | HardSwish / ReLU6 |
| 二分类输出 | Sigmoid |
| 多分类输出 | Softmax(或直接 logits + CE) |
| 多标签分类 | Sigmoid |
| 需要零中心有界输出 | Tanh |
| 希望避免 Dead ReLU | Leaky ReLU / PReLU |
| 自归一化网络 | SELU |
| 平滑 ReLU | Softplus |
| 研究型实验 | GELU / SiLU / Mish 等 |
42. PyTorch 中常见激活函数代码汇总
import torch
import torch.nn as nn
activations = {
# Classic
"sigmoid": nn.Sigmoid(),
"tanh": nn.Tanh(),
# ReLU family
"relu": nn.ReLU(),
"leaky_relu": nn.LeakyReLU(),
"prelu": nn.PReLU(),
"rrelu": nn.RReLU(),
"relu6": nn.ReLU6(),
# ELU family
"elu": nn.ELU(),
"selu": nn.SELU(),
"celu": nn.CELU(),
# Smooth modern activations
"softplus": nn.Softplus(),
"gelu": nn.GELU(),
"silu": nn.SiLU(),
"mish": nn.Mish(),
# Hard activations
"hardtanh": nn.Hardtanh(),
"hardswish": nn.Hardswish(),
# Others
"softsign": nn.Softsign(),
"logsigmoid": nn.LogSigmoid(),
"tanhshrink": nn.Tanhshrink(),
"softshrink": nn.Softshrink(),
"hardshrink": nn.Hardshrink(),
}
PyTorch 当前 API 中确实提供了这些常见激活函数,包括 ReLU、LeakyReLU、PReLU、RReLU、ELU、SELU、CELU、GELU、SiLU、Mish、Softplus、Tanh、Sigmoid、Softsign、Softshrink、Hardshrink、Tanhshrink、GLU、Softmax 等。
43. 最后用一张"激活函数进化图"理解全文
激活函数
│
┌─────────────┴─────────────┐
│ │
经典激活 现代激活
│ │
┌────┴────┐ ┌───────┼────────┐
│ │ │ │ │
Sigmoid Tanh GELU SiLU Mish
│ │ │ │
│ │ │ └── Swish
│ │ │
└────┬────┘ │
│ │
梯度消失问题 │
│ │
↓ │
ReLU ────────────────→ 平滑非线性
│
├── Leaky ReLU
│
├── PReLU
│
├── RReLU
│
└── ReLU6
ELU
│
├── SELU
└── CELU
Softplus
│
└── ReLU 的平滑近似
44. 一句话记忆所有重要激活函数
如果准备机器学习/深度学习面试,可以直接这样记:
Sigmoid:输出概率。
Tanh:零中心的 Sigmoid。
ReLU:简单、高效、正区间梯度为 1。
Leaky ReLU:给 ReLU 的负区间留一条梯度通道。
PReLU:让负区间斜率自己学习。
RReLU:让负区间斜率随机化。
ReLU6:把 ReLU 限制在 0~6。
ELU:负区间使用指数函数,输出可以为负。
SELU:通过自归一化思想稳定激活分布。
Softplus:ReLU 的平滑版本。
GELU:平滑地决定信息保留多少,Transformer 常见。
SiLU/Swish:,典型自门控激活。
Mish:,平滑、非单调。
Softmax:把多个 logits 转换成概率分布。
GLU:利用门控机制控制信息流。
45. 最重要的结论
如果把整个激活函数的发展过程压缩成一句话,可以理解为:
背后的核心驱动力其实一直没有变:
如何在提供足够非线性表达能力的同时,让梯度能够稳定、高效地传播。
早期主要解决:梯度消失,于是出现:ReLU
随后解决:Dead ReLU,于是出现:LeakyReLU/PReLU/ELU
再后来更加关注:平滑性+梯度传播+表达能力+门控机制,于是出现:GELU,SiLU,Mish,GLU,SwiGLU
因此,不要把激活函数简单理解成"给神经网络增加非线性的一个函数"。从现代深度学习的角度看,激活函数实际上同时影响:
模型表达能力
↓
梯度传播
↓
优化难度
↓
激活分布
↓
参数初始化
↓
训练稳定性
↓
最终模型性能
这也是为什么在 CNN、Transformer、LLM、扩散模型以及各种多模态模型中,激活函数的选择仍然是模型设计中的一个重要组成部分。
参考资料: PyTorch 当前激活函数 API 对 ReLU、ELU、SELU、CELU、LeakyReLU、PReLU、GELU、Sigmoid、SiLU、Mish、Softplus、Softmax 等进行了完整定义;其中 GELU、SiLU、Mish 的公式及实现可以直接对应到上述介绍。