ReLU 和 Sigmoid 都属于激活函数,但它们的作用和应用场景有很大区别,这也是为什么在这个模型中会同时使用它们:
神经网络中的线性层(如nn.Linear)本质上只是加权求和,多层线性层堆叠仍然等价于单层线性层(因为线性变换的复合还是线性变换)。激活函数的加入引入了非线性因素,使网络能够学习复杂的非线性模式。
- 数学形式:
ReLU(x) = max(0, x),即负数输入变为 0,正数保持不变。
- 作用:
- 引入非线性:使网络能够学习复杂的曲线关系(例如区分 "x [0] > x [4]" 这种非线性条件)。
- 缓解梯度消失:相比 Sigmoid/Tanh,ReLU 在正数区域梯度恒为 1,训练更稳定。
- 稀疏激活:一部分神经元可能被 "激活"(输出 > 0),另一部分被抑制(输出 = 0),类似生物神经元的激活机制。
- 应用场景:通常用于隐藏层(如你的模型中 5→8 的第一层之后)。
self.activation = torch.sigmoid
- 数学形式:
sigmoid(x) = 1 / (1 + exp(-x)),将输入压缩到 (0,1) 区间。
- 作用:
- 二分类概率输出:在你的模型中,最终输出需要表示 "样本属于正类的概率",Sigmoid 恰好满足这个需求(输出范围 0~1)。
- 历史原因:早期神经网络常用 Sigmoid 作为激活函数,但现在隐藏层基本被 ReLU 取代(原因见下文)。
- 应用场景:通常用于二分类问题的输出层。
如果将模型改为:
会导致以下问题:
- 梯度消失:Sigmoid 在输入值较大或较小时,梯度接近 0,导致深层网络无法有效训练。
- 输出偏移:Sigmoid 输出始终为正数,破坏了数据分布的对称性,可能导致学习效率降低。
- 计算效率低:指数运算比 ReLU 的
max(0,x)更耗时。
- ReLU(中间层):负责引入非线性,使网络能够学习复杂模式。
- Sigmoid(输出层):将回归值映射到概率区间 [0,1],符合二分类任务的需求。
如果移除 ReLU:
- 无论堆叠多少线性层,整个网络仍然等价于单层线性模型(因为线性变换的复合还是线性变换)。
- 无法学习 "x [0] > x [4]" 这种非线性规则,模型性能会严重受限。
| 激活函数 | 数学表达式 | 图像特点 | 应用场景 |
| ReLU |
max(0,x) |
折线,右侧斜率为 1 |
隐藏层 |
| Sigmoid |
1/(1+e^(-x)) |
S 型曲线,输出压缩到 (0,1) |
输出层(二分类概率) |
- Tanh:输出范围 (-1,1),比 Sigmoid 更对称,适用于需要零中心化输出的场景。
- LeakyReLU:
max(αx, x),解决 ReLU 的 "神经元死亡" 问题(当输入为负时,仍有小梯度)。
- Swish、GELU:更复杂的激活函数,在 Transformer 等模型中表现优异。
在你的模型中:
- ReLU帮助网络从 5 维输入中提取非线性特征,增强表达能力。
- Sigmoid将最终输出转换为概率值,符合二分类任务的目标。
这是深度学习中的标准做法,通过组合不同类型的激活函数,充分发挥各自的优势。