面向机器学习入门:从网络结构、前向传播、交叉熵损失,到矩阵求导、链式法则、完整反向传播手推。 不依赖框架黑盒,一步步拆解单层/多层神经网络数学原理,附维度校验 + Python 可运行伪代码。
🚀 想要直接运行代码? 本文对应的纯 NumPy 完整实现(包含单样本基础版与 Batch 批量实战版)已在 ../code 目录下就绪。请前往查看 mnist_numpy.py 等可执行文件!
适用人群:
- 后端/全栈开发者,想补神经网络底层数学
- 正在学习算法、深度学习、凸优化入门的同学
- 面试准备神经网络推导、梯度相关算法题
如果您是初学者,建议先看“前置基础”确认基础,然后对照“符号速查表”理解每一个公式的维度。推导部分重点掌握“通用法则”,再逐层代入。代码实现可以参考最后的伪代码。
- 简单的神经网络构造
- 矩阵乘法运算
- 微积分的(偏)导数
- 多元微积分链式法则(向量对向量)
- 梯度下降算法
在深入矩阵求导之前,请将此表作为“导航图”。推导中随时回来查阅维度。
| 符号 | 含义 | 维度示例 |
|---|---|---|
| 输入图像展平列向量 | ||
| 第 |
取决于层 | |
| 第 |
同上 | |
| 第 |
例如 |
|
| 第 |
||
| 第 |
视当前层变换而定 | |
|
|
|
与对应节点相同 |
|
|
与对应变量相同 | |
| Softmax 输出的概率向量 | ||
| One-Hot 真实标签 | ||
| 交叉熵损失 | 标量 | |
| 学习率 | 标量 | |
| 逐元素相乘(哈达玛积 Hadamard Product) | 同维度向量 / 矩阵 |
假设输入图像展平后为列向量
-
输入层 (Input Layer)
- 输入变量:
$x$ - 向量维度:
$(784 \times 1)$
- 输入变量:
-
隐藏层 1 (Hidden Layer 1)
- 线性计算:
$h_1 = W_0 x + b_0$ - 激活函数:
$a_1 = \text{ReLU}(h_1)$ - 参数维度:
$W_0$ 为$(16 \times 784)$ ,$b_0$ 为$(16 \times 1)$ ,$a_1$ 为$(16 \times 1)$
- 线性计算:
-
隐藏层 2 (Hidden Layer 2)
- 线性计算:
$h_2 = W_1 a_1 + b_1$ - 激活函数:
$a_2 = \text{ReLU}(h_2)$ - 参数维度:
$W_1$ 为$(15 \times 16)$ ,$b_1$ 为$(15 \times 1)$ ,$a_2$ 为$(15 \times 1)$
- 线性计算:
-
输出层 (Output Layer)
- 线性计算:
$h_3 = W_2 a_2 + b_2$ - 激活函数:
$p = \text{Softmax}(h_3)$ - 概率公式:
$p_i = \frac{e^{h_{3,i}}}{\sum_{k=1}^{10} e^{h_{3,k}}}$ - 参数维度:
$W_2$ 为$(10 \times 15)$ ,$b_2$ 为$(10 \times 1)$ ,$p$ 为$(10 \times 1)$
- 线性计算:
注:隐藏层使用的 ReLU 激活函数数学定义为
为了简化推导,隐藏层使用了较小的神经元数量(16和15),实际应用中可放大到 128 或 256。
处理多分类问题,采用交叉熵损失函数(Cross-Entropy Loss)。
注:
在神经网络中,相邻层之间最核心的计算交替进行:线性变换 与 激活函数。我们可以将这两种操作的公式提炼成极其对称的正反向对照格式。(定义
多元链式法则核心公式:
其中
假设从输入节点
变量与典型维度说明:
-
$W$ :当前层的权重矩阵,假设维度为$(15 \times 16)$ 。 -
$X$ :代表当前层的输入(上一层的激活输出,列向量),假设维度为$(16 \times 1)$ 。 -
$b$ :当前层的偏置项(列向量),假设维度与$h$ 相同,为$(15 \times 1)$ 。 -
$h$ :当前层的线性输出节点(列向量),其维度为$(15 \times 1)$ 。 -
$g_h$ :已知下一层传回来的、损失$L$ 对输出$h$ 的梯度$\left(\frac{\partial L}{\partial h}\right)$ ,维度与$h$ 相同,为$(15 \times 1)$ 。
根据多元链式法则核心公式,我们可以直接得出针对
当对输入节点
- 维度验算:
$(16 \times 15) \times (15 \times 1) = (16 \times 1)$ ,完美匹配$X$ 的原有维度。
当对权重
- 维度验算:
$(15 \times 1) \times (1 \times 16) = (15 \times 16)$ ,完美匹配$W$ 的原有维度。
当对偏置
- 维度验算:
$g_b$ 直接继承$g_h$ 的维度,为$(15 \times 1)$ ,完美匹配$b$ 的原有维度。
假设预激活输入节点为
根据多元链式法则,误差穿透激活函数时的求导公式为:
-
符号说明:激活函数
$\Phi(\cdot)$ 及其导数$\Phi'(\cdot)$ 均是独立作用于向量的每个元素上。符号$\odot$ 表示逐元素相乘 (Element-wise Multiplication)。
掌握了这两个通用法则,后续隐藏层的复杂推导,就是这两个公式的交替套用组合!-- 详细推导待更新。
反向传播的核心逻辑分为两步:首先计算误差在节点间的传递(节点梯度
计算损失
- 维度验算:
$g_3$ 为$(10 \times 1)$ 的列向量。
该结果是交叉熵损失 + Softmax 激活的著名简化形式,详细推导待更新。
计算第 3 层权重和偏置的梯度:
- 维度验算:
$\frac{\partial L}{\partial W_2} = (10 \times 1) \times (1 \times 15) = (10 \times 15)$ ,完美匹配$W_2$ 原有维度。
4.2 隐藏层 2 梯度 (Hidden Layer 2)
误差从
- 注:
$\text{ReLU}'(h_2)$ 为导数向量,当$h_2 > 0$ 时元素为$1$ ,否则为$0$ 。 - 维度验算:
$W_2^T$ 为$(15 \times 10)$ ,$g_3$ 为$(10 \times 1)$ 。两者矩阵乘法结果为$(15 \times 1)$ 。与 ReLU 导数逐元素相乘后,$g_2$ 为$(15 \times 1)$ 列向量。
计算第 2 层权重和偏置的梯度:
- 维度验算:
$\frac{\partial L}{\partial W_1} = (15 \times 1) \times (1 \times 16) = (15 \times 16)$ ,完美匹配$W_1$ 原有维度。
4.3 隐藏层 1 梯度 (Hidden Layer 1)
同理,误差从
- 维度验算:
$W_1^T$ 为$(16 \times 15)$ ,$g_2$ 为$(15 \times 1)$ ,矩阵乘法后$g_1$ 为$(16 \times 1)$ 列向量。
计算第 1 层权重和偏置的梯度:
- 维度验算:
$\frac{\partial L}{\partial W_0} = (16 \times 1) \times (1 \times 784) = (16 \times 784)$ ,完美匹配$W_0$ 原有维度。
利用收集到的梯度,使用学习率
注意:所有梯度计算完成后,再统一进行参数更新(同步更新),否则会使用已更新的权重影响后续梯度的正确性。
# 说明使用 numpy 矩阵运算习惯(@ 矩阵乘、* 逐元素乘)
# 前向传播
h1 = W0 @ x + b0
a1 = relu(h1)
h2 = W1 @ a1 + b1
a2 = relu(h2)
h3 = W2 @ a2 + b2
p = softmax(h3)
L = cross_entropy(y, p)
# 反向传播
g3 = p - y
dW2 = g3 @ a2.T
db2 = g3
g2 = (W2.T @ g3) * relu_deriv(h2)
dW1 = g2 @ a1.T
db1 = g2
g1 = (W1.T @ g2) * relu_deriv(h1)
dW0 = g1 @ x.T
db0 = g1
# 参数更新
W2 -= alpha * dW2; b2 -= alpha * db2
W1 -= alpha * dW1; b1 -= alpha * db1
W0 -= alpha * dW0; b0 -= alpha * db0实际运行代码,见 code/mnist_numpy.py。
证明:
当前文档为 单样本 推导;实际训练中使用批量数据,会引入均值、维度广播,后续补充 Batch 版本公式。
结合本推导,延伸学习方向:
- 凸优化基础(梯度下降进阶、约束优化)
- 各类激活函数(Sigmoid/Tanh)反向传播
- 正则化(L1/L2)、Dropout 数学推导
- 优化器:SGD、Adam 原理与公式
