BP神经网络入门指南:从数学原理到Python实战

1次阅读
没有评论

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

image.webp

为什么学习 BP 神经网络?

BP 神经网络(Backpropagation Neural Network)是深度学习的基础。比如:

BP 神经网络入门指南:从数学原理到 Python 实战

  • 手写数字识别 :银行支票自动识别系统通过 BP 网络学习数字特征,准确率可达 98%
  • 销量预测 :电商平台用历史销售数据训练网络,预测下周商品销量,误差小于传统统计方法

数学原理拆解

1. 前向传播的矩阵表示

假设网络有 3 层(输入层 L1、隐藏层 L2、输出层 L3),前向传播公式为:

Z2 = W1 · X + b1  # 隐藏层加权输入
A2 = σ(Z2)        # Sigmoid 激活函数
Z3 = W2 · A2 + b2
A3 = σ(Z3)        # 最终输出 

2. 损失函数选择

对于分类问题常用交叉熵损失(Cross-Entropy):

L = -Σ[y·log(a3) + (1-y)·log(1-a3)]

3. 反向传播推导(核心!)

通过链式法则计算梯度:

  1. 输出层误差:δ3 = (A3 – Y) * σ'(Z3)
  2. 隐藏层误差:δ2 = (W2.T · δ3) * σ'(Z2)
  3. 权重更新:
    W2 -= η · δ3 · A2.T
    b2 -= η · δ3
    W1 -= η · δ2 · X.T
    b1 -= η · δ2

    (η 为学习率)

Python 实现(NumPy 版)

import numpy as np

class NeuralNetwork:
    def __init__(self, input_size, hidden_size, output_size):
        self.W1 = np.random.randn(hidden_size, input_size) * 0.01
        self.b1 = np.zeros((hidden_size, 1))
        self.W2 = np.random.randn(output_size, hidden_size) * 0.01
        self.b2 = np.zeros((output_size, 1))

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

    def forward(self, X):
        self.Z2 = np.dot(self.W1, X) + self.b1
        self.A2 = self.sigmoid(self.Z2)
        self.Z3 = np.dot(self.W2, self.A2) + self.b2
        self.A3 = self.sigmoid(self.Z3)
        return self.A3

    def backward(self, X, Y, learning_rate):
        m = X.shape[1]  # 样本数量

        # 输出层误差
        dZ3 = self.A3 - Y
        dW2 = np.dot(dZ3, self.A2.T) / m
        db2 = np.sum(dZ3, axis=1, keepdims=True) / m

        # 隐藏层误差
        dZ2 = np.dot(self.W2.T, dZ3) * (self.A2 * (1 - self.A2))
        dW1 = np.dot(dZ2, X.T) / m
        db1 = np.sum(dZ2, axis=1, keepdims=True) / m

        # 更新参数
        self.W2 -= learning_rate * dW2
        self.b2 -= learning_rate * db2
        self.W1 -= learning_rate * dW1
        self.b1 -= learning_rate * db1

MNIST 实验测试

from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784', version=1)
X = mnist.data.T / 255.0  # 归一化
Y = np.eye(10)[mnist.target.astype(int)].T  # one-hot 编码

nn = NeuralNetwork(784, 128, 10)
for i in range(1000):
    nn.forward(X)
    nn.backward(X, Y, 0.1)
    if i % 100 == 0:
        print(f"Epoch {i}, Loss: {np.mean((nn.A3 - Y)**2)}")

常见问题解决方案

梯度消失问题

  • 现象 :隐藏层梯度接近 0,参数无法更新
  • 解决 :
  • 使用 ReLU 激活函数替代 Sigmoid
  • 采用 Batch Normalization

过拟合对策

  • Early Stopping:验证集准确率下降时停止训练
  • L2 正则化:在损失函数中加入权重平方项

进阶思考

  1. 与 CNN/RNN 对比 :
  2. CNN 擅长处理网格数据(如图像)
  3. RNN 适合序列数据(如文本)

  4. Mini-Batch 优化 :

    def train_batch(X, Y, batch_size=32):
        for i in range(0, X.shape[1], batch_size):
            X_batch = X[:, i:i+batch_size]
            Y_batch = Y[:, i:i+batch_size]
            nn.forward(X_batch)
            nn.backward(X_batch, Y_batch, 0.1)

通过这个完整案例,你应该已经掌握了 BP 网络的核心要义。建议尝试调整隐藏层节点数、更换激活函数,观察对模型性能的影响。

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