深入解析bp反向传播算法过程:从数学原理到Python实现

1次阅读
没有评论

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

image.webp

1. 单层感知机的梯度计算

我们先从最简单的单层感知机开始理解梯度计算。假设我们有一个线性神经元,其输出为:

深入解析 bp 反向传播算法过程:从数学原理到 Python 实现

$$ y = \sigma(wx + b) $$

其中 $\sigma$ 是激活函数,$w$ 是权重,$b$ 是偏置。损失函数 $L$ 通常采用均方误差:

$$ L = \frac{1}{2}(y – t)^2 $$

其中 $t$ 是目标值。根据链式法则,权重 $w$ 的梯度为:

$$ \frac{\partial L}{\partial w} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial (wx+b)} \cdot \frac{\partial (wx+b)}{\partial w} $$

2. 多层神经网络的反向传播

对于多层神经网络,误差需要从输出层反向传播到输入层。以两层网络为例,前向传播过程为:

  1. 第一层:$ z_1 = W_1x + b_1 $
  2. 第一层激活:$ a_1 = \sigma(z_1) $
  3. 第二层:$ z_2 = W_2a_1 + b_2 $
  4. 输出:$ y = \sigma(z_2) $

反向传播时,我们需要计算各层的梯度:

  1. 输出层误差:$ \delta_2 = (y-t) \cdot \sigma'(z_2) $
  2. 隐藏层误差:$ \delta_1 = (W_2^T \delta_2) \cdot \sigma'(z_1) $
  3. 权重梯度:$ \nabla W_2 = \delta_2 a_1^T $,$ \nabla W_1 = \delta_1 x^T $

3. Python 实现示例

import numpy as np

# 定义激活函数及其导数
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    s = sigmoid(x)
    return s * (1 - s)

# 网络参数
input_size = 3
hidden_size = 4
output_size = 1
learning_rate = 0.1

# 初始化权重
W1 = np.random.randn(hidden_size, input_size)
W2 = np.random.randn(output_size, hidden_size)

# 前向传播
def forward(x):
    z1 = np.dot(W1, x)
    a1 = sigmoid(z1)
    z2 = np.dot(W2, a1)
    y = sigmoid(z2)
    return y, a1, z1

# 反向传播
def backward(x, t, y, a1, z1):
    # 计算输出层误差
    delta2 = (y - t) * sigmoid_derivative(y)

    # 计算隐藏层误差
    delta1 = np.dot(W2.T, delta2) * sigmoid_derivative(a1)

    # 更新权重
    global W1, W2
    W2 -= learning_rate * np.outer(delta2, a1)
    W1 -= learning_rate * np.outer(delta1, x)

# 训练过程
for epoch in range(1000):
    # 这里应该使用实际的数据集
    x = np.random.randn(input_size)
    t = np.random.randn(output_size)

    y, a1, z1 = forward(x)
    backward(x, t, y, a1, z1)

4. 避坑指南

学习率选择

  • 太大:可能导致震荡或发散
  • 太小:训练过程缓慢
  • 建议:从 0.01 开始尝试,使用学习率衰减策略

梯度消失 / 爆炸

  • 深层网络容易出现梯度指数级减小或增大
  • 解决方案:
  • 使用 ReLU 等激活函数
  • 批归一化
  • 残差连接

激活函数选择

  • Sigmoid:容易导致梯度消失
  • ReLU:计算简单,缓解梯度消失
  • LeakyReLU:解决 ReLU 的 ” 死亡 ” 问题

5. 思考题

  1. 如何修改代码实现批量梯度下降?
  2. 不同优化器 (如 Adam) 如何改变反向传播过程?
  3. 为什么 ReLU 能缓解梯度消失问题?

通过本文的讲解和代码实现,希望读者能够深入理解 bp 反向传播的核心机制。在实际应用中,还需要考虑正则化、优化器选择等更多因素。建议读者尝试扩展代码,实现更复杂的网络结构。

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