BP神经网络入门指南:正向传播与反向传播的数学原理与代码实现

1次阅读
没有评论

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

image.webp

神经网络基础概念

BP 神经网络(Back Propagation Neural Network)是一种典型的前馈神经网络,由输入层、隐藏层(可以有多层)和输出层组成。每一层由若干个神经元(节点)构成,层与层之间通过权重连接。它的学习过程分为正向传播和反向传播两个阶段。

BP 神经网络入门指南:正向传播与反向传播的数学原理与代码实现

  • 输入层:接收外部输入数据
  • 隐藏层:对输入数据进行非线性变换
  • 输出层:输出最终预测结果

正向传播的数学原理

正向传播是指数据从输入层经过隐藏层最终到达输出层的过程。在这个过程中,每个神经元都会对输入进行加权求和,然后通过激活函数进行非线性转换。

  1. 加权求和:
    $$z_j = \sum_{i=1}^n w_{ji}x_i + b_j$$
    其中,$w_{ji}$ 是连接输入 $x_i$ 和神经元 $j$ 的权重,$b_j$ 是偏置项。

  2. 激活函数计算:
    $$a_j = \sigma(z_j)$$
    常用的激活函数包括 Sigmoid、ReLU 和 tanh 等。

  3. 逐层计算直到输出层,得到预测值 $\hat{y}$

反向传播算法详解

反向传播是通过计算损失函数对权重的梯度,然后使用梯度下降法更新权重参数的过程。

  1. 计算损失函数(以均方误差为例):
    $$L = \frac{1}{2}(y – \hat{y})^2$$

  2. 输出层误差计算:
    $$\delta_j = (\hat{y}_j – y_j)\sigma'(z_j)$$

  3. 隐藏层误差反向传播(链式法则):
    $$\delta_j = \sigma'(z_j)\sum_k w_{kj}\delta_k$$

  4. 权重更新(梯度下降):
    $$\Delta w_{ji} = -\eta \delta_j a_i$$
    $$w_{ji} = w_{ji} + \Delta w_{ji}$$
    其中,$\eta$ 是学习率。

Python 代码实现

import numpy as np

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

def sigmoid_derivative(x):
    return x * (1 - x)

# 神经网络类
class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        # 初始化权重
        self.weights1 = np.random.randn(input_size, hidden_size)
        self.weights2 = np.random.randn(hidden_size, output_size)

    def forward(self, X):
        # 正向传播
        self.hidden = sigmoid(np.dot(X, self.weights1))
        self.output = sigmoid(np.dot(self.hidden, self.weights2))
        return self.output

    def backward(self, X, y, output, learning_rate):
        # 反向传播
        output_error = y - output
        output_delta = output_error * sigmoid_derivative(output)

        hidden_error = np.dot(output_delta, self.weights2.T)
        hidden_delta = hidden_error * sigmoid_derivative(self.hidden)

        # 更新权重
        self.weights2 += learning_rate * np.dot(self.hidden.T, output_delta)
        self.weights1 += learning_rate * np.dot(X.T, hidden_delta)

# 示例:XOR 问题
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([[0], [1], [1], [0]])

# 创建神经网络
nn = NeuralNetwork(2, 4, 1)

# 训练
for i in range(10000):
    output = nn.forward(X)
    nn.backward(X, y, output, 0.1)

    if i % 1000 == 0:
        print(f"Epoch {i}, Loss: {np.mean(np.square(y - output))}")

# 测试
print("Final predictions:")
print(nn.forward(X))

避坑指南

  • 梯度消失 / 爆炸问题
  • 使用 ReLU 等激活函数替代 Sigmoid
  • 采用权重初始化方法(如 Xavier 初始化)
  • 使用 Batch Normalization

  • 学习率选择

  • 初始学习率通常设置在 0.01-0.1 之间
  • 可以使用学习率衰减策略

  • 激活函数选择

  • Sigmoid:输出范围(0,1),适合二分类
  • tanh:输出范围(-1,1),中心对称
  • ReLU:计算简单,缓解梯度消失

思考题

  1. 如何改进基础 BP 算法提高收敛速度?可以考虑动量法、自适应学习率等方法。
  2. 批量训练与在线训练各有何优劣?批量训练更稳定但需要更多内存,在线训练更灵活但可能不稳定。
  3. 不同优化器 (如 Adam) 的实现原理是什么?Adam 结合了动量法和 RMSProp 的优点。

通过本文的学习,你应该对 BP 神经网络的正向传播和反向传播有了基本的理解。建议读者尝试修改代码中的网络结构和参数,观察不同设置对模型性能的影响,这是掌握神经网络的最好方法。

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