MindSpore梯度计算报错AttributeError: module ‘mindspore’ has no attribute ‘value_and_grad’分析及解决

1 系统环境

  • 硬件环境(Ascend/GPU/CPU): Ascend910
  • MindSpore版本: mindspore=2.0.0
  • 执行模式(PyNative/ Graph): PyNative
  • Python版本: Python=3.8
  • 操作系统平台: Linux

2 报错信息

2.1 问题描述

在使用MindSporePyNative模式进行模型训练时,尝试通过mindspore.value_and_grad接口获取梯度计算函数,但程序抛出了AttributeError异常。具体场景为在自定义损失函数中计算梯度以便进行参数优化。一个简单的全连接神经网络,并在前向计算后使用value_and_grad方法获取梯度。相关代码段如下:

2.2 脚本信息

import mindspore
from mindspore import nn, Tensor
import numpy as np
class SimpleNet(nn.Cell):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc = nn.Dense(10, 1)
    
    def construct(self, x):
        return self.fc(x)
net = SimpleNet()
optimizer = nn.SGD(net.trainable_params(), learning_rate=0.01)
def forward_fn(x, y):
    output = net(x)
    loss = nn.MSELoss()(output, y)
    return loss
# 获取梯度函数时出现报错
grad_fn = mindspore.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)

2.3 报错信息

AttributeError: module ‘mindspore’ has no attribute ‘value_and_grad’

3 根因分析

根据以上信息可以知道使用的MindSpore=2.0.0,在MindSpore=2.0.0版本中value_and_grad不在mindspore.nn模块中。

4 解决方案

通过以上分析可以知道是value_and_grad算子的导入路径不对,查看2.0.0版本的文档可知,value_and_grad是直接在mindspore下面。所以可以如下修改。

import mindspore
from mindspore import nn, Tensor, value_and_grad  # 重点:value_and_grad导入
import numpy as np

class SimpleNet(nn.Cell):
    def __init__(self):
        super(SimpleNet, self).__init__()
        self.fc = nn.Dense(10, 1)
    
    def construct(self, x):
        return self.fc(x)

net = SimpleNet()
optimizer = nn.SGD(net.trainable_params(), learning_rate=0.01)

def forward_fn(x, y):
    output = net(x)
    loss = nn.MSELoss()(output, y)
    return loss

# 修正:使用 ops.value_and_grad
grad_fn = value_and_grad(forward_fn, 
                         grad_position=None, 
                         weights=optimizer.parameters, 
                         has_aux=False)  # 注意:你的函数只返回loss,应设为False

# 使用示例
x = Tensor(np.random.randn(32, 10).astype(np.float32))
y = Tensor(np.random.randn(32, 1).astype(np.float32))

loss, grads = grad_fn(x, y)
print(f"Loss: {loss}")
print(f"Gradients calculated: {len(grads)}")