共计 1643 个字符,预计需要花费 5 分钟才能阅读完成。
神经网络前向传播与梯度下降的必要性
在神经网络中,前向传播是指输入数据通过网络的每一层,最终得到预测值的过程。以一个简单的两层全连接网络为例:

- 输入层到隐藏层的计算:
$$\mathbf{h} = \sigma(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1)$$ - 隐藏层到输出层的计算:
$$\mathbf{y} = \mathbf{W}_2 \mathbf{h} + \mathbf{b}_2$$
其中 $\sigma$ 是激活函数。网络的预测结果与实际标签之间的差异用损失函数 $E$ 来衡量。为了最小化这个损失,我们需要调整网络参数 $\mathbf{W}$ 和 $\mathbf{b}$,这就是梯度下降的基本思想。
反向传播的数学原理
反向传播的核心是链式法则。以计算 $\partial E / \partial w_{ij}$ 为例:
- 输出层参数的梯度:
$$\frac{\partial E}{\partial \mathbf{W}_2} = \frac{\partial E}{\partial \mathbf{y}} \cdot \frac{\partial \mathbf{y}}{\partial \mathbf{W}_2} = (\mathbf{y} – \mathbf{t}) \cdot \mathbf{h}^T$$ - 隐藏层参数的梯度:
$$\frac{\partial E}{\partial \mathbf{W}_1} = \frac{\partial E}{\partial \mathbf{h}} \cdot \frac{\partial \mathbf{h}}{\partial \mathbf{W}_1} = (\mathbf{W}_2^T (\mathbf{y} – \mathbf{t}) \odot \sigma'(\mathbf{z}_1)) \cdot \mathbf{x}^T$$
其中 $\mathbf{z}_1 = \mathbf{W}_1 \mathbf{x} + \mathbf{b}_1$,$\odot$ 表示逐元素乘法。
NumPy 实现完整反向传播
import numpy as np
class FullyConnectedLayer:
def __init__(self, input_size, output_size):
self.weights = np.random.randn(output_size, input_size) * 0.01
self.bias = np.zeros((output_size, 1))
def forward(self, x):
# x shape: (input_size, batch_size)
self.input = x
self.output = np.dot(self.weights, x) + self.bias
return self.output
def backward(self, dout):
# dout shape: (output_size, batch_size)
self.dweights = np.dot(dout, self.input.T)
self.dbias = np.sum(dout, axis=1, keepdims=True)
dx = np.dot(self.weights.T, dout)
return dx
# 梯度检查实现
def gradient_check(layer, x, epsilon=1e-7):
# 实现数值梯度计算并与解析梯度对比
...
常见问题与解决方案
- 梯度消失 / 爆炸识别 :
- 监控各层梯度范数
-
使用梯度裁剪技术
-
学习率设置 :
- 初始学习率通常设为 0.001-0.1
-
结合学习率衰减策略
-
ReLU 导数处理 :
def relu_backward(dout, cache): x = cache dx = dout * (x > 0) return dx
思考题
- 卷积层的反向传播需要考虑局部连接和权值共享的特性,如何修改全连接层的实现来适应这种结构?
- 批量归一化层在反向传播时会对梯度产生怎样的影响?这种影响对网络训练有什么帮助?
- 二阶优化算法如 L -BFGS 如何使用反向传播计算的海森矩阵信息来改进参数更新?
正文完
