神经网络模型实战:从零实现前向传播、反向传播与训练过程

1次阅读
没有评论

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

image.webp

神经网络的核心训练流程就像教孩子认图的过程:前向传播是让孩子看图片说答案,反向传播是根据错误调整认知,参数更新则是不断优化判断标准。掌握这个闭环,就能让模型从数据中自动学习规律。

神经网络模型实战:从零实现前向传播、反向传播与训练过程

一、数学原理图解

1. 前向传播的矩阵运算

假设输入数据 $X\in\mathbb{R}^{n\times d}$(n 个样本,d 维特征),第一层权重 $W_1\in\mathbb{R}^{d\times h}$,则隐藏层输出为:
$$H = \text{ReLU}(XW_1 + b_1)$$
其中 ReLU 函数 $\text{ReLU}(z)=\max(0,z)$ 引入非线性。

2. 反向传播的链式法则

以交叉熵损失 $L$ 对 $W_1$ 的梯度为例:
$$\frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial H} \cdot \frac{\partial H}{\partial (XW_1+b_1)} \cdot \frac{\partial (XW_1+b_1)}{\partial W_1}$$
实际计算时从右向左逐层求导,就像沿着计算图的反方向传递误差。

3. 学习率与批量大小的关系

  • 大批量:梯度估计更稳定,但需要更大学习率
  • 小批量:每次更新方向波动大,需减小学习率
    经验公式:$\text{新学习率} = \text{原学习率} \times \sqrt{\frac{\text{ 原批量}}{\text{ 新批量}}}$

二、NumPy 代码实现

import numpy as np

class ThreeLayerMLP:
    def __init__(self, input_dim, hidden_dim, output_dim):
        # He 初始化适应 ReLU
        self.W1 = np.random.randn(input_dim, hidden_dim) * np.sqrt(2/input_dim)
        self.b1 = np.zeros(hidden_dim)
        self.W2 = np.random.randn(hidden_dim, output_dim) * np.sqrt(2/hidden_dim)
        self.b2 = np.zeros(output_dim)

    def forward(self, X):
        self.z1 = X @ self.W1 + self.b1
        self.h1 = np.maximum(0, self.z1)  # ReLU
        self.z2 = self.h1 @ self.W2 + self.b2
        self.probs = np.exp(self.z2) / np.sum(np.exp(self.z2), axis=1, keepdims=True)
        return self.probs

    def backward(self, X, y, lr=0.01):
        m = X.shape[0]  # 批量大小
        # 输出层梯度
        dz2 = self.probs
        dz2[range(m), y] -= 1
        dz2 /= m
        # 隐藏层梯度
        dh1 = dz2 @ self.W2.T
        dz1 = dh1 * (self.z1 > 0)  # ReLU 导数
        # 参数更新
        self.W2 -= lr * self.h1.T @ dz2
        self.b2 -= lr * np.sum(dz2, axis=0)
        self.W1 -= lr * X.T @ dz1
        self.b1 -= lr * np.sum(dz1, axis=0)

三、实战避坑指南

1. 梯度问题识别

  • 梯度爆炸 :参数突然变成 NaN 或极大值
  • 梯度消失 :深层网络参数几乎不更新
    解决方案:
  • 使用梯度裁剪(np.clip(grad, -5, 5)
  • 改用残差连接

2. 参数初始化

激活函数 推荐初始化方法
ReLU He 初始化
Tanh Xavier/Glorot
Sigmoid Xavier/Glorot

3. 学习率调整策略

  1. 阶梯下降 :每 N 轮学习率减半
  2. 余弦退火 :$\eta_t = \eta_{min} + \frac{1}{2}(\eta_{max}-\eta_{min})(1+\cos(\frac{t}{T}\pi))$
  3. 热重启 :周期性重置学习率

四、扩展思考

  1. Dropout 实现 :在前向传播时随机屏蔽部分神经元,注意测试阶段要缩放输出
  2. 批量归一化位置 :通常放在全连接层后、激活函数前
  3. 优化器内存 :Adam 需保存每个参数的动量变量,比 SGD 多 2 倍显存

通过这次手写实现,最让我惊讶的是反向传播中矩阵求导的优雅对称性——每一层的梯度计算都像是前向传播的镜像过程。建议读者用玩具数据(如螺旋数据集)可视化训练过程,能直观看到决策边界如何逐步优化。

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