一、一句话总结

激活函数就像给神经网络装了 “非线性开关”,让它能处理复杂的曲线关系或分类问题,而不只是简单的直线划分。

二、生活案例类比

激活函数就像 “老师批改作业的方式”:

  • 线性计算是 “统计错题数”(原始分数);
  • Sigmoid 像 “按比例给分”:无论错多少题,最终成绩只在 0-100 分之间(避免负分或超满分);
  • Tanh 像 “正负评分”:做得好加分(+1 到 + 100),做得差扣分(-1 到 - 100),更公平;
  • ReLU 像 “只看对题”:对的题给分,错的题直接 0 分(简单但可能忽略进步空间);
  • Leaky ReLU 像 “错题为负分但扣分少”:错的题扣少量分(比如错 1 题扣 0.01 分),既指出错误,又不让学生彻底放弃(避免神经元死亡)。

三、拆解知识步骤

1. 由来背景

早期神经网络只有 “线性计算”(比如y=wx+b),就像只用直尺画直线 —— 无论叠多少层,结果还是直线,无法拟合曲线(比如 “房价与面积的非线性关系”“图像中复杂的边缘轮廓”)。

为了让网络能处理 “非线性问题”,科学家引入 “激活函数”:通过对线性结果做非线性变换(把直线 “掰弯”),让多层网络叠加后能拟合复杂的曲线或分类边界。

2. 目标及解决的问题

核心目标:给神经网络注入 “非线性能力”,让它能处理线性模型搞不定的复杂任务。

解决的痛点

  • 突破线性局限:线性模型无法分开 “太极图”“异或问题” 等非线性数据,激活函数通过 “掰弯” 边界实现准确划分;
  • 控制信号范围:线性计算可能让输出变得极大或极小(如输入 100→输出 10000),激活函数通过限制范围(0-1、-1-1 等)避免信号爆炸;
  • 提升学习效率:ReLU 及变种计算简单(无需指数运算),让网络训练更快。

3. 实现逻辑

所有激活函数都是神经网络 “神经元” 的 “最后一步操作”,流程统一:

  • 第一步:神经元先做线性计算(z=wx+b 汇总输入特征的加权和);
  • 第二步:将z传入激活函数,得到非线性输出(如 a=\sigma(z) “Sigmoid 输出”);
  • 第三步:这个非线性输出作为下一层的输入,层层传递后,网络整体具备拟合非线性关系的能力(比如从 “像素值” 到 “这是猫” 的复杂映射)。

4. 局限性

函数

局限性

图示

Sigmoid

输入极端值(x太大或太小)时,输出接近 1 或 0,梯度几乎为 0→导致 “梯度消失”(网络学不动)。

Tanh

虽比 Sigmoid 对称,但输入极端值时梯度仍接近 0→同样易梯度消失。

ReLU

输入为负数时输出 0,梯度也为 0→导致 “死亡神经元”(永久不更新,像阀门锈死)。

Leaky ReLU

需要人工设定\alpha(无统一标准,增加调参成本);极负输入时梯度仍弱→效果有限。

五、代码实现

import numpy as np
import matplotlib.pyplot as plt

# 设置matplotlib字体,解决中文显示问题(适用于macOS)
plt.rcParams["font.family"] = ["Arial Unicode MS", "SimHei"]
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 1. 实现激活函数
def sigmoid(x):
    """Sigmoid激活函数:将输入映射到(0, 1)"""
    return 1 / (1 + np.exp(-x))

def tanh(x):
    """Tanh激活函数:将输入映射到(-1, 1)"""
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))

def relu(x):
    """ReLU激活函数:x>0时输出x,否则输出0"""
    return np.maximum(0, x)

def leaky_relu(x, alpha=0.01):
    """Leaky ReLU激活函数:x>0时输出x,否则输出alpha*x(解决死亡ReLU问题)"""
    return np.where(x > 0, x, alpha * x)

# 2. 生成输入数据(范围从-10到10,足够展示函数特性)
x = np.linspace(-10, 10, 1000)  # 生成1000个均匀分布的点

# 3. 计算各激活函数的输出
y_sigmoid = sigmoid(x)
y_tanh = tanh(x)
y_relu = relu(x)
y_leaky_relu = leaky_relu(x)

# 4. 可视化所有激活函数
plt.figure(figsize=(12, 8))  # 设置画布大小

# 子图1:Sigmoid
plt.subplot(2, 2, 1)
plt.plot(x, y_sigmoid, color='blue')
plt.title('Sigmoid激活函数')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)  # x轴
plt.axvline(x=0, color='k', linestyle='-', alpha=0.3)  # y轴

# 子图2:Tanh
plt.subplot(2, 2, 2)
plt.plot(x, y_tanh, color='green')
plt.title('Tanh激活函数')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='k', linestyle='-', alpha=0.3)

# 子图3:ReLU
plt.subplot(2, 2, 3)
plt.plot(x, y_relu, color='red')
plt.title('ReLU激活函数')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='k', linestyle='-', alpha=0.3)

# 子图4:Leaky ReLU
plt.subplot(2, 2, 4)
plt.plot(x, y_leaky_relu, color='purple')
plt.title('Leaky ReLU激活函数 (alpha=0.01)')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=0, color='k', linestyle='-', alpha=0.3)
plt.axvline(x=0, color='k', linestyle='-', alpha=0.3)

# 调整子图间距
plt.tight_layout()
plt.show()

Logo

惟楚有才,于斯为盛。欢迎来到长沙!!! 茶颜悦色、臭豆腐、CSDN和你一个都不能少~

更多推荐