一、函数式自动微分是什么?
神经网络的训练主要使用反向传播算法,模型预测值(logits)与正确标签(label)送入损失函数(loss function)获得loss,然后进行反向传播计算,求得梯度(gradients),最终更新至模型参数(parameters)。自动微分能够计算可导函数在某点处的导数值,是反向传播算法的一般化。自动微分主要解决的问题是将一个复杂的数学运算分解为一系列简单的基本运算,该功能对用户屏蔽了大量的求导细节和过程,大大降低了框架的使用门槛。
二、计算图是什么?
计算图是用图论语言表示数学函数的一种方式,也是深度学习框架表达神经网络模型的统一方法。我们将根据下面的计算图构造计算函数和神经网络。
三、计算损失
观察以上计算图,在这个模型中,
x
x
x为输入,
y
y
y为正确值,
w
w
w和
b
b
b是我们需要优化的参数(优化参数得到更好的网络模型),
z
z
z相当于输入
x
x
x经过网络模型计算得出的结果。
我们根据计算图描述的计算过程,构造计算函数。
其中,binary_cross_entropy_with_logits 是一个损失函数,计算预测值和目标值之间的二值交叉熵损失。
执行计算函数,可以获得计算的loss值并打印。
四、微分函数与梯度计算
为了优化模型参数,需要求参数对loss的导数:
∂
loss
∂
w
\frac{\partial \operatorname{loss}}{\partial w}
∂w∂loss和
∂
loss
∂
b
\frac{\partial \operatorname{loss}}{\partial b}
∂b∂loss,此时我们调用mindspore.grad
函数,来获得function
的微分函数。
这里使用了grad
函数的两个入参,分别为:
fn
:待求导的函数。grad_position
:指定求导输入位置的索引。
由于我们对
w
w
w和
b
b
b求导,因此配置其在function
入参对应的位置(2, 3)
。
使用
grad
获得微分函数是一种函数变换,即输入为函数,输出也为函数。
可以看到,求得
w
w
w、
b
b
b对应的梯度值发生了变化。
五、神经网络梯度计算
前述章节主要根据计算图对应的函数介绍了MindSpore的函数式自动微分,但我们的神经网络构造是继承自面向对象编程范式的nn.Cell
。接下来我们通过Cell
构造同样的神经网络,利用函数式自动微分来实现反向传播。
首先我们继承nn.Cell
构造单层线性变换神经网络。这里我们直接使用前文的
w
w
w、
b
b
b作为模型参数,使用mindspore.Parameter
进行包装后,作为内部属性,并在construct
内实现相同的Tensor操作。
接下来我们实例化模型和损失函数。
完成后,由于需要使用函数式自动微分,需要将神经网络和损失函数的调用封装为一个前向计算函数。
完成后,我们使用value_and_grad
接口获得微分函数,用于计算梯度。
由于使用Cell封装神经网络模型,模型参数为Cell的内部属性,此时我们不需要使用grad_position
指定对函数输入求导,因此将其配置为None
。对模型参数求导时,我们使用weights
参数,使用model.trainable_params()
方法从Cell中取出可以求导的参数。
执行微分函数,可以看到梯度值和前文function
求得的梯度值一致。
总结
本节介绍了如何用mindspore函数式自动微分,求微分函数和神经网络的参数梯度值。求得梯度值主要用于反向传播优化模型,这在下一节进行介绍。
个人打卡
日常感谢昇思大模型平台的ascend算力支持