BP神经网络算法流程图详解:从数学原理到Python实现

1次阅读
没有评论

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

image.webp

1. 神经网络基础概念

BP 神经网络(Back Propagation Neural Network)是一种多层前馈神经网络,通过误差反向传播算法训练权重。它由输入层、隐藏层和输出层组成,每层包含多个神经元。

BP 神经网络算法流程图详解:从数学原理到 Python 实现

  • 神经元结构 :每个神经元接收前一层神经元的输出,经过加权求和后通过激活函数产生输出
  • 前向传播 :数据从输入层流向输出层
  • 反向传播 :误差从输出层反向传播到输入层,用于调整权重

2. BP 算法流程图解

2.1 前向传播阶段

 输入层 -> 隐藏层 -> 输出层
    |         |         |
    W_ih     W_ho     y_pred
  1. 输入数据通过输入层传递
  2. 计算隐藏层输入:$z_h = W_{ih}^T x + b_h$
  3. 应用激活函数:$a_h = \sigma(z_h)$
  4. 计算输出层输入:$z_o = W_{ho}^T a_h + b_o$
  5. 应用输出层激活函数:$y_{pred} = \sigma(z_o)$

2.2 损失计算

常用损失函数(以二分类为例):
$$ L = -\frac{1}{N}\sum_{i=1}^N [y_i\log(y_{pred}) + (1-y_i)\log(1-y_{pred})] $$

2.3 反向传播阶段

 输出层 <- 隐藏层 <- 输入层
    |         |         |
    δ_o      δ_h      W_update
  1. 计算输出层误差:$\delta_o = y_{pred} – y$
  2. 计算隐藏层误差:$\delta_h = (W_{ho} \delta_o) \odot \sigma'(z_h)$
  3. 更新权重:
    $$ W_{ho} = W_{ho} – \eta \delta_o a_h^T $$
    $$ W_{ih} = W_{ih} – \eta \delta_h x^T $$

3. Python 实现

import numpy as np
from typing import Tuple

class BPNeuralNetwork:
    def __init__(self, input_size: int, hidden_size: int, output_size: int):
        # 初始化权重
        self.W_ih = np.random.randn(input_size, hidden_size) * 0.01
        self.W_ho = np.random.randn(hidden_size, output_size) * 0.01
        self.b_h = np.zeros((1, hidden_size))
        self.b_o = np.zeros((1, output_size))

    def sigmoid(self, z: np.ndarray) -> np.ndarray:
        return 1 / (1 + np.exp(-z))

    def sigmoid_derivative(self, z: np.ndarray) -> np.ndarray:
        s = self.sigmoid(z)
        return s * (1 - s)

    def forward(self, x: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
        # 前向传播
        self.z_h = np.dot(x, self.W_ih) + self.b_h  # (batch, hidden)
        self.a_h = self.sigmoid(self.z_h)  # (batch, hidden)
        self.z_o = np.dot(self.a_h, self.W_ho) + self.b_o  # (batch, output)
        y_pred = self.sigmoid(self.z_o)  # (batch, output)
        return y_pred, self.z_o, self.a_h, self.z_h

    def backward(self, x: np.ndarray, y: np.ndarray, y_pred: np.ndarray, 
                 lr: float = 0.1) -> None:
        # 反向传播
        batch_size = x.shape[0]

        # 输出层误差
        delta_o = (y_pred - y) * self.sigmoid_derivative(self.z_o)  # (batch, output)

        # 隐藏层误差
        delta_h = np.dot(delta_o, self.W_ho.T) * self.sigmoid_derivative(self.z_h)  # (batch, hidden)

        # 更新权重和偏置
        self.W_ho -= lr * np.dot(self.a_h.T, delta_o) / batch_size  # (hidden, output)
        self.W_ih -= lr * np.dot(x.T, delta_h) / batch_size  # (input, hidden)
        self.b_o -= lr * np.mean(delta_o, axis=0, keepdims=True)
        self.b_h -= lr * np.mean(delta_h, axis=0, keepdims=True)

4. 实践建议

4.1 学习率设置

  • 初始学习率通常设置为 0.01 到 0.1
  • 使用学习率衰减策略:$\eta_t = \frac{\eta_0}{1 + decay\times t}$
  • 梯度裁剪防止梯度爆炸:
    max_grad_norm = 5.0
    total_norm = np.sqrt(sum(np.sum(np.square(grad)) for grad in grads))
    clip_coef = max_grad_norm / (total_norm + 1e-6)
    if clip_coef < 1:
        for grad in grads:
            grad *= clip_coef

4.2 隐藏层神经元数量

  • 经验公式:$N_h = \frac{N_i + N_o}{2} + \sqrt{N_{sample}}$
  • 过少会导致欠拟合,过多会导致过拟合
  • 可以通过交叉验证选择最优值

4.3 激活函数选择

任务类型 输出层激活函数 损失函数
二分类 Sigmoid 交叉熵
多分类 Softmax 交叉熵
回归 线性 MSE

5. 常见问题与解决方案

  1. 梯度消失问题 :
  2. 使用 ReLU 等非饱和激活函数
  3. 使用 Batch Normalization
  4. 残差连接

  5. 过拟合问题 :

  6. 增加 L2 正则化
  7. Dropout
  8. 早停法

  9. 训练集准确率高但验证集差 :

  10. 检查是否数据划分有问题
  11. 增加正则化强度
  12. 获取更多训练数据

6. 扩展思考

  • 自动微分 :尝试用 PyTorch 重构代码,利用其自动求导功能
  • 动量优化 :实现带动量的梯度下降
  • 不同架构 :尝试增加隐藏层数量,观察效果变化

7. 总结

BP 神经网络是深度学习的基础,理解其工作原理对后续学习更复杂模型至关重要。建议读者:
1. 手动实现一遍代码
2. 在不同数据集上测试
3. 尝试调整各种超参数观察效果
4. 进阶学习时可以研究更优化的算法如 Adam

通过这篇文章,你应该已经掌握了 BP 神经网络的核心原理和实现方法。接下来可以尝试在实际项目中应用这些知识,或者学习更高级的神经网络结构。

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