在神经网络训练中,计算参数的梯度是关键步骤。numerical_gradient 方法旨在通过数值微分(中心差分法)计算损失函数对网络参数的梯度。然而,该方法的实现存在一个关键问题,导致梯度计算错误。
1、错误代码示例:
def numerical_gradient(self, x, t):loss_W = lambda W: self.loss(x, t) # 定义损失函数grads = {} # 存储梯度结果# 计算各参数的梯度grads['W1'] = numerical_gradient(loss_W, self.params['W1'])grads['b1'] = numerical_gradient(loss_W, self.params['b1'])grads['W2'] = numerical_gradient(loss_W, self.params['W2'])grads['b2'] = numerical_gradient(loss_W, self.params['b2'])return grads
1、1关键问题:
1、2相关疑问及解答
在梯度下降中,为什么需要对以前的权重系数进行保存,并且用更新后的数据进行梯度下降?
回答:
1. 数值梯度计算中的权重保存
在 数值微分(Numerical Gradient) 过程中,需要临时保存权重,以确保梯度计算的准确性。
场景:通过中心差分法计算梯度时,需对参数的每个分量进行微小扰动(如±ε),观察损失的变化。
原因:
避免污染参数状态:计算梯度时,需临时修改某个参数值(如W[i] += ε),但必须恢复原值,否则后续计算其他参数梯度时会使用已污染的参数值,导致误差累积。
保持计算独立性:每次扰动仅针对一个参数分量,其他参数需保持原值,确保梯度计算的正确性。
2. 优化算法中的历史权重保存
在部分高级优化算法(如动量法、Adam)中,需保存历史梯度或权重信息,以加速收敛或稳定训练。
作用:自适应调整各参数的学习率,适合稀疏梯度或非平稳目标函数。
3. 为什么需要用更新后的数据梯度下降?
梯度下降的核心逻辑是 “用当前参数计算梯度,再更新参数”。
数据更新:每次迭代使用当前批次的数据(如Mini-Batch)计算梯度,确保参数朝着当前数据分布下的最优方向更新。
时序性:若使用旧数据(如过时的权重或历史批次数据),梯度方向可能偏离真实分布,导致收敛缓慢或不稳定。
2、正确代码示例
修正方法
对每个参数单独定义闭包函数,在计算时临时修改网络参数:
def numerical_gradient(self, x, t):grads = {}# 计算 W1 的梯度def loss_W1(W):original = self.params['W1'].copy()self.params['W1'] = W # 临时修改参数loss = self.loss(x, t)self.params['W1'] = original # 恢复原始参数return lossgrads['W1'] = numerical_gradient(loss_W1, self.params['W1'])# 类似地处理 b1、W2、b2...return grads