反向传播(Backpropagation)是神经网络训练的基石算法,它如同一位严格的导师,精确指出网络每个参数应该如何调整才能减少预测误差。这个算法首次被Rumelhart等人于1986年系统提出,现已成为深度学习的基础。
# 以3层网络为例
def forward(x, W1, b1, W2, b2):
z1 = np.dot(W1, x) + b1
a1 = relu(z1) # 第一层激活
z2 = np.dot(W2, a1) + b2
a2 = sigmoid(z2) # 输出层激活
return a2, (z1, a1, z2, a2)
存储中间结果:z(加权输入)、a(激活输出)用于后续梯度计算
以二分类交叉熵损失为例:
def compute_loss(y_true, y_pred):
return -np.mean(y_true*np.log(y_pred) + (1-y_true)*np.log(1-y_pred))
dz2 = y_pred - y_true
dW2 = np.dot(a1.T, dz2)
db2 = np.sum(dz2, axis=0)
dz1 = np.dot(dz2, W2.T) * relu_derivative(z1) # ⊙表示逐元素乘
learning_rate = 0.01
W1 -= learning_rate * dW1
b1 -= learning_rate * db1
考虑三层网络:输入层→隐藏层→输出层
梯度计算路径:
# 避免log(0)的情况
epsilon = 1e-7
y_pred = np.clip(y_pred, epsilon, 1 - epsilon)
# 向量化实现(批处理)
def backward(x_batch, y_batch, cache):
z1, a1, z2, a2 = cache
batch_size = x_batch.shape[0]
dz2 = (a2 - y_batch) / batch_size # 平均梯度
dW2 = np.dot(a1.T, dz2)
db2 = np.sum(dz2, axis=0)
dz1 = np.dot(dz2, W2.T) * relu_derivative(z1)
dW1 = np.dot(x_batch.T, dz1)
db1 = np.sum(dz1, axis=0)
return dW1, db1, dW2, db2
# 数值梯度验证
def numerical_gradient(f, x, eps=1e-4):
grad = np.zeros_like(x)
for i in range(x.size):
tmp = x[i]
x[i] = tmp + eps
f_plus = f(x)
x[i] = tmp - eps
f_minus = f(x)
grad[i] = (f_plus - f_minus) / (2*eps)
x[i] = tmp
return grad
想象你在教机器人投篮:
前向传播:
观察结果:
反向指导:
链式教学:
关键点:
为什么有效: