使用MindSpore报错AttributeError: The 'Controller' object has no attribute 'to'.

1 系统环境

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

#2 报错信息

2.1 问题描述

将pytorch转换成mindspore代码的过程中报错AttributeError: The ‘Controller’ object has no attribute ‘to’.。

2.2 脚本信息

self.controller = Controller(self.args).to(device)

其中Controller定义为:

class Controller(nn.Module):

3 根因分析

根据文档https://www.mindspore.cn/docs/zh-CN/r2.0/migration_guide/typical_api_comparision.html?highlight=device
pytorch与mindspore device的不同
PyTorch 在构建模型时,通常会利用 torch.device 指定模型和数据绑定的设备,是在 CPU 还是 GPU 上,如果支持多 GPU,还可以指定具体的 GPU 序号。绑定相应的设备后,需要将模型和数据部署到对应设备,代码如下:

import os  
import torch  
from torch import nn  
    
# bind to the GPU 0 if GPU is available, otherwise bind to CPU  
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # 单 GPU 或者 CPU  
# deploy model to specified hardware  
model.to(device)  
# deploy data to specified hardware  
data.to(device)  
    
# distribute training on multiple GPUs  
if torch.cuda.device_count() > 1:  
    model = nn.DataParallel(model, device_ids=[0,1,2])  
    model.to(device)  
    
    # set available device  
    os.environ['CUDA_VISIBLE_DEVICE']='1'  
    model.cuda()  

而在 MindSpore 中,我们通过 context 中 的 device_target 参数 指定模型绑定的设备,device_id 指定设备的序号。与 PyTorch 不同的是,一旦设备设置成功,输入数据和模型会默认拷贝到指定的设备中执行,不需要也无法再改变数据和模型所运行的设备类型。代码如下:

import mindspore as ms  
ms.set_context(device_target='Ascend', device_id=0)  
    
# define net  
Model = ..  
# define dataset  
dataset = ..  
# training, automatically deploy to Ascend according to device_target  
Model.train(1, dataset)  

此外,网络运行后返回的 Tensor 默认均拷贝到 CPU 设备,可以直接对该 Tensor 进行访问和修改,包括转成 numpy 格式,无需像 PyTorch 一样需要先执行 tensor.cpu 再转换成 numpy 格式。
pytorch与mindspore Module的不同
使用 PyTorch 构建网络结构时,我们会用到nn.Module 类,通常将网络中的元素定义在__init__ 函数中并对其初始化,将网络的图结构表达定义在forward 函数中,通过调用这些类的对象完成整个模型的构建和训练。nn.Module 不仅为我们提供了构建图接口,它还为我们提供了一些常用的 API ,来帮助我们执行更复杂逻辑。
MindSpore 中的 nn.Cell 类发挥着和 PyTorch 中 nn.Module 相同的作用,都是用来构建图结构的模块,MindSpore 也同样提供了丰富的 API 供开发者使用,虽然名字不能一一对应,但 nn.Module 中常用的功能都可以在nn.Cell 中找到映射。

4 解决方案

首先 torch.nn.Module => mindspore.nn.Cell

import mindspore as ms  
from mindspore import ops, nn  
ms.set_context(device_target='GPU', device_id = 0)  
class Controller(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.dense = nn.Dense(2, 3)  
    
    def construct(self, x):  
        return self.dense(x)  
net = Controller()  
print(net(ops.ones((1,2))))  
    
[[0.00981624 0.00829783 0.00173066]]