深度学习入门:手把手实现常用激活函数的反向传播(头歌实践)

1次阅读
没有评论

共计 1729 个字符,预计需要花费 5 分钟才能阅读完成。

image.webp

核心概念:为什么需要反向传播和激活函数?

在神经网络中,反向传播是训练模型的核心算法,它通过计算损失函数对每个参数的梯度,指导参数更新。而激活函数决定了神经元是否被激活,为网络引入非线性能力。二者配合才能实现有效的学习。

深度学习入门:手把手实现常用激活函数的反向传播(头歌实践)

新手常见痛点

刚开始手动实现反向传播时,最容易卡在三个地方:

  1. 混淆对谁求导(是对输入 x 求导还是对参数 w 求导?)
  2. 梯度公式推导错误(特别是复合函数的链式法则应用)
  3. 维度不匹配导致计算崩溃

激活函数梯度推导实战

1. Sigmoid 函数

数学表达式:σ(x) = 1/(1+e^{-x})

梯度推导过程:
– 先求 σ(x) 对 x 的导数:σ'(x) = σ(x)(1-σ(x))
– 在实际反向传播时,我们会收到上游梯度 dL/dσ
– 根据链式法则,最终梯度为:dL/dx = dL/dσ * σ'(x)

Python 实现:

def sigmoid_backward(dL_dsigmoid, x):
    """
    dL_dsigmoid: 上游梯度 (dL/dσ)
    x: 前向传播时的原始输入
    返回: dL/dx
    """
    sigmoid = 1 / (1 + np.exp(-x))  # 重新计算前向传播结果
    dsigmoid_dx = sigmoid * (1 - sigmoid)  # 梯度公式
    return dL_dsigmoid * dsigmoid_dx  # 链式法则 

2. ReLU 函数

数学表达式:ReLU(x) = max(0, x)

梯度特点:
– 当 x >0 时,梯度为 1
– 当 x <= 0 时,梯度为 0

Python 实现:

def relu_backward(dL_drelu, x):
    """
    dL_drelu: 上游梯度 (dL/dReLU)
    x: 前向传播时的原始输入
    返回: dL/dx
    """
    dx = np.where(x > 0, dL_drelu, 0)  # 按条件选择梯度值
    return dx

3. Tanh 函数

数学表达式:tanh(x) = (e^x – e^{-x})/(e^x + e^{-x})

梯度推导:
– tanh'(x) = 1 – tanh²(x)
– 最终梯度:dL/dx = dL/dtanh * (1 – tanh²(x))

Python 实现:

def tanh_backward(dL_dtanh, x):
    """
    dL_dtanh: 上游梯度 (dL/dtanh)
    x: 前向传播时的原始输入
    返回: dL/dx
    """
    tanh_x = np.tanh(x)  # 重新计算前向传播结果
    dtanh_dx = 1 - tanh_x ** 2  # 梯度公式
    return dL_dtanh * dtanh_dx  # 链式法则 

单元测试验证

建议用数值梯度检验实现是否正确:

def test_gradient(func, backward_func, x=1.0, eps=1e-7):
    # 数值梯度
    fx_plus = func(x + eps)
    fx_minus = func(x - eps)
    numerical_grad = (fx_plus - fx_minus) / (2 * eps)

    # 解析梯度
    analytic_grad = backward_func(1.0, x)  # 假设上游梯度为 1

    # 比较差异
    assert abs(numerical_grad - analytic_grad) < 1e-6
    print(f"测试通过!数值梯度:{numerical_grad:.6f}, 解析梯度:{analytic_grad:.6f}")

# 测试 Sigmoid
test_gradient(lambda x: 1/(1+np.exp(-x)), sigmoid_backward)

性能考量

三种激活函数在反向传播时的特点:

  1. Sigmoid
  2. 需要重新计算前向传播结果
  3. 梯度最大值为 0.25,容易出现梯度消失

  4. ReLU

  5. 不需要存储中间结果
  6. 计算速度最快
  7. 可能有神经元死亡问题

  8. Tanh

  9. 类似 Sigmoid 需要重新计算
  10. 梯度范围 (0,1],比 Sigmoid 稍好

避坑指南

  1. 维度问题
  2. 确保输入和梯度的 shape 一致
  3. 必要时使用 np.reshape 保持维度

  4. 精度问题

  5. 对 Sigmoid/Tanh,大输入值会导致数值不稳定
  6. 可对输入做裁剪处理

  7. 中间结果存储

  8. 实践时通常在前向传播时保存计算结果
  9. 避免反向传播时重复计算

思考题

如何实现 LeakyReLU 的反向传播?提示:
– LeakyReLU(x) = max(αx, x),其中 α 是小的正数 (如 0.01)
– 反向传播时需要根据 x 的正负选择梯度系数

期待你在评论区分享自己的实现方案!

正文完
 0
评论(没有评论)