问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

梯度检查:保障模型训练准确性的关键环节

创作时间:
作者:
@小白创作中心

梯度检查:保障模型训练准确性的关键环节

引用
CSDN
1.
https://blog.csdn.net/uncle_ll/article/details/145121954

梯度检查是保障模型训练准确性的关键环节。通过数值微分和泰勒公式,可以有效验证反向传播计算的梯度是否准确,从而避免因梯度计算错误导致的模型训练失败。本文将详细介绍梯度检查的原理、实现方法及注意事项。

为何要做梯度检查

在神经网络算法的复杂架构中,反向传播是计算目标函数关于每个参数梯度的核心机制,其计算结果可视为解析梯度。然而,由于神经网络涉及的参数数量极为庞大,在代码实现反向传播计算梯度的过程中,极易产生误差。这些误差可能如同隐藏在暗处的 “陷阱”,导致最终迭代所获得的参数值偏离最优解,使模型的性能大打折扣。

为了有效验证代码中反向传播计算的梯度是否精准无误,梯度检验(gradient check)应运而生。其核心原理在于通过计算数值梯度,获取梯度的近似值,并将其与反向传播得到的梯度进行细致比对。若两者之间的差异微小,便可有力证明反向传播的代码逻辑正确可靠;反之,则表明代码可能存在缺陷或错误,需要深入排查与修正。

数值微分

导数概念回忆

导数的基本定义公式
$$
f'(x)=\lim_{h \to 0} \frac{f(x+h)-f(x)}{h}
$$
其直观含义为当x发生微小变化h(h为无限小的值)时,函数f(x)值的相应变化程度。在Python中,可通过如下代码片段实现简单的数值微分计算:

def numerical_diff(f, x):
    h = 1e-5
    d = (f(x+h) - f(x))/h
    return d

不过,由于计算机存在舍入误差,h的取值不能过小,比如1e-10可能会造成计算结果上的误差,所以一般用[1e-4, 1e-7]之间的数值。但是如果使用上述方法会有一个问题,如图所示。

红色实线为真实的导数切线,蓝色虚线是上述方法的体现,即从x到x+h画一条直线,来模拟真实导数。但是可以明显看出红色实线和蓝色虚线的斜率是不等的。因此通常用绿色的虚线来模拟真实导数,公式变为:
$$
f'(x) = \lim_{h \to 0} \frac{f(x+h)-f(x-h)}{2h}
$$
公式2被称为双边逼近方法。用双边逼近形式会比单边逼近形式的误差小100~10000倍左右,这一结论可通过泰勒展开公式进行严谨证明。

泰勒公式

泰勒公式是一种强大的数学工具,它能够在$x = x_0$处具有n阶导数的函数$f(x)$利用关于$(x-x_0)$的n次多项式来逼近函数。若函数$f(x)$在包含$x_0$的某个闭区间$[a,b]$上具有n阶导数,且在开区间$(a,b)$上具有$n+1$阶导数,则对闭区间$[a,b]$上任意一点$x$,下式成立:
$$
f(x)=\frac{f(x_0)}{0!} + \frac{f'(x_0)}{1!}(x-x_0)+\frac{f''(x_0)}{2!}(x-x_0)^2 + ...+\frac{f^{(n)}(x_0)}{n!}(x-x_0)^n+R_n(x)
$$
其中,$f^{(n)}(x)$表示$f(x)$的n阶导数,等号后的多项式称为函数$f(x)$在$x_0$处的泰勒展开式,剩余的$R_n(x)$是泰勒公式的余项,是$(x-x_0)^n$的高阶无穷小。利用泰勒展开公式,令$x = \theta + h, x_0=\theta$,可以得到:
$$
f(\theta + h)=f(\theta) + f'(\theta)h + O(h^2)
$$

单边逼近误差

如果用单边逼近,把公式4两边除以h后变形:
$$
f'(\theta) + O(h)=\frac{f(\theta+h)-f(\theta)}{h}
$$
公式5已经和公式1的定义非常接近了,只是左侧多出来的第二项,就是逼近的误差,是个$O(h)$级别的误差项。

双边逼近误差

如果用双边逼近,用三阶泰勒展开:令$x = \theta + h, x_0=\theta$,可以得到:
$$
f(\theta + h)=f(\theta) + f'(\theta)h + f''(\theta)h^2 + O(h^3)
$$
再令$x = \theta - h, x_0=\theta$可以得到:
$$
f(\theta - h)=f(\theta) - f'(\theta)h + f''(\theta)h^2 - O(h^3)
$$
公式6减去公式7,有:
$$
f(\theta + h) - f(\theta - h)=2f'(\theta)h + 2O(h^3)
$$
两边除以$2h$:
$$
f'(\theta) + O(h^2)={f(\theta + h) - f(\theta - h) \over 2h}
$$
公式9中,左侧多出来的第二项,就是双边逼近的误差,是个$O(h^2)$级别的误差项,比公式5中的误差项小很多数量级。

实例说明

公式2就是梯度检查的理论基础。比如一个函数:
$$
f(x) = x^2 + 3x
$$
看一下它在$x=2$处的数值微分,令$h = 0.001$:
$$
f(x+h) = f(2+0.001) = (2+0.001)^2 + 3 \times (2+0.001) = 10.007001
$$
$$
f(x-h) = f(2-0.001) = (2-0.001)^2 + 3 \times (2-0.001) = 9.993001
$$
$$
\frac{f(x+h)-f(x-h)}{2h}=\frac{10.007001-9.993001}{2 \times 0.001}=7
$$
再看它的数学解析解:
$$
f'(x)=2x+3
$$
$$
f'(x|_{x=2})=2 \times 2+3=7
$$
可以看到公式10和公式11的结果一致。当然在实际应用中,一般不可能会完全相等,只要两者的误差小于$1e-5$以下就认为是满足精度要求的。

算法实现

在神经网络中,假设使用多分类的交叉熵函数,则其形式为:
$$
J(w,b) =- \sum_{i=1}^m \sum_{j=1}^n y_{ij} \ln a_{ij}
$$
$m$是样本数,$n$是分类数。参数向量化需要检查的是关于W和B的梯度,而W和B是若干个矩阵,而不是一个标量,所以在进行梯度检验之前先做好准备工作,那就是把矩阵W和B向量化,然后把神经网络中所有层的向量化的W和B连接在一起(concatenate),成为一个大向量,称之为$J(\theta)$,然后对通过back-prop过程得到的W和B求导的结果$d\theta_{real}$也做同样的变换,接下来就要开始做检验了。

向量化的W,B连接以后,统一称作为$\theta$,按顺序用不同下标区分,于是有$J(\theta)$的表达式为:
$$
J(w,b)=J(\theta_1,...,\theta_i,...,\theta_n)
$$
对于上式中的每一个向量,依次使用公式2的方式做检查,于是有对第$i$个向量值的梯度检查公式:
$$
\frac{\partial J}{\partial \theta_i}=\frac{J(\theta_1,...,\theta_i+h,...,\theta_n) - J(\theta_1,...,\theta_i-h,...,\theta_n)}{2h}
$$
由于是比较两个向量对应分量的差异,可采用对应分量差的平方和的开方(欧氏距离)来度量。但为了获得一个更具通用性和可比性的评估指标,我们希望得到一个比率。这是因为在神经网络训练过程中,参数的梯度会随着迭代不断变化。在初始迭代阶段,参数梯度往往较大,而随着迭代逐渐收敛,梯度趋近于 0。若仅依据欧氏距离来判断梯度检验效果,由于其与梯度值直接相关,在迭代过程中缺乏固定的评判标准。而通过引入分母,将梯度的平方和纳入考虑范围,实现大值与大值比较,小值与小值比较,从而得到一个稳定的比率,以此作为衡量梯度检验效果的标准。

具体算法步骤如下:

  1. 采用合适的初始化方法(如随机初始化或其他非 0 初始化方法)对神经网络的所有矩阵参数进行初始化。
  2. 把所有层的W,B都转化成向量形式,并按顺序存放在$\theta$中
  3. 随机设置X值,为提高计算稳定性,建议将其归一化处理至$[0,1]$之间
  4. 执行一次前向计算,紧接着进行一次反向计算,从而获取各参数的梯度$d\theta_{real}$
  5. 把得到的梯度$d\theta_{real}$变化成向量形式,其尺寸应该和第2步中的$\theta$相同,且一一对应(W对应$dW$,B对应$dB$)
  6. 对2中的$\theta$向量中的每一个值,运用双边逼近公式计算得到$d\theta_{approx}$
  7. 比较$d\theta_{real}$和$d\theta_{approx}$的值,通过计算两个向量之间的欧式距离:
    $$
    diff = \frac{\parallel d\theta_{real} - d\theta_{approx}\parallel_2}{\parallel d\theta_{approx}\parallel_2 + \parallel d\theta_{real}\parallel_2}
    $$

结果判断:

  1. $diff > 1e^{-2}$则表明梯度计算极有可能出现严重问题,需要深入排查。
  2. $1e^{-2} > diff > 1e^{-4}$则可能存在问题,需进一步仔细检查。
  3. $1e^{-4} > diff > 1e^{-7}$对于使用非光滑激励函数的情况来说该结果可以接受,但是如果使用平滑的激励函数如$tanh$或者$softmax$,此结果仍偏高,需优化。
  4. $1e^{-7} > diff$则表明梯度计算较为准确,可视为成功通过梯度检验,值得庆祝。

此外,随着网络深度的增加,误差可能会逐渐积累。例如,在使用10层的网络,若得到的相对误差为$1e-2$,在这种情况下该结果也可勉强接受。

注意事项

  1. 梯度检验切不可用于模型训练过程中的梯度计算。由于其计算速度相对较慢,在实际训练时,应依旧采用反向传播(backprop)方法计算参数梯度,而将梯度检验作为一种调试工具,用于检验反向传播过程的准确性。
  2. 若在梯度检验过程中发现反向传播过程存在问题,需要对所有参数进行全面计算与分析,以精准定位造成计算偏差的源头。偏差可能源于求解B时出现异常,也可能是某一层W的计算失误。梯度检验能够有效确定问题发生的大致范围,为调试工作提供有力线索。
  3. 正则化处理不容忽视。当添加了二范数正则化时,在使用反向传播计算参数梯度时,务必注意梯度形式已发生相应变化,应正确添加正则化部分的梯度贡献。同理,在进行梯度检验时,也要确保目标函数J的形式已根据正则化进行了正确调整。
  4. 若使用了 dropout 正则化,梯度检验将无法正常使用。这是因为 dropout 操作会按照一定的保留概率随机保留部分节点,其引入的随机性使得目标函数J的形式变得极为复杂且不明确,从而导致无法运用梯度检验来验证反向传播过程。若确实需要在使用 dropout 的同时检验反向传播,可先将保留概率设置为 1,即保留全部节点,然后进行梯度检验。若检验结果无问题,再根据实际需求调整保留概率以应用 dropout 操作。
  5. 一种较为特殊且少见的情况是,在模型初始化阶段,W和B的值通常较小,此时反向传播过程可能正常运行。但随着迭代的推进,W和B的值逐渐增大,反向传播过程可能会出现问题,且梯度差距可能会逐渐扩大。为有效避免此类情况的发生,建议在模型训练过程中多次进行梯度检验。例如,在初始化权重时进行首次检验,在迭代一段时间后,再次使用梯度检验对反向传播过程进行验证,确保模型训练的稳定性与准确性。

总结

在机器学习模型的训练过程中,梯度检查是不可或缺的重要环节。它基于数值微分原理,通过双边逼近方法获取梯度的近似值,并与反向传播计算出的梯度进行精确比对,以此来验证梯度计算的准确性。从理论层面的导数概念、泰勒公式推导,到实践中的实例计算、算法实现步骤,以及在不同网络环境和正则化条件下的应用注意事项,都全面展示了梯度检查的复杂性与严谨性。

正确运用梯度检查能够帮助我们及时发现模型训练中的梯度异常问题,避免因梯度计算错误而导致模型训练效果不佳甚至失败。它不是训练过程中的计算工具,而是调试和保障训练准确性的得力助手。通过对各种细节的把控,如合适的取值、向量的处理、误差的判断标准以及与不同正则化方法的协同等,我们能够更好地发挥梯度检查的作用,提升模型训练的可靠性和稳定性,为构建高效、准确的机器学习模型奠定坚实的基础,从而在复杂多变的人工智能应用场景中实现更优的性能表现。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号