反向传播算法 Python 实现:从计算图到 2 层网络梯度验证

📅 2026/7/5 11:18:38
反向传播算法 Python 实现:从计算图到 2 层网络梯度验证
反向传播算法 Python 实现从计算图到 2 层网络梯度验证1. 计算图与反向传播基础计算图是理解反向传播算法的关键工具。它将数学运算分解为节点和边的有向图其中节点代表变量或运算边代表数据流向。在神经网络中前向传播对应计算图从左到右的计算过程而反向传播则是从右到左的梯度计算。让我们通过一个简单的乘法层实现来理解核心机制class MulLayer: def __init__(self): self.x None self.y None def forward(self, x, y): self.x x # 保存输入用于反向传播 self.y y return x * y def backward(self, dout): dx dout * self.y # 上游梯度乘以另一输入 dy dout * self.x # 上游梯度乘以另一输入 return dx, dy这个实现展示了反向传播的核心特征前向传播时保存输入值反向传播时利用链式法则计算局部梯度梯度通过乘以翻转的输入值进行传播2. 神经网络层的模块化实现构建神经网络需要实现几种基础层类型。以下是关键层的实现原理2.1 仿射层Affine Layer仿射变换实现权重矩阵乘法加偏置class Affine: def __init__(self, W, b): self.W W self.b b self.x None self.dW None self.db None def forward(self, x): self.x x return np.dot(x, self.W) self.b def backward(self, dout): dx np.dot(dout, self.W.T) self.dW np.dot(self.x.T, dout) self.db np.sum(dout, axis0) return dx2.2 ReLU激活层class Relu: def __init__(self): self.mask None def forward(self, x): self.mask (x 0) # 记录小于0的位置 out x.copy() out[self.mask] 0 return out def backward(self, dout): dout[self.mask] 0 # 小于0的位置梯度为0 return dout2.3 Softmax-with-Loss层class SoftmaxWithLoss: def __init__(self): self.loss None self.y None self.t None def forward(self, x, t): self.t t self.y softmax(x) self.loss cross_entropy_error(self.y, self.t) return self.loss def backward(self, dout1): batch_size self.t.shape[0] dx (self.y - self.t) / batch_size return dx3. 两层神经网络实现结合上述基础层我们可以构建完整的神经网络class TwoLayerNet: def __init__(self, input_size, hidden_size, output_size): # 初始化权重 self.params {} self.params[W1] np.random.randn(input_size, hidden_size) self.params[b1] np.zeros(hidden_size) self.params[W2] np.random.randn(hidden_size, output_size) self.params[b2] np.zeros(output_size) # 构建网络层 self.layers OrderedDict() self.layers[Affine1] Affine(self.params[W1], self.params[b1]) self.layers[Relu1] Relu() self.layers[Affine2] Affine(self.params[W2], self.params[b2]) self.last_layer SoftmaxWithLoss() def predict(self, x): for layer in self.layers.values(): x layer.forward(x) return x def loss(self, x, t): y self.predict(x) return self.last_layer.forward(y, t) def gradient(self, x, t): # 前向传播 self.loss(x, t) # 反向传播 dout 1 dout self.last_layer.backward(dout) layers list(self.layers.values()) layers.reverse() for layer in layers: dout layer.backward(dout) # 收集梯度 grads {} grads[W1] self.layers[Affine1].dW grads[b1] self.layers[Affine1].db grads[W2] self.layers[Affine2].dW grads[b2] self.layers[Affine2].db return grads4. 梯度验证反向传播实现的正确性可以通过数值梯度验证def numerical_gradient(f, x): h 1e-4 grad np.zeros_like(x) it np.nditer(x, flags[multi_index], op_flags[readwrite]) while not it.finished: idx it.multi_index tmp_val x[idx] x[idx] tmp_val h fxh1 f(x) x[idx] tmp_val - h fxh2 f(x) grad[idx] (fxh1 - fxh2) / (2*h) x[idx] tmp_val it.iternext() return grad # 验证示例 network TwoLayerNet(input_size784, hidden_size50, output_size10) x_batch x_train[:3] t_batch t_train[:3] grad_numerical numerical_gradient(lambda w: network.loss(x_batch, t_batch), network.params[W1]) grad_backprop network.gradient(x_batch, t_batch)[W1] # 计算相对误差 diff np.average(np.abs(grad_backprop - grad_numerical)) print(diff) # 通常应小于1e-75. 训练流程与优化完整的训练循环包含以下关键步骤# 超参数设置 iters_num 10000 batch_size 100 learning_rate 0.1 for i in range(iters_num): # 小批量数据 batch_mask np.random.choice(train_size, batch_size) x_batch x_train[batch_mask] t_batch t_train[batch_mask] # 计算梯度 grad network.gradient(x_batch, t_batch) # 参数更新 for key in (W1, b1, W2, b2): network.params[key] - learning_rate * grad[key] # 记录学习过程 loss network.loss(x_batch, t_batch) train_loss_list.append(loss)实际应用中还需要考虑以下优化学习率调度Learning rate scheduling动量Momentum权重衰减Weight decay批量归一化Batch Normalization反向传播算法通过自动微分实现了高效梯度计算使得深度神经网络的训练成为可能。理解其底层实现原理对于调试网络和开发新架构至关重要。