共计 1580 个字符,预计需要花费 4 分钟才能阅读完成。
神经网络权重更新的重要性
在深度学习模型中,权重更新是训练过程中最核心的环节。通过反向传播算法,网络能够根据预测结果与真实标签之间的误差,自动调整各层权重参数,使得模型性能逐步提升。手动实现一次完整的权重更新过程,不仅能够加深对神经网络工作原理的理解,还能帮助开发者更好地诊断和解决训练过程中遇到的各种问题。

网络结构与初始参数
假设我们有一个简单的 3 层全连接网络结构如下:
- 输入层:2 个神经元(x1, x2)
- 隐藏层:2 个神经元(h1, h2),使用 Sigmoid 激活函数
- 输出层:1 个神经元(y_pred),使用 Sigmoid 激活函数
初始权重矩阵为:
W1 = [[0.1, 0.2], # 输入层到隐藏层
[0.3, 0.4]]
W2 = [[0.5], # 隐藏层到输出层
[0.6]]
前向传播与损失计算
-
输入样本 x = [0.5, 0.8],真实标签 y = 1
-
计算隐藏层输出:
$$ h = \sigma(x \cdot W1) $$
其中 σ 表示 Sigmoid 函数 -
计算输出层预测值:
$$ y_{pred} = \sigma(h \cdot W2) $$ -
计算交叉熵损失:
$$ L = -[y \cdot log(y_{pred}) + (1-y) \cdot log(1-y_{pred})] $$
反向传播梯度推导
-
计算输出层梯度:
$$ \frac{\partial L}{\partial W2} = (y_{pred} – y) \cdot h^T $$ -
计算隐藏层梯度:
$$ \frac{\partial L}{\partial W1} = [(y_{pred} – y) \cdot W2^T \odot h \odot (1-h)] \cdot x^T $$
其中⊙表示逐元素相乘 -
权重更新(学习率 η =0.1):
$$ W_{new} = W_{old} – \eta \cdot \frac{\partial L}{\partial W} $$
Python 实现代码
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 初始化参数
x = np.array([0.5, 0.8])
y = 1
W1 = np.array([[0.1, 0.2], [0.3, 0.4]])
W2 = np.array([[0.5], [0.6]])
lr = 0.1
# 前向传播
h = sigmoid(np.dot(x, W1))
y_pred = sigmoid(np.dot(h, W2))
loss = - (y * np.log(y_pred) + (1-y) * np.log(1-y_pred))
# 反向传播
dL_dW2 = (y_pred - y) * h.reshape(-1, 1)
dh = (y_pred - y) * W2.T * h * (1-h)
dL_dW1 = np.outer(x, dh)
# 权重更新
W1_new = W1 - lr * dL_dW1
W2_new = W2 - lr * dL_dW2
print(f"Updated W1:\n{W1_new}")
print(f"Updated W2:\n{W2_new}")
避坑指南
-
梯度消失 / 爆炸 :当使用 Sigmoid 激活函数时,如果初始权重设置不当,容易出现梯度消失问题。可以通过使用 ReLU 激活函数或权重初始化策略(如 Xavier 初始化)来缓解。
-
学习率设置 :学习率过大容易导致震荡不收敛,过小则训练缓慢。建议从 0.01 开始尝试,根据损失曲线调整。
-
数值稳定性检查 :在反向传播过程中,可以打印各层梯度的最大值、最小值,确保数值在合理范围内(通常绝对值不应超过 1e5)。
思考题
-
如何设计梯度检查(gradient check)来验证反向传播的实现是否正确?
-
如果将 Sigmoid 激活函数替换为 ReLU,反向传播的梯度计算会有哪些变化?
-
当使用批量训练时,权重更新策略与单样本训练有何不同?如何实现高效的批量更新?
通过手动实现神经网络权重更新的完整流程,我们能够更深入地理解深度学习模型训练的本质。在实践中,建议先在小规模网络上验证算法的正确性,再扩展到更复杂的模型结构。
