共计 1526 个字符,预计需要花费 4 分钟才能阅读完成。
神经网络权重更新的重要性
神经网络的核心在于通过不断调整权重来最小化损失函数。手动实现反向传播不仅帮助我们深入理解梯度下降的工作原理,还能避免框架黑箱操作带来的困惑。本文将通过一个具体案例,带你完整走一遍从损失计算到权重更新的全过程。

网络结构与初始参数
假设我们有一个简单的 2 层网络:
- 输入层:2 个节点 (x1, x2)
- 隐藏层:2 个节点 (h1, h2),使用 ReLU 激活
- 输出层:1 个节点 (ŷ),使用 Sigmoid 激活
初始权重矩阵为:
W1 = [[0.3, -0.1], # 输入层→隐藏层
[0.2, 0.4]]
W2 = [[0.1], # 隐藏层→输出层
[-0.2]]
前向传播计算
-
给定输入 x =[1, 0.5] 和真实标签 y =1:
-
隐藏层计算:
h = ReLU(W1^T x) = ReLU([[0.3*1 + 0.2*0.5], [-0.1*1 + 0.4*0.5]]) = [0.4, 0.1] -
输出层计算:
ŷ = σ(W2^T h) = σ(0.1*0.4 + (-0.2)*0.1) ≈ 0.505 -
交叉熵损失:
L = -[y*ln(ŷ) + (1-y)*ln(1-ŷ)] ≈ 0.683
反向传播推导
-
输出层梯度:
∂L/∂W2 = (ŷ - y) * h = [-0.495] * [0.4, 0.1] = [-0.198, -0.0495] -
隐藏层梯度:
∂L/∂h = (ŷ - y) * W2 = [-0.495] * [0.1, -0.2] = [-0.0495, 0.099]∂h/∂W1 = I(x > 0) * x = [1, 0.5] (因为 ReLU 在 0.4 和 0.1 处激活)∂L/∂W1 = ∂L/∂h * ∂h/∂W1 = [[-0.0495*1, -0.0495*0.5], [0.099*1, 0.099*0.5]]
Python 实现
import numpy as np
def relu(x):
return np.maximum(0, x)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 初始化参数
W1 = np.array([[0.3, -0.1], [0.2, 0.4]])
W2 = np.array([[0.1], [-0.2]])
# 前向传播
x = np.array([1, 0.5])
h = relu(W1.T @ x)
y_pred = sigmoid(W2.T @ h)
loss = -np.log(y_pred) # 简化损失计算
# 反向传播
dL_dy_pred = -1 / y_pred
dy_pred_dz2 = y_pred * (1 - y_pred)
dz2_dW2 = h
dL_dW2 = dL_dy_pred * dy_pred_dz2 * dz2_dW2
dz2_dh = W2
dL_dh = dL_dy_pred * dy_pred_dz2 * dz2_dh
dh_dz1 = (h > 0).astype(float)
dz1_dW1 = x
dL_dW1 = np.outer(dz1_dW1, dL_dh * dh_dz1)
# 权重更新 (学习率 η =0.1)
eta = 0.1
W1_new = W1 - eta * dL_dW1
W2_new = W2 - eta * dL_dW2
避坑指南
-
梯度消失 :当使用 Sigmoid 时,其导数最大值为 0.25,多层传播时梯度会指数级减小。解决方案:改用 ReLU 或 LeakyReLU
-
学习率选择 :
- 常用初始值:0.001-0.1
-
观察损失曲线:若震荡→调小;若下降慢→调大
-
数值检查 :
- 用有限差分法验证梯度:
eps = 1e-5 (loss(W1+eps) - loss(W1-eps)) / (2*eps) ≈ 计算出的梯度
思考题
-
如何设计自动化测试来验证反向传播的实现正确性?
-
如果把隐藏层激活函数换成 Tanh,梯度计算公式会有哪些变化?
-
当使用批量样本训练时,权重更新规则需要如何调整?
通过这次手动实现,相信你对反向传播的底层机制有了更直观的理解。建议尝试用不同网络结构复现这个过程,这是掌握深度学习核心原理的最佳途径。
正文完
发表至: 未分类
四天前
