多层神经网络传导与梯度下降:从数学原理到实现细节

1次阅读
没有评论

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

image.webp

数学基础:矩阵运算在神经网络中的作用

神经网络的核心计算依赖于矩阵运算。前向传播本质上是权重矩阵与输入数据的连续乘积与非线性变换的叠加。假设网络有 L 层,第 l 层的权重矩阵为 $W^l$,偏置向量为 $b^l$,则前向传播可表示为:

多层神经网络传导与梯度下降:从数学原理到实现细节

  1. 输入层:$a^0 = x$
  2. 隐藏层计算:$z^l = W^l a^{l-1} + b^l$
  3. 激活函数:$a^l = \sigma(z^l)$

反向传播则是通过链式法则计算梯度的过程。损失函数 $L$ 对第 l 层参数的梯度为:

  • 权重梯度:$\frac{\partial L}{\partial W^l} = \delta^l (a^{l-1})^T$
  • 偏置梯度:$\frac{\partial L}{\partial b^l} = \delta^l$
    其中 $\delta^l$ 表示误差项:

$\delta^l = (W^{l+1})^T \delta^{l+1} \odot \sigma'(z^l)$

Python 实现核心算法

import numpy as np

class NeuralNetwork:
    def __init__(self, layer_dims):
        """
        初始化网络参数
        layer_dims: 包含各层神经元数量的列表,如 [784, 30, 10]
        """
        self.params = {}
        for l in range(1, len(layer_dims)):
            # Xavier 初始化
            self.params[f'W{l}'] = np.random.randn(layer_dims[l], layer_dims[l-1]) / np.sqrt(layer_dims[l-1])
            self.params[f'b{l}'] = np.zeros((layer_dims[l], 1))

    def forward(self, X):
        """前向传播"""
        cache = {'A0': X}
        L = len(self.params) // 2

        for l in range(1, L+1):
            Z = np.dot(self.params[f'W{l}'], cache[f'A{l-1}']) + self.params[f'b{l}']
            cache[f'Z{l}'] = Z
            cache[f'A{l}'] = self.relu(Z) if l < L else self.softmax(Z)

        return cache

    def backward(self, cache, Y):
        """反向传播"""
        grads = {}
        L = len(self.params) // 2
        m = Y.shape[1]

        # 输出层梯度
        dZ = cache[f'A{L}'] - Y
        grads[f'dW{L}'] = np.dot(dZ, cache[f'A{L-1}'].T) / m
        grads[f'db{L}'] = np.sum(dZ, axis=1, keepdims=True) / m

        # 隐藏层梯度
        for l in reversed(range(1, L)):
            dA = np.dot(self.params[f'W{l+1}'].T, dZ)
            dZ = dA * self.relu_derivative(cache[f'Z{l}'])
            grads[f'dW{l}'] = np.dot(dZ, cache[f'A{l-1}'].T) / m
            grads[f'db{l}'] = np.sum(dZ, axis=1, keepdims=True) / m

        return grads

    def relu(self, x):
        return np.maximum(0, x)

    def relu_derivative(self, x):
        return (x > 0).astype(float)

    def softmax(self, x):
        exps = np.exp(x - np.max(x))
        return exps / np.sum(exps, axis=0)

性能优化策略

  1. 向量化计算 :使用 NumPy 的矩阵运算替代循环,充分利用 SIMD 指令
  2. 批量归一化 :对每层输入进行标准化处理,加速收敛
  3. 并行计算 :使用 GPU 加速矩阵运算(如 CuPy 库)
  4. 内存优化 :及时释放中间计算结果,避免内存泄漏

常见数值稳定性问题

  • 梯度消失 / 爆炸 :使用 ReLU 激活函数、权重初始化(Xavier/He)、梯度裁剪
  • 数值溢出 :softmax 计算时减去最大值
  • 学习率震荡 :采用学习率衰减策略

进阶思考

当网络深度增加到 50 层以上时,传统的反向传播会遇到哪些挑战?如何通过残差连接(ResNet)解决这些问题?请结合梯度流动的数学原理进行分析。

实践思考题

尝试在 MNIST 数据集上实现一个 5 层神经网络,观察以下情况:
1. 当学习率设为 0.1 时训练过程会出现什么现象?
2. 如果将所有权重初始化为 0,会对训练产生什么影响?
3. 比较 Sigmoid 和 ReLU 激活函数在深层网络中的表现差异。

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