自动微分(AD):原理与Sigmoid算子实现

4 阅读1分钟

自动微分(Automatic Differentiation,AD)是深度学习框架实现高效梯度计算的核心技术,其本质是将复杂数值计算分解为有限的基本运算,利用已知的基本运算导数与链式法则,自动组合得到整体梯度。

一、自动微分的核心思想

数值计算(如神经网络的层间计算)可拆解为一系列基础算术运算(加减乘除、指数、对数等),而每个基本运算的导数表达式是已知的(如dxd​exp(x)=exp(x),dxd​1+x1​=(1+x)2−1​)。自动微分通过记录计算图的拓扑结构,从输出反向遍历各节点,依据链式法则(∂x∂L​=∂y∂L​⋅∂x∂y​,其中L为损失函数,y为中间变量,x为输入变量)将各节点的局部梯度相乘并传播,最终得到输入相对于输出的梯度。

二、Sigmoid算子的自动微分实现(代码示例解析)

以Sigmoid激活函数(定义为y=1+exp(−x)1​)的自动微分为例,代码分为正向计算与反向传播(梯度计算)两部分:

1. 正向计算类:Sigmoid(Primitive)

Primitive是基础算子类的抽象,用于封装可微分操作。

  • __init__:初始化Sigmoid,输入为x,输出为output
  • 核心计算:output = 1/(1 + np.exp(-x)),这是Sigmoid的正向数学表达式。
  • self.init_prim_io_names:记录输入(x)与输出(output)的名称,用于构建计算图的输入输出映射。

2. 反向传播(梯度计算):get_bprop_sigmoid_grad

自动微分的反向传播需为每个算子定义梯度函数,通过注册器(@bprop_getters.register)关联到G.SigmoidGrad操作。

  • 内部定义bprop函数:接收y(Sigmoid输出)、grad(上游传递的梯度,即∂y∂L​)、out(Sigmoid输出,此处与y一致)、dout(Sigmoid的本地梯度,即∂x∂y​的载体)。
  • 梯度计算逻辑:
    • 先通过dout * grad * (1 - 2 * y)计算输入x的梯度∂x∂L​(依据Sigmoid的导数公式dxdy​=y(1−y),结合链式法则,这里dout是上游梯度,grad是链式法则的传递项,需注意代码中对Sigmoid导数的推导:∂x∂L​=∂y∂L​⋅∂x∂y​,而∂x∂y​=y(1−y),代码中dout * grad * (1 - 2 * y)可能是简化或特定场景的等价变形,核心是链式法则的梯度传递)。
    • 再通过sigmoid_grad(y, dout)调用Sigmoid梯度的正向计算(用于后续可能的二次梯度或更复杂计算的复用)。
  • 最终返回输入梯度dy与Sigmoid梯度的输出dgrad,完成反向传播的一个节点计算。

三、自动微分的优势与应用

自动微分避免了手动推导梯度的繁琐与易错性,支持任意复杂计算图的梯度计算(如深度学习模型的训练)。相比符号微分(易产生表达式爆炸)与数值微分(精度低、计算量大),自动微分兼具精确性与高效性,是现代深度学习框架(如TensorFlow、PyTorch)实现自动求导的底层核心技术。

通过上述Sigmoid算子的示例可见,自动微分通过“分解-记录-链式传播”的流程,让开发者只需关注正向计算逻辑,框架自动完成梯度的反向传播,极大降低了模型训练的门槛。