共计 1495 个字符,预计需要花费 4 分钟才能阅读完成。
为什么需要 BP 神经网络?
在图像识别、语音处理等领域,传统算法(如 SVM)难以自动提取特征。BP 神经网络通过多层非线性变换,能学习数据中的复杂模式。但新手常误以为:
- 层数越多效果越好(实际可能引发梯度消失)
- 所有场景都用 ReLU 就万事大吉(分类任务最后一层仍需 Sigmoid/Softmax)
- 参数初始化可以随便设置(导致训练初期梯度爆炸)
数学原理图解
前向传播
输入数据 $X$ 经过第 $l$ 层时:
$$Z^{[l]} = W^{[l]}A^{[l-1]} + b^{[l]}$$
$$A^{[l]} = g^{[l]}(Z^{[l]})$$
其中 $g^{[l]}$ 是激活函数,$A^{[0]}=X$
反向传播关键步骤
通过链式法则计算损失 $L$ 对参数的梯度:
1. 输出层误差:
$$dZ^{[L]} = A^{[L]} – Y$$
2. 隐藏层误差(以 Sigmoid 为例):
$$dZ^{[l]} = W^{[l+1]T}dZ^{[l+1]} \odot g’^{[l]}(Z^{[l]})$$
3. 参数梯度:
$$dW^{[l]} = \frac{1}{m}dZ^{[l]}A^{[l-1]T}$$
$$db^{[l]} = \frac{1}{m}\sum dZ^{[l]}$$
Python 实现核心模块
网络初始化(Xavier 方法)
def initialize_parameters(layer_dims):
params = {}
for l in range(1, len(layer_dims)):
params['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l-1]) * np.sqrt(2/layer_dims[l-1])
params['b' + str(l)] = np.zeros((layer_dims[l], 1))
return params
ReLU 与 Sigmoid 实现
def relu(Z):
return np.maximum(0, Z)
def sigmoid(Z):
return 1/(1+np.exp(-Z))
交叉熵损失计算
def compute_cost(A_L, Y):
m = Y.shape[1]
cost = -1/m * np.sum(Y*np.log(A_L) + (1-Y)*np.log(1-A_L))
return np.squeeze(cost)
训练过程可视化
损失曲线绘制
plt.plot(costs)
plt.ylabel('Cost')
plt.xlabel('Iterations')
plt.title("Learning rate =" + str(learning_rate))
plt.show()

工业级优化方案
学习率衰减策略对比
- 指数衰减:
learning_rate = initial_lr * (0.95 ** epoch) - 余弦退火:
learning_rate = 0.5 * lr_max * (1 + np.cos(epoch * np.pi / total_epochs))
梯度裁剪示例
def clip_grads(grads, max_norm):
total_norm = np.sum([np.sum(np.square(g)) for g in grads.values()])
scale = max_norm / (np.sqrt(total_norm) + 1e-6)
if scale < 1:
for key in grads:
grads[key] *= scale
return grads
下一步探索建议
- 用 PyTorch 的
autograd重构反向传播代码,对比训练速度 - 尝试添加 BatchNorm 层观察对梯度消失的改善
- 在 CIFAR-10 数据集测试不同网络深度的影响
完整代码可在 Colab 笔记本 运行
正文完
