当前位置:   article > 正文

昇思MindSpore 25天学习打卡营|day6

昇思MindSpore 25天学习打卡营|day6

函数式自动微分

自动微分技术在深度学习库中处于重要地位,是整个训练算法的核心组件之一,自动微分主要解决的问题是将一个复杂的数学运算分解为一系列简单的基本运算,该功能对用户屏蔽了大量的求导细节和过程,大大降低了框架的使用门槛。

神经网络的训练主要使用反向传播算法,模型预测值(logits)与正确标签(label)送入损失函数(loss function)获得loss,然后进行方向传播计算,求得梯度(gradients),最终更新至模型参数(parameters)。

Mindspore使用函数式自动微分的设计理念,提供更接近于数学语义的自动微分接口 grad 和 value_and_grad 。下面使用一个简单的单层线性变换模型进行介绍。

函数与计算图

计算图是用图论语言表示数学函数的一种方式,也是深度学习框架表达神经网络模型的统一方法。可以根据计算图构造计算函数和神经网络。

这个模型计算图中, x 为输入, y 为正确值, wb 是需要优化的参数。可以根据计算图描述的计算过程来构造一个计算函数计算损失值

  1. x = ops.ones(5, mindspore.float32) # input tensor
  2. y = ops.zeros(3, mindspore.float32) # expected output
  3. w = Parameter(Tensor(np.random.randn(5, 3), mindspore.float32), name='w') # weight
  4. b = Parameter(Tensor(np.random.randn(3,), mindspore.float32), name='b') # bias
  5. def function(x, y, w, b):
  6. z = ops.matmul(x, w) + b
  7. loss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))
  8. return loss
  9. loss = function(x, y, w, b)
  10. print(loss)
output:
         0.5794568

上述代码中的 binary_cross_entropy_with_logits 是一个损失函数,计算预测值和目标值之间的二值交叉熵损失。

微分函数与梯度计算

为了优化模型参数,需要求参数对loss的导数:$\frac{\partial \operatorname{loss}}{\partial w}$$\frac{\partial \operatorname{loss}}{\partial b}$,此时调用mindspore.grad函数,来获得 function 的微分函数。

使用了 grad 函数的两个入参,分别为:

--fn:待求导的函数。 

--grad_position:指定求导输入位置的索引。

由于是对wb求导,所以入参的位置为(2,3).

  1. grad_fn = mindspore.grad(function, (2, 3))
  2. # 调用grads并传入function所需要的四个参数x,y,w,b
  3. grads = grad_fn(x, y, w, b)
  4. print(grads)
output:
(Tensor(shape=[5, 3], dtype=Float32, value=
[[ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01],
 [ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01],
 [ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01],
 [ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01],
 [ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01]]), Tensor(shape=[3], dtype=Float32, value= [ 1.81848228e-01,  6.19844384e-02,  1.74926624e-01]))

> 使用`grad`获得微分函数是一种函数变换,即输入为函数,输出也为函数。

Stop Gradient

停止梯度计算(梯度截断)

通常情况下,求导时会求loss对参数的导数,因此函数的输出只有loss一项。当我们希望函数输出多项时,微分函数会求所有输出项对参数的导数。此时如果想实现对某个输出项的梯度截断,或消除某个Tensor对梯度的影响,需要用到Stop Gradient操作。

将上一节中的function改为同时输出loss和z的function_with_logits,获得微分函数并执行。

  1. def function_with_logits(x, y, w, b):
  2. z = ops.matmul(x, w) + b
  3. loss = ops.binary_cross_entropy_with_logits(z, y, ops.ones_like(z), ops.ones_like(z))
  4. return loss, z
  5. grad_fn = mindspore.grad(function_with_logits, (2, 3))
  6. grads = grad_fn(x, y, w, b)
  7. print(grads)
output:
(Tensor(shape=[5, 3], dtype=Float32, value=
 [[ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00],
  [ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00],
  [ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00],
  [ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00],
  [ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00]]),
 Tensor(shape=[3], dtype=Float32, value= [ 1.06568694e+00,  1.05373347e+00,  1.30146706e+00]))

从输出结果可以看到求得 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/844466
推荐阅读
相关标签