MindSpore反向传播配置关键字参数

mindspore · 浏览次数 : 0

小编点评

**MindSpore中的自定义反向传播函数传参规则** 在MindSpore深度学习框架中,自定义反向传播函数需要满足一些约束条件,包括必备参数和关键字参数。 **必备参数** 必备参数是函数的输入参数,必须在函数定义中明确指定。在Bprop函数中,必备参数包括`x`和`out`。 **关键字参数** 关键字参数是函数的输出参数,可以根据需要在函数中定义。在Bprop函数中,`out`和`dout`是关键字参数。 **自定义函数的传参顺序** MindSpore允许自定义函数的传参顺序,但必须遵守以下规则: 1. 关键字参数必须位于必备参数的后面。 2. 如果有多个关键字参数,必须按从左到右的顺序排列。 **示例** ```python import mindspore as ms class Net(nn.Cell): def bprop(self, x, y, out, dout): return msnp.cos(x) + y if y is not None else msnp.cos(x) # 创建网络实例 net = Net() # 打印网络结构 print(net(x, y=1), value_and_grad(net)(x, y=0)) ``` **注意** 在自定义函数中,如果指定了多个关键字参数,它们必须以列表形式提供。

正文

技术背景

在MindSpore深度学习框架中,我们可以向construct函数传输必备参数或者关键字参数,这跟普通的Python函数没有什么区别。但是对于MindSpore中的自定义反向传播bprop函数,因为标准化格式决定了最后的两位函数输入必须是必备参数outdout用于接收函数值和导数值。那么对于一个自定义的反向传播函数而言,我们有可能要传入多个参数。例如这样的一个案例:

import mindspore as ms
from mindspore import nn, Tensor, value_and_grad
from mindspore import numpy as msnp

class Net(nn.Cell):
    def bprop(self, x, y=1, out, dout):
        return msnp.cos(x) + y
    def construct(self, x, y=1):
        return msnp.sin(x) + y

x = Tensor([3.14], ms.float32)
net = Net()
print (net(x, y=1), value_and_grad(net)(x, y=0))

但是因为在Python的函数传参规则下,必备参数必须放在关键字参数之前,也就是out和dout这两个参数要放在前面,否则就会出现这样的报错:

  File "test_rand.py", line 53
    def bprop(self, x, y=1, out, dout):
             ^
SyntaxError: non-default argument follows default argument

按照普通Python函数的传参规则,我们可以把y这个关键字参数的放到最后面去:

import mindspore as ms
from mindspore import nn, Tensor, value_and_grad
from mindspore import numpy as msnp

class Net(nn.Cell):
    def bprop(self, x, out, dout, y=1):
        return msnp.cos(x) + y
    def construct(self, x, y=1):
        return msnp.sin(x) + y

x = Tensor([3.14], ms.float32)
net = Net()
print (net(x, y=1), value_and_grad(net)(x, y=0))

经过这一番调整之后,我们发现没有报错了,可以正常输出结果,但是这个结果似乎不太正常:

[1.0015925] (Tensor(shape=[1], dtype=Float32, value= [ 1.59254798e-03]), Tensor(shape=[1], dtype=Float32, value= [ 1.25169754e-06]))

因为这里x传入了一个近似的\(\pi\),所以在construct函数计算函数值时,得到的结果应该是\(\sin(\pi)+y\),那么这里面\(y\)\(0\)\(1\)所得到的结果都是对的。但是关键问题在反向传播函数的计算,原本应该是\(\cos(\pi)+y=y-1\),但是在这里输入的\(y=0\),而导数的计算结果却是\(0\)而不是正确结果\(-1\)。这就说明,在MindSpore的自定义反向传播函数中,并不支持传入关键字参数。

解决方案

刚好前面写了一篇关于PyTorch的文章,这篇文章中提到的两个Issue就针对此类问题。受到这两个Issue的启发,我们在MindSpore中如果需要自定义反向传播函数,可以这么写:

import mindspore as ms
from mindspore import nn, Tensor, value_and_grad
from mindspore import numpy as msnp

class Net(nn.Cell):
    def bprop(self, x, y, out, dout):
        return msnp.cos(x) + y if y is not None else msnp.cos(x)
    def construct(self, x, y=1):
        return msnp.sin(x) + y

x = Tensor([3.14], ms.float32)
net = Net()
print (net(x, y=1), value_and_grad(net)(x, y=0))

简单来说就是,把原本要传给bprop的关键字参数,转换成必备参数的方式进行传入,然后做一个条件判断:当给定了该输入的时候,执行计算一,如果不给定参数值,或者给一个None,执行计算二。上述代码的执行结果如下所示:

[1.0015925] (Tensor(shape=[1], dtype=Float32, value= [ 1.59254798e-03]), Tensor(shape=[1], dtype=Float32, value= [-9.99998748e-01]))

这里输出的结果都是正确的。

当然,这里因为我们其实是强行把关键字参数按照顺序变成了必备参数进行输入,所以在顺序上一定要严格遵守bprop所定义的必备参数的顺序,否则计算结果也会出错:

import mindspore as ms
from mindspore import nn, Tensor, value_and_grad
from mindspore import numpy as msnp

class Net(nn.Cell):
    def bprop(self, x, w, y, out, dout):
        return w*msnp.cos(x) + y if y is not None else msnp.cos(x)
    def construct(self, x, w=1, y=1):
        return msnp.sin(x) + y

x = Tensor([3.14], ms.float32)
net = Net()
print (net(x, y=1), value_and_grad(net)(x, y=0, w=2))

输出的结果为:

[1.0015925] (Tensor(shape=[1], dtype=Float32, value= [ 1.59254798e-03]), Tensor(shape=[1], dtype=Float32, value= [ 2.00000000e+00]))

那么很显然,这个结果就是因为在执行函数时给定的关键字参数跟必备参数顺序不一致,所以才出错的。

总结概要

继上一篇文章从Torch的两个Issue中找到一些类似的问题之后,可以发现深度学习框架对于自定义反向传播函数中的传参还是比较依赖于必备参数,而不是关键字参数,MindSpore深度学习框架也是如此。但是我们可以使用一些临时的解决方案,对此问题进行一定程度上的规避,只要能够自定义的传参顺序传入关键字参数即可。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/bprop-kwargs.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

参考链接

  1. https://www.cnblogs.com/dechinphy/p/18179248/torch

与MindSpore反向传播配置关键字参数相似的内容:

MindSpore反向传播配置关键字参数

继上一篇文章从Torch的两个Issue中找到一些类似的问题之后,可以发现深度学习框架对于自定义反向传播函数中的传参还是比较依赖于必备参数,而不是关键字参数,MindSpore深度学习框架也是如此。但是我们可以使用一些临时的解决方案,对此问题进行一定程度上的规避,只要能够自定义的传参顺序传入关键字参...

MindSpore强化学习:使用PPO配合环境HalfCheetah-v2进行训练

本文分享自华为云社区《MindSpore强化学习:使用PPO配合环境HalfCheetah-v2进行训练》,作者: irrational。 半猎豹(Half Cheetah)是一个基于MuJoCo的强化学习环境,由P. Wawrzyński在“A Cat-Like Robot Real-Time L

这是你没见过的MindSpore 2.0.0 for Windows GPU版

摘要:一文带你看看MindSpore 2.0.0 for Windows GPU版。 本文分享自华为云社区《MindSpore 2.0.0 for Windows GPU泄漏版尝鲜》,作者:张辉 。 在看了MindSpore架构师王磊老师的帖子( https://zhuanlan.zhihu.com

带你了解NLP的词嵌入

摘要:今天带领大家学习自然语言处理中的词嵌入的内容。 本文分享自华为云社区《【MindSpore易点通】深度学习系列-词嵌入》,作者:Skytier。 1 特征表示 在自然语言处理中,有一个很关键的概念是词嵌入,这是语言表示的一种方式,可以让算法自动的理解一些同类别的词,比如苹果、橘子,比如袜子、手

浅谈深度学习中的概率

摘要:本次就和大家聊一聊深度学习中的概率。 本文分享自华为云社区《【MindSpore易点通】深度学习中的概率》,作者: chengxiaoli。 为什么会用到概率呢?因为在深度学习中经常会需要处理随机的数据,或者包含随机性的任务,随机性也来自非常多的方面,所以在存在不确定性的情况下,都需要用到概率

大模型高效开发的秘密武器:大模型低参微调套件MindSpore PET

摘要:本文介绍大模型低参微调套件——MindSpore PET。 本文分享自华为云社区《大模型高效开发的秘密武器——大模型低参微调套件MindSpore PET篇》,作者:yd_280874276 。 人工智能进入“大模型时代”。大模型具备更强泛化能力,在各垂直领域落地时,只需要进行参数微调,就可以

基于Mindspore2.0的GPT2预训练模型迁移教程

摘要: 这篇文章主要目的是为了让大家能够清楚如何用MindSpore2.0来进行模型的迁移。 本文分享自华为云社区《MindNLP-基于Mindspore2.0的GPT2预训练模型迁移教程》,作者: Super_WZB。 前言 动机 大家好,我是Super_WZB,最近MindSpore快要上线2.

MindSpore梯度进阶操作

这篇文章主要介绍了mindspore深度学习框架中基于InsertGradientOf算子的进阶梯度操作。InsertGradientOf算子的功能跟此前介绍过的bprop功能有些类似,也是自定义梯度,但bprop更倾向于计算梯度,而InsertGradientOf算子更倾向于修改梯度,这里介绍了一...

解决大模型“开发难”,昇思MindSpore自动并行技术应用实践

本文介绍MindSpore常用的分布式并行训练技术,以及如何将并行技术应用到大模型预训练中。

MindSponge分子动力学模拟——自定义控制器(2024.05)

本文介绍了在MindSponge分子动力学模拟框架先实现自定义Controller控制器的方法,通过调控体系中的原子坐标和原子速度等,来控制系综的参量。MindSponge分子模拟框架基于MindSpore深度学习框架开发而成,对于开发者尤其是深度学习开发者来说,非常的友好。