BP神经网络计算:从数学原理到Python实现

1次阅读
没有评论

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

image.webp

BP 神经网络的基础地位

BP 神经网络(Backpropagation Neural Network)是深度学习的基础算法之一,它通过不断调整网络中的权重和偏置,使网络能够学习输入和输出之间的复杂关系。BP 算法的核心是反向传播误差,通过梯度下降优化网络参数。这种算法在图像识别、语音处理、自然语言处理等领域都有广泛应用。

BP 神经网络计算:从数学原理到 Python 实现

数学推导

前向传播的矩阵表示

前向传播的过程可以用矩阵乘法简洁表示。对于一个三层的神经网络,输入层到隐藏层的计算可以表示为:

$$ h = \sigma(W_1 x + b_1) $$

其中,$W_1$ 是权重矩阵,$x$ 是输入向量,$b_1$ 是偏置向量,$\sigma$ 是激活函数(如 Sigmoid 或 ReLU)。

隐藏层到输出层的计算类似:

$$ y = \sigma(W_2 h + b_2) $$

损失函数对权重的偏导

反向传播的关键是计算损失函数对权重的偏导数。以均方误差(MSE)为例,损失函数为:

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

通过链式法则,可以分解为:

$$ \frac{\partial L}{\partial W_2} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial W_2} $$

$$ \frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial h} \cdot \frac{\partial h}{\partial W_1} $$

学习率与梯度下降

梯度下降的更新规则为:

$$ W = W – \eta \cdot \frac{\partial L}{\partial W} $$

其中,$\eta$ 是学习率,控制每次更新的步长。学习率过大可能导致震荡,过小则收敛缓慢。

Python 实现

纯 Python + NumPy 实现

import numpy as np

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

    def forward(self, x):
        self.h = np.dot(x, self.W1) + self.b1
        self.h_activated = 1 / (1 + np.exp(-self.h))  # Sigmoid
        self.y = np.dot(self.h_activated, self.W2) + self.b2
        return self.y

    def backward(self, x, y_true, learning_rate):
        m = x.shape[0]
        dy = self.y - y_true
        dW2 = np.dot(self.h_activated.T, dy) / m
        db2 = np.sum(dy, axis=0, keepdims=True) / m

        dh_activated = np.dot(dy, self.W2.T)
        dh = dh_activated * self.h_activated * (1 - self.h_activated)
        dW1 = np.dot(x.T, dh) / m
        db1 = np.sum(dh, axis=0, keepdims=True) / m

        self.W2 -= learning_rate * dW2
        self.b2 -= learning_rate * db2
        self.W1 -= learning_rate * dW1
        self.b1 -= learning_rate * db1

标准化输入处理

def normalize(x):
    return (x - np.mean(x, axis=0)) / np.std(x, axis=0)

梯度检查

梯度检查用于验证反向传播的实现是否正确。通过数值方法近似计算梯度,与反向传播的结果对比:

def gradient_check(x, y_true, network, epsilon=1e-7):
    params = network.W1.flatten()
    grad = np.zeros_like(params)

    for i in range(len(params)):
        params_plus = params.copy()
        params_plus[i] += epsilon
        network.W1 = params_plus.reshape(network.W1.shape)
        loss_plus = np.mean((network.forward(x) - y_true) ** 2)

        params_minus = params.copy()
        params_minus[i] -= epsilon
        network.W1 = params_minus.reshape(network.W1.shape)
        loss_minus = np.mean((network.forward(x) - y_true) ** 2)

        grad[i] = (loss_plus - loss_minus) / (2 * epsilon)

    return grad

工程实践

权重初始化

  • Xavier 初始化 :适用于 Sigmoid 和 Tanh 激活函数,权重初始化为 $W \sim U(-\sqrt{6/n_{in} + n_{out}}, \sqrt{6/n_{in} + n_{out}})$
  • He 初始化 :适用于 ReLU 激活函数,权重初始化为 $W \sim N(0, \sqrt{2/n_{in}})$

学习率衰减

常见的学习率衰减策略包括:

  1. 固定步长衰减:每隔一定 epoch,学习率乘以一个衰减系数
  2. 指数衰减:学习率按指数函数衰减
  3. 余弦退火:学习率按余弦函数周期变化

批量归一化

批量归一化(Batch Normalization)通常在全连接层或卷积层之后、激活函数之前应用:

def batch_norm(x, gamma, beta, eps=1e-5):
    mu = np.mean(x, axis=0)
    var = np.var(x, axis=0)
    x_norm = (x - mu) / np.sqrt(var + eps)
    return gamma * x_norm + beta

思考题

  1. 计算图优化 :如何利用计算图(如 TensorFlow 或 PyTorch 的自动微分)优化反向传播的效率?
  2. 自动微分与手动实现 :对比自动微分框架(如 Autograd)与手动实现反向传播的优缺点,哪种更适合大规模网络?

总结

BP 神经网络是深度学习的基础,理解其数学原理和实现细节对后续学习更复杂的模型至关重要。通过手动实现 BP 算法,可以深入理解梯度下降和反向传播的工作机制。在实际工程中,合理的权重初始化、学习率策略和批量归一化能显著提升训练效果。

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