神经网络构建原理(以MINIST为例)
神经网络构建原理(以MINIST为例)
在 MNIST 手写数字识别任务中,构建神经网络并训练模型来进行分类是经典的深度学习应用。MNIST 数据集包含 28x28 像素的手写数字图像(0-9),任务是构建一个神经网络,能够根据输入的图像预测对应的数字。本文将通过该案例详细介绍神经网络的逻辑框架和具体的计算流程。
神经网络构建框架
1.数据预处理
- 将输入数据进行标准化处理(归一化),并将标签转换为适合模型的格式( one-hot 编码)。
2.模型构建
- a.输入层:定义输入的大小(将 28x28 的图像展平为 784 维向量)。
- b.隐藏层:添加一个或多个隐藏层,每层包含一定数量的神经元,并应用激活函数(如 ReLU)[实际上神经元相当于维数,该过程即是对原特征维数进行扩维或降维]。
- c.输出层:定义输出层的神经元数量(与分类类别一致),通常使用 Softmax 函数将输出转换为概率。
3.前向传播
- 执行输入层到隐藏层、再到输出层的矩阵乘法和激活函数,计算输出值。
4.损失函数计算
- 使用交叉熵等损失函数,计算预测输出与真实标签之间的误差。
5.反向传播
- 通过链式法则,计算损失函数对每个参数的偏导数,并更新权重和偏置项。
6.优化器更新
- 使用优化器(如 SGD、Adam)基于计算的梯度更新模型参数,降低损失值。
7.迭代训练
- 不断重复前向传播、损失计算和反向传播,直到损失收敛或达到设定的训练轮次。
8.模型评估与预测
- 训练完成后,用测试数据评估模型性能,并进行新数据的预测。
神经网络的具体计算流程
接下来以MINIST手写数字识别为例,模拟神经网络构建的具体计算过程。
假设该网络包含 两个隐藏层,每个隐藏层有 25 个神经元,最后的输出层为 10 个神经元。
1. 前向传播(Forward Propagation)
1.1输入层到第一个隐藏层:
-
输入大小:假设输入图像是 28x28 的像素矩阵,展平成 784 维的向量。 x ∈ R 784 × 1 x \in \mathbb{R}^{784 \times 1} x∈R784×1
-
权重矩阵:连接输入层到第一个隐藏层的权重矩阵,大小为 25x784,[因为特征向量是列向量,所以需要转置]。 W 1 ∈ R 25 × 784 W_1 \in \mathbb{R}^{25 \times 784} W1∈R25×784
-
偏置项:第一个隐藏层的偏置项,大小为 25x1。 b 1 ∈ R 25 × 1 b_1 \in \mathbb{R}^{25 \times 1} b1∈R25×1
-
激活函数:使用 ReLU 激活函数。
计算步骤:
- 执行矩阵乘法 z 1 = W 1 ⋅ x + b 1 z_1 = W_1 \cdot x + b_1 z1=W1⋅x+b1
z 1 z_1 z1 的维度是 25x1。
- 应用 ReLU 激活函数: h 1 = ReLU ( z 1 ) h_1 = \text{ReLU}(z_1) h1=ReLU(z1)
其中: ReLU ( z 1 ) = max ( 0 , z 1 ) \text{ReLU}(z_1) = \max(0, z_1) ReLU(z1)=max(0,z1)
- 结果:第一个隐藏层的输出
h
1
h_1
h1 是 25 维的向量。
1.2第一个隐藏层到第二个隐藏层:
-
权重矩阵:连接第一个隐藏层到第二个隐藏层的权重矩阵,大小为 25x25。 W 2 ∈ R 25 × 25 W_2 \in \mathbb{R}^{25 \times 25} W2∈R25×25
-
偏置项:第二个隐藏层的偏置项,大小为 25x1。 b 2 ∈ R 25 × 1 b_2 \in \mathbb{R}^{25 \times 1} b2∈R25×1
计算步骤:
- 执行矩阵乘法 z 2 = W 2 ⋅ h 1 + b 2 z_2 = W_2 \cdot h_1 + b_2 z2=W2⋅h1+b2
z 2 z_2 z2的维度是 25x1。
-
应用 ReLU 激活函数: h 2 = ReLU ( z 2 ) h_2 = \text{ReLU}(z_2) h2=ReLU(z2)
-
结果:第二个隐藏层的输出 h 2 h_2 h2 仍然是 25 维的向量。
1.3第二个隐藏层到输出层:
-
权重矩阵:连接第二个隐藏层到输出层的权重矩阵,大小为 10x25。 W 3 ∈ R 10 × 25 W_3 \in \mathbb{R}^{10 \times 25} W3∈R10×25
-
偏置项:输出层的偏置项,大小为 10x1。 b 3 ∈ R 10 × 1 b_3 \in \mathbb{R}^{10 \times 1} b3∈R10×1
计算步骤:
- 执行矩阵乘法 z 3 = W 3 ⋅ h 2 + b 3 z_3 = W_3 \cdot h_2 + b_3 z3=W3⋅h2+b3
z 3 z_3 z3的维度是 10x1。
- 应用 Softmax 函数将输出转换为概率: Softmax ( z 3 ) i = e z 3 i ∑ j = 1 10 e z 3 j \text{Softmax}(z_3)_i = \frac{e^{z_{3i}}}{\sum_{j=1}^{10} e^{z_{3j}}} Softmax(z3)i=∑j=110ez3jez3i
Softmax 输出是 10 维的概率向量,表示输入属于 0-9 的概率。
2. 损失计算
使用交叉熵损失函数来计算预测输出与真实标签之间的误差,假设真实标签是 one-hot 编码的向量
y
∈
R
10
y \in \mathbb{R}^{10}
y∈R10,其中,
y
i
=
1
y_i = 1
yi=1 表示真实类别,
p
i
=
Softmax
(
z
3
)
i
p_i = \text{Softmax}(z_3)_i
pi=Softmax(z3)i 表示模型对类别
i
i
i 的预测概率。
交叉熵损失公式: L = − ∑ i = 1 10 y i log ( p i ) L = -\sum_{i=1}^{10} y_i \log(p_i) L=−i=1∑10yilog(pi)
损失计算步骤:
- 对于每一个样本,计算预测类别对应的概率 p i p_i pi 的对数,然后计算损失 L L L。
3. 反向传播(Backward Propagation)
反向传播的目标是通过链式法则计算损失函数对每层权重的偏导数,并更新权重矩阵。
3.1输出层到第二个隐藏层:
-
计算损失对输出层的导数: ∂ L ∂ z 3 = Softmax ( z 3 ) − y \frac{\partial L}{\partial z_3} = \text{Softmax}(z_3) - y ∂z3∂L=Softmax(z3)−y
-
计算损失对 W 3 W_3 W3的导数: ∂ L ∂ W 3 = ∂ L ∂ z 3 ⋅ h 2 T \frac{\partial L}{\partial W_3} = \frac{\partial L}{\partial z_3} \cdot h_2^T ∂W3∂L=∂z3∂L⋅h2T
-
计算损失对 b 3 b_3 b3的导数: ∂ L ∂ b 3 = ∂ L ∂ z 3 \frac{\partial L}{\partial b_3} = \frac{\partial L}{\partial z_3} ∂b3∂L=∂z3∂L
3.2第二个隐藏层到第一个隐藏层:
-
损失传播到第二层的输出 h 2 h_2 h2: ∂ L ∂ h 2 = W 3 T ⋅ ∂ L ∂ z 3 \frac{\partial L}{\partial h_2} = W_3^T \cdot \frac{\partial L}{\partial z_3} ∂h2∂L=W3T⋅∂z3∂L
-
计算 ReLU 激活函数的导数: ∂ L ∂ z 2 = ∂ L ∂ h 2 ⋅ ReLU ′ ( z 2 ) \frac{\partial L}{\partial z_2} = \frac{\partial L}{\partial h_2} \cdot \text{ReLU}'(z_2) ∂z2∂L=∂h2∂L⋅ReLU′(z2)
其中: ReLU ′ ( z 2 ) = { 1 if z 2 > 0 0 if z 2 ≤ 0 \text{ReLU}'(z_2) = \begin{cases} 1 & \text{if } z_2 > 0 \\ 0 & \text{if } z_2 \leq 0 \end{cases} ReLU′(z2)={10if z2>0if z2≤0
-
计算损失对 W 2 W_2 W2的导数: ∂ L ∂ W 2 = ∂ L ∂ z 2 ⋅ h 1 T \frac{\partial L}{\partial W_2} = \frac{\partial L}{\partial z_2} \cdot h_1^T ∂W2∂L=∂z2∂L⋅h1T
-
计算损失对 b 2 b_2 b2的导数: ∂ L ∂ b 2 = ∂ L ∂ z 2 \frac{\partial L}{\partial b_2} = \frac{\partial L}{\partial z_2} ∂b2∂L=∂z2∂L
3.3第一个隐藏层到输入层:
-
损失传播到第一层的输出 h 1 h_1 h1: ∂ L ∂ h 1 = W 2 T ⋅ ∂ L ∂ z 2 \frac{\partial L}{\partial h_1} = W_2^T \cdot \frac{\partial L}{\partial z_2} ∂h1∂L=W2T⋅∂z2∂L
-
计算 ReLU 激活函数的导数: ∂ L ∂ z 1 = ∂ L ∂ h 1 ⋅ ReLU ′ ( z 1 ) \frac{\partial L}{\partial z_1} = \frac{\partial L}{\partial h_1} \cdot \text{ReLU}'(z_1) ∂z1∂L=∂h1∂L⋅ReLU′(z1)
-
计算损失对 h 1 h_1 h1的导数: ∂ L ∂ W 1 = ∂ L ∂ z 1 ⋅ x T \frac{\partial L}{\partial W_1} = \frac{\partial L}{\partial z_1} \cdot x^T ∂W1∂L=∂z1∂L⋅xT
-
计算损失对 b 1 b_1 b1的导数: ∂ L ∂ b 1 = ∂ L ∂ z 1 \frac{\partial L}{\partial b_1} = \frac{\partial L}{\partial z_1} ∂b1∂L=∂z1∂L
4. 权重更新
使用梯度下降算法或 Adam 优化器来更新权重。
更新公式: W = W − η ⋅ ∂ L ∂ W W = W - \eta \cdot \frac{\partial L}{\partial W} W=W−η⋅∂W∂L
- W W W是权重矩阵, η η η是学习率, ∂ L ∂ W \frac{\partial L}{\partial W} ∂W∂L 是损失函数关于权重的梯度。
权重更新步骤在每一层执行:
- 更新 W 1 W_1 W1, W 2 W_2 W2, W 3 W_3 W3和对应的偏置项 b 1 b_1 b1, b 2 b_2 b2, b 3 b_3 b3。
5. 优化器(Adam)介绍
Adam 优化器通过结合动量和自适应学习率进行参数更新。详细的更新公式在上面的回答中已经给出。
1.一阶动量估计:
计算当前梯度
∇
θ
L
\nabla_{\theta}L
∇θL的加权平均,用来估计梯度的期望。这个一阶动量主要是累积之前的梯度,使得更新方向更加平滑。
m
t
=
β
1
m
t
−
1
+
(
1
−
β
1
)
∇
θ
L
m_t = \beta_1 m_{t-1} + (1 - \beta_1) \nabla_{\theta}L
mt=β1mt−1+(1−β1)∇θL
β
1
\beta_1
β1是一阶动量的衰减率,通常取值为 0.9。
m
t
m_t
mt是当前的动量(梯度的指数加权平均)。
2.二阶矩估计:
计算当前梯度平方的加权平均,估计梯度的方差,用来调节学习率,避免更新步长过大。
v
t
=
β
2
v
t
−
1
+
(
1
−
β
2
)
(
∇
θ
L
)
2
v_t = \beta_2 v_{t-1} + (1 - \beta_2) (\nabla_{\theta}L)^2
vt=β2vt−1+(1−β2)(∇θL)2
β
2
\beta_2
β2是二阶动量的衰减率,通常取值为 0.999。
v
t
v_t
vt是梯度平方的指数加权平均。
3.偏差修正:
由于
m
^
t
\hat{m}_t
m^t和
v
^
t
\hat{v}_t
v^t在前几步可能会有较大的偏差,Adam 引入了偏差修正,减少估计的偏差。
m
^
t
=
m
t
1
−
β
1
t
,
v
^
t
=
v
t
1
−
β
2
t
\hat{m}_t = \frac{m_t}{1 - \beta_1^t}, \quad \hat{v}_t = \frac{v_t}{1 - \beta_2^t}
m^t=1−β1tmt,v^t=1−β2tvt
m
^
t
\hat{m}_t
m^t和
v
^
t
\hat{v}_t
v^t是偏差修正后的动量和二阶矩估计.
4.参数更新:
使用修正后的动量和方差来更新参数。Adam 的更新方式是自适应的,能根据梯度的历史动态调整学习率。
W
t
+
1
=
W
t
−
η
m
^
t
v
^
t
+
ϵ
W_{t+1} = W_t - \eta \frac{\hat{m}_t}{\sqrt{\hat{v}_t} + \epsilon}
Wt+1=Wt−ηv^t+ϵm^t
η
η
η是学习率,通常取值在 0.001 左右。
$ \epsilon$是一个小的平滑项,避免除以零,通常为
1
0
−
8
10^{-8}
10−8 。
Reference:
- TensorFlow Documentation
- CS231n Convolutional Neural Networks for Visual Recognition
- Adam Optimizer Paper
- Gradient Descent and Backpropagation Overview
- https://www.deeplearningbook.org/
- http://cs231n.github.io/optimization-2/