形参与实参的不对应导致ops.GradOperation执行报错:The parameters number of the function is 2, but the number of provided arguments is 1.

1. 系统环境

硬件环境(Ascend/GPU/CPU): GPU
软件环境: MindSpore 版本: 1.7.0
执行模式: 静态图(GRAPH) – Python 版本: 3.7.6
操作系统平台: linux

2. 报错信息

2.1 问题描述

自定义训练网络中,进行反向传播计算梯度时,少给ops.GradOperation传入了一个参数导致执行报错。

2.2 报错信息

TypeError: mindspore/ccsrc/pipeline/jit/static_analysis/stack_frame.cc:101 DoJump] The parameters number of the function is 2, but the number of provided arguments is 1.

2.3 脚本代码

class TrainOneStepCell(nn.Cell):

    def __init__(self, network, optimizer, sens=1.0):
        super(TrainOneStepCell, self).__init__(auto_prefix=False)
        self.network = network
        self.network.set_grad()
        self.optimizer = optimizer
        self.weights = self.optimizer.parameters
        self.grad = ops.GradOperation(get_by_list=True, sens_param=True)

    def construct(self,*inputs):
        """Defines the computation performed."""
        loss = self.network(*inputs)
        grads = self.grad(self.network, self.weights)(*inputs)
        self.optimizer(grads)
        return grads,loss

3. 根因分析


看报错信息,翻译意思就是函数的形参数为2,但提供的实参数为1。
查看官网文档关于自定义训练网络的设置,再进行反向传播,计算梯度时需要将loss传入。原因是因为反向传播需要根据loss值进行计算。

4. 解决方案

解决方案说明:根据官网文档,将loss值传入self.grad。
修改后代码:

class TrainOneStepCell(nn.Cell):

    def __init__(self, network, optimizer, sens=1.0):
        super(TrainOneStepCell, self).__init__(auto_prefix=False)
        self.network = network
        self.network.set_grad()
        self.optimizer = optimizer
        self.weights = self.optimizer.parameters
        self.grad = ops.GradOperation(get_by_list=True, sens_param=True)

    def construct(self,*inputs):
        """Defines the computation performed."""
        loss = self.network(*inputs)
        grads = self.grad(self.network, self.weights)(*inputs,loss)
        self.optimizer(grads)
        return grads,loss

修改后,程序正常训练。