神经网络激活函数:从ReLU到前沿SwiGLU

摘要

本文全面介绍了神经网络中常用的激活函数,包括Sigmoid、Tanh、ReLU等传统函数,以及2017年后出现的Swish、Mish、SwiGLU等新兴函数。每个函数均提供数学定义、优缺点分析、Python实现代码和可视化图像,并附有实际应用建议和性能对比数据,帮助读者根据具体任务选择合适的激活函数。

1. 激活函数核心概念与作用

激活函数是神经网络中的非线性变换组件,其主要作用包括:

  • 引入非线性:使神经网络能够学习复杂模式和关系
  • 控制输出范围:限制神经元输出值在合理范围内
  • 影响梯度流动:通过导数影响反向传播中的梯度计算
  • 增强表示能力:提高模型对复杂数据的拟合能力

理想激活函数的特性

  • 非线性
  • 可微分(至少几乎处处可微)
  • 单调性(多数但不必须)
  • 近似恒等性(f(x)≈x near 0)

2. 传统激活函数

2.1 Sigmoid

数学定义 :f(x)=11+e−xf(x) = \frac{1}{1 + e^{-x}}f(x)=1+e−x1
优点 :输出范围(0,1),平滑可微,适合概率输出
缺点 :梯度消失严重,输出非零中心,指数计算成本高
适用场景:二分类输出层,LSTM门控机制

python 复制代码
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

2.2 Tanh

数学定义 :f(x)=ex−e−xex+e−xf(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}}f(x)=ex+e−xex−e−x
优点 :输出范围(-1,1),零中心化,梯度强于Sigmoid
缺点 :梯度消失问题仍然存在
适用场景:RNN隐藏层

python 复制代码
def tanh(x):
    return np.tanh(x)

2.3 ReLU (Rectified Linear Unit)

数学定义 :f(x)=max⁡(0,x)f(x) = \max(0, x)f(x)=max(0,x)
优点 :计算高效,缓解梯度消失,稀疏激活
缺点 :神经元死亡问题,输出非零中心化
适用场景:CNN隐藏层(默认选择)

python 复制代码
def relu(x):
    return np.maximum(0, x)

2.4 Leaky ReLU

数学定义 :f(x)={xx≥0αxx<0f(x) = \begin{cases} x & x \geq 0 \\ \alpha x & x < 0 \end{cases}f(x)={xαxx≥0x<0
优点 :缓解Dead ReLU问题,保持计算效率
缺点 :需手动设定α参数,性能提升有限
适用场景:替代ReLU的保守选择

python 复制代码
def leaky_relu(x, alpha=0.1):
    return np.where(x >= 0, x, alpha * x)

2.5 GELU (Gaussian Error Linear Unit)

数学定义 :f(x)=x⋅Φ(x)f(x) = x \cdot \Phi(x)f(x)=x⋅Φ(x),其中Φ(x)是标准正态分布的累积分布函数
优点 :结合随机正则化,适合预训练模型,平滑且非单调
缺点 :需近似计算,计算成本较高
适用场景:Transformer、BERT类模型

python 复制代码
def gelu(x):
    return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x**3)))

2.6 ELU (Exponential Linear Unit)

数学定义 :f(x)={xx≥0α(ex−1)x<0f(x) = \begin{cases} x & x \geq 0 \\ \alpha(e^x - 1) & x < 0 \end{cases}f(x)={xα(ex−1)x≥0x<0
优点

  • 负值区域平滑,避免神经元死亡问题
  • 输出均值接近零,加速学习
  • 比ReLU家族有更好的泛化性能

缺点

  • 指数计算成本较高
  • 需要手动选择α参数(通常设为1.0)

适用场景:对噪声鲁棒性要求较高的任务

python 复制代码
def elu(x, alpha=1.0):
    return np.where(x >= 0, x, alpha * (np.exp(x) - 1))

2.7 SELU (Scaled Exponential Linear Unit)

数学定义 :f(x)=λ{xx≥0α(ex−1)x<0f(x) = \lambda \begin{cases} x & x \geq 0 \\ \alpha(e^x - 1) & x < 0 \end{cases}f(x)=λ{xα(ex−1)x≥0x<0

其中 λ≈1.0507\lambda \approx 1.0507λ≈1.0507, α≈1.67326\alpha \approx 1.67326α≈1.67326

优点

  • 具有自归一化特性,保持网络激活值的均值和方差稳定
  • 适合深层网络,无需Batch Normalization
  • 理论上可以训练极深的网络

缺点

  • 需要特定的权重初始化(LeCun正态初始化)
  • 在某些架构中可能不如Batch Normalization + ReLU有效

适用场景:极深的前馈神经网络,希望减少或避免使用Batch Normalization的场景

python 复制代码
def selu(x, alpha=1.67326, scale=1.0507):
    return scale * np.where(x >= 0, x, alpha * (np.exp(x) - 1))

3. 新兴激活函数(2017年后)

3.1 Swish (2017)

数学定义 :f(x)=x⋅σ(βx)f(x) = x \cdot \sigma(\beta x)f(x)=x⋅σ(βx),其中σ是sigmoid函数,β是可学习参数
核心特性 :自门控机制,平滑且非单调
优点

  • 在负值区域有非零输出,避免神经元死亡
  • 在深层网络中表现优于ReLU
  • 有助于缓解梯度消失问题

缺点 :计算量比ReLU大(包含sigmoid运算)
适用场景:深层CNN,Transformer中的GLU层

python 复制代码
def swish(x, beta=1.0):
    return x * (1 / (1 + np.exp(-beta * x)))

3.2 Mish (2019)

数学定义 :f(x)=x⋅tanh⁡(ln⁡(1+ex))f(x) = x \cdot \tanh(\ln(1 + e^x))f(x)=x⋅tanh(ln(1+ex))
核心特性 :自正则化的非单调激活函数
优点

  • 保持小的负值信息,消除死亡ReLU现象
  • 连续可微,提供更平滑的优化landscape
  • 在计算机视觉任务中表现出色

缺点 :计算复杂度较高(包含多个指数运算)
性能数据:在ImageNet数据集上,ResNet-50使用Mish比ReLU提高约1%的Top-1准确率

python 复制代码
def softplus(x):
    return np.log(1 + np.exp(x))

def mish(x):
    return x * np.tanh(softplus(x))

3.3 SwiGLU (2020)

数学定义 :SwiGLU(x)=Swish1(xW+b)⊗(xV+c)\text{SwiGLU}(x) = \text{Swish}_1(xW + b) \otimes (xV + c)SwiGLU(x)=Swish1(xW+b)⊗(xV+c)
核心特性 :门控线性单元变体,结合Swish激活函数
优点

  • 门控机制允许模型学习复杂特征交互
  • 在Transformer的FFN层中表现优异
  • 被PaLM、LLaMA等大语言模型采用

缺点

  • 参数量增加(需要三个权重矩阵)
  • 计算复杂度很高

适用场景:大型Transformer模型中的FFN层

python 复制代码
# SwiGLU的简化实现
def swiglu(x, w1, v, w2):
    return np.dot(swish(np.dot(x, w1)) * np.dot(x, v), w2)

3.4 Logish (2021)

数学定义 :f(x)=x⋅ln⁡(1+Sigmoid(x))f(x) = x \cdot \ln(1 + \text{Sigmoid}(x))f(x)=x⋅ln(1+Sigmoid(x))
核心特性 :基于对数和sigmoid组合的新型激活函数
优点

  • 适合学习率较大的浅层和深层网络
  • 在复杂网络中表现良好
  • 在图像去雨等任务中展现良好泛化性

缺点 :相对较新,应用验证不够广泛
性能数据:在CIFAR-10数据集上的ResNet-50网络中达到94.8%的Top-1准确率

python 复制代码
def logish(x):
    sigmoid = 1 / (1 + np.exp(-x))
    return x * np.log(1 + sigmoid)

3.5 ACON (2021)

数学定义 :ACON家族通过学习参数自动决定是否激活
核心特性 :可学习的激活函数,能够平滑切换线性和非线性
优点

  • 自适应调整激活形态
  • 比Swish更灵活
  • 在多个任务上表现优异

缺点:需要学习额外参数,增加模型复杂度

python 复制代码
# ACON-C的简化实现
def acon_c(x, p1, p2):
    return (p1 - p2) * x * torch.sigmoid(beta * x) + p2 * x

4. 可视化对比

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# 设置绘图风格
plt.style.use('default')
plt.rcParams['figure.figsize'] = [10, 8]
plt.rcParams['font.size'] = 12

# 定义x轴范围
x = np.linspace(-4, 4, 1000)

# 计算数值梯度函数
def compute_gradient(f, x, eps=1e-5):
    """使用中心差分法计算数值梯度"""
    return (f(x + eps) - f(x - eps)) / (2 * eps)

# 创建带有坐标轴的绘图函数
def plot_activation_function(name, func, x_range):
    """绘制单个激活函数的完整分析图"""
    fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 5))
    
    # 计算函数值、梯度和二阶导数
    y = func(x_range)
    gradient = compute_gradient(func, x_range)
    second_gradient = compute_gradient(lambda x: compute_gradient(func, x), x_range)
    
    # 绘制函数图像
    ax1.plot(x_range, y, 'b-', linewidth=3)
    ax1.set_title(f'{name} Function')
    ax1.set_xlabel('x')
    ax1.set_ylabel('f(x)')
    ax1.grid(True, alpha=0.3)
    ax1.axhline(y=0, color='k', linestyle='-', alpha=0.3)  # x轴
    ax1.axvline(x=0, color='k', linestyle='-', alpha=0.3)  # y轴
    
    # 绘制梯度图像
    ax2.plot(x_range, gradient, 'r-', linewidth=3)
    ax2.set_title(f'{name} Gradient')
    ax2.set_xlabel('x')
    ax2.set_ylabel("f'(x)")
    ax2.grid(True, alpha=0.3)
    ax2.axhline(y=0, color='k', linestyle='-', alpha=0.3)  # x轴
    ax2.axvline(x=0, color='k', linestyle='-', alpha=0.3)  # y轴
    
    # 绘制二阶导数图像
    ax3.plot(x_range, second_gradient, 'g-', linewidth=3)
    ax3.set_title(f'{name} Second Derivative')
    ax3.set_xlabel('x')
    ax3.set_ylabel("f''(x)")
    ax3.grid(True, alpha=0.3)
    ax3.axhline(y=0, color='k', linestyle='-', alpha=0.3)  # x轴
    ax3.axvline(x=0, color='k', linestyle='-', alpha=0.3)  # y轴
    
    plt.tight_layout()
    plt.show()

# 1. Sigmoid 函数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

plot_activation_function('Sigmoid', sigmoid, x)

# 2. Tanh 函数
def tanh(x):
    return np.tanh(x)

plot_activation_function('Tanh', tanh, x)

# 3. ReLU 函数
def relu(x):
    return np.maximum(0, x)

plot_activation_function('ReLU', relu, x)

# 4. Leaky ReLU 函数
def leaky_relu(x, alpha=0.1):
    return np.where(x >= 0, x, alpha * x)

plot_activation_function('Leaky ReLU', lambda x: leaky_relu(x, 0.1), x)

# 5. GELU 函数
def gelu(x):
    # GELU近似计算
    return 0.5 * x * (1 + np.tanh(np.sqrt(2 / np.pi) * (x + 0.044715 * x**3)))

plot_activation_function('GELU', gelu, x)

# 6. Swish 函数
def swish(x, beta=1.0):
    return x * (1 / (1 + np.exp(-beta * x)))

plot_activation_function('Swish', lambda x: swish(x, 1.0), x)

# 7. Mish 函数
def softplus(x):
    return np.log(1 + np.exp(x))

def mish(x):
    return x * np.tanh(softplus(x))

plot_activation_function('Mish', mish, x)

# 8. Logish 函数
def logish(x):
    sigmoid_val = 1 / (1 + np.exp(-x))
    return x * np.log(1 + sigmoid_val)

plot_activation_function('Logish', logish, x)

# 9. ELU 函数
def elu(x, alpha=1.0):
    return np.where(x >= 0, x, alpha * (np.exp(x) - 1))

plot_activation_function('ELU', lambda x: elu(x, 1.0), x)

# 10. SELU 函数
def selu(x, alpha=1.67326, scale=1.0507):
    return scale * np.where(x >= 0, x, alpha * (np.exp(x) - 1))

plot_activation_function('SELU', selu, x)

# 11. 额外:绘制所有激活函数的对比图(带坐标轴)
plt.figure(figsize=(14, 10))
activation_functions = {
    'Sigmoid': sigmoid,
    'Tanh': tanh,
    'ReLU': relu,
    'Leaky ReLU': lambda x: leaky_relu(x, 0.1),
    'GELU': gelu,
    'Swish': lambda x: swish(x, 1.0),
    'Mish': mish,
    'Logish': logish
}

for i, (name, func) in enumerate(activation_functions.items(), 1):
    plt.subplot(3, 3, i)
    y = func(x)
    plt.plot(x, y, linewidth=2.5)
    plt.title(name)
    plt.xlabel('x')
    plt.ylabel('f(x)')
    plt.grid(True, alpha=0.3)
    plt.axhline(y=0, color='k', linestyle='-', alpha=0.5)  # x轴
    plt.axvline(x=0, color='k', linestyle='-', alpha=0.5)  # y轴

plt.tight_layout()
plt.show()

# 12. 绘制负区域放大图(带坐标轴)
plt.figure(figsize=(12, 8))
x_neg = np.linspace(-2, 0, 500)
selected_functions = {
    'ReLU': relu,
    'Leaky ReLU (α=0.1)': lambda x: leaky_relu(x, 0.1),
    'GELU': gelu,
    'Swish (β=1)': lambda x: swish(x, 1.0),
    'Mish': mish,
    'ELU (α=1)': lambda x: elu(x, 1.0)
}

for name, func in selected_functions.items():
    plt.plot(x_neg, func(x_neg), label=name, linewidth=2.5)

plt.title('Activation Functions in Negative Region (Zoomed)')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.5)  # x轴
plt.axvline(x=0, color='k', linestyle='-', alpha=0.5)  # y轴
plt.legend()
plt.show()

# 13. 绘制梯度对比图(带坐标轴)
plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
for name, func in [('ReLU', relu), ('Swish', lambda x: swish(x, 1.0)), ('Mish', mish)]:
    gradient = compute_gradient(func, x)
    plt.plot(x, gradient, label=name, linewidth=2.5)
plt.title('Activation Function Gradients')
plt.xlabel('x')
plt.ylabel("f'(x)")
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.5)  # x轴
plt.axvline(x=0, color='k', linestyle='-', alpha=0.5)  # y轴
plt.legend()

plt.subplot(1, 2, 2)
for name, func in [('ReLU', relu), ('Swish', lambda x: swish(x, 1.0)), ('Mish', mish)]:
    gradient = compute_gradient(func, x)
    plt.semilogy(x, np.abs(gradient) + 1e-10, label=name, linewidth=2.5)
plt.title('Gradient Magnitude (Log Scale)')
plt.xlabel('x')
plt.ylabel("|f'(x)|")
plt.grid(True, alpha=0.3)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.5)  # x轴
plt.axvline(x=0, color='k', linestyle='-', alpha=0.5)  # y轴
plt.legend()

plt.tight_layout()
plt.show()

关键观察与洞察

通过添加坐标轴,我们可以更清楚地观察到以下特性:

1. Sigmoid
  • 函数值始终为正,输出范围(0,1)
  • 函数关于点(0, 0.5)对称
  • 梯度在x=0处最大,向两侧递减
2. Tanh
  • 函数关于原点对称,是奇函数
  • 输出范围(-1,1),零中心化
  • 梯度在x=0处最大,向两侧递减
3. ReLU
  • 在x<0时函数值为0,x>0时函数值为x
  • 在x=0处不可导(梯度从0突变到1)
  • 二阶导数几乎处处为0
4. Leaky ReLU
  • 在x<0时函数值为αx(α=0.1),x>0时函数值为x
  • 解决了ReLU的死亡神经元问题
  • 在x=0处连续但不可导
5. GELU
  • 函数在负区域有平滑过渡
  • 函数值在x=0处为0,但曲线平滑
  • 梯度在负区域不为零,缓解了梯度消失问题
6. Swish
  • 非单调函数,在负区域有小的正值
  • 函数通过原点(0,0)
  • 梯度比ReLU更平滑
7. Mish
  • 非常平滑的激活函数,通过原点
  • 在负区域保持小的正值,避免神经元死亡
  • 梯度特性优异,有助于缓解梯度消失问题
8. Logish
  • 基于对数和sigmoid的组合
  • 在负区域有更平缓的变化
  • 函数通过原点
9. ELU
  • 在负区域有指数渐近线,趋近于-α
  • 输出均值接近零,加速学习
  • 梯度在负区域不为零
10. SELU
  • 具有自归一化特性
  • 在负区域有指数变化,正区域线性
  • 函数通过原点

应用建议

  1. 需要零中心化输出:选择Tanh、Mish或GELU
  2. 防止神经元死亡:使用Leaky ReLU、Mish或Swish
  3. 需要平滑梯度:选择Mish、Swish或GELU
  4. 计算效率优先:使用ReLU或Leaky ReLU
  5. 自归一化网络:考虑使用SELU(配合LeCun初始化)

5. 性能对比与选择指南(更新)

5.1 定量性能对比(更新)

激活函数 ImageNet (ResNet-50) CIFAR-10 (ResNet-56) 计算开销 参数增加
ReLU 76.2% (基线) 92.8% (基线)
Swish +0.6-0.9% +0.5-0.8% 1.5-2× 可选
Mish +0.8-1.2% +0.7-1.0% 2-2.5×
GELU +0.4-0.7% +0.3-0.6% 1.8-2.2×
SwiGLU +1.5-2.5% (Transformer) N/A 3-4× 显著
ACON-C +1.0-1.5% +0.9-1.3% 1.8-2.2× 轻微
ELU +0.3-0.6% +0.2-0.5% 2-2.5×
SELU +0.5-0.8% (适合极深网络) +0.4-0.7% 2-2.5×

5.2 选择策略与实用建议(更新)

  1. 默认起始选择

    • CNN架构:从ReLU开始,然后尝试Swish/Mish
    • Transformer架构:优先选择GELU或SwiGLU
    • 资源受限环境:使用ReLU或Leaky ReLU
    • 极深网络:考虑使用SELU(配合LeCun初始化)
  2. 高级选择

    • 追求最佳性能:尝试ACON家族或Meta-ACON
    • 需要自归一化特性:使用SELU
    • 对噪声敏感的任务:考虑使用ELU
  3. 实践技巧

    • 使用He初始化配合ReLU家族
    • 对于Mish/Swish,学习率可适当增大10-20%
    • 使用混合精度训练时可考虑GELU的数值稳定性
    • 使用SELU时确保权重初始化为LeCun正态初始化
  4. 部署考虑

    • 移动端部署:ReLU6 (clipped ReLU) 或 Hard-Swish
    • 服务器端:可根据精度需求选择更复杂的激活函数
    • 边缘设备:考虑使用分段线性近似替代指数运算

6. 总结与展望(更新)

激活函数的发展从简单的饱和函数(Sigmoid/Tanh)到线性整流函数(ReLU家族),再到近年来的自门控、可学习激活函数(Swish、Mish、SwiGLU、ACON),体现了神经网络设计理念的演进。未来趋势包括:

  1. 可学习激活函数:如ACON,能够根据数据和任务自适应调整
  2. 硬件感知设计:专为特定硬件(如NPU、GPU)优化的激活函数
  3. 动态激活机制:根据输入特征动态调整激活形态
  4. 理论分析深化:更深入地理解激活函数如何影响优化和泛化
  5. 条件激活函数:根据网络层深度、宽度等条件选择不同激活函数

选择激活函数时,建议从业者基于具体任务、计算预算和精度要求进行实证评估,没有单一的"最佳"激活函数,只有最适合特定场景的选择。随着自动机器学习(AutoML)技术的发展,未来可能会有更多自动选择和设计激活函数的方法出现。

相关推荐
雍凉明月夜4 分钟前
深度学习网络笔记Ⅱ(常见网络分类1)
人工智能·笔记·深度学习
北岛寒沫4 分钟前
北京大学国家发展研究院 经济学辅修 经济学原理课程笔记(第十三课 垄断竞争)
人工智能·经验分享·笔记
AI营销实验室6 分钟前
AI 工具何高质量的为销售线索打分?
大数据·人工智能
Wang201220137 分钟前
RNN和LSTM对比
人工智能·算法·架构
xueyongfu11 分钟前
从Diffusion到VLA pi0(π0)
人工智能·算法·stable diffusion
jackylzh27 分钟前
配置pytorch环境,并调试YOLO
人工智能·pytorch·yolo
杜子不疼.35 分钟前
AI Ping双款新模型同步免费解锁:GLM-4.7与MiniMax M2.1实测
人工智能
打码人的日常分享35 分钟前
企业数据资产管控和数据治理解决方案
大数据·运维·网络·人工智能·云计算
百***787537 分钟前
小米MiMo-V2-Flash深度解析:国产开源大模型标杆与海外AI接入方案
人工智能·开源
大数据追光猿38 分钟前
【Prompt】Prompt Caching:原理、实现与高并发价值
人工智能·大模型·prompt·agent