机器学习(神经网络基础篇)——个人理解篇5(梯度下降中遇到的问题)

发布于:2025-04-08 ⋅ 阅读:(31) ⋅ 点赞:(0)

        在神经网络训练中,计算参数的梯度是关键步骤。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 loss
    
    grads['W1'] = numerical_gradient(loss_W1, self.params['W1'])
    
    # 类似地处理 b1、W2、b2...
    return grads