Cell对象序列化失败-使用pickle.dumps保存到本地后重新加载失败

1 系统环境

硬件环境(Ascend/GPU/CPU): CPU
MindSpore版本: 2.0.0-rc1
执行模式(PyNative/ Graph): 不限
Python版本: 3.7.5
操作系统平台:Linux Ubuntu 18.04

2 报错信息

2.1 问题描述

示例代码为使用第三方工具包pickle保存mindspore框架搭建的vgg16模型及pytorch框架的搭建的vgg16模型。pytorch框架搭建的vgg16模型可以正常保存并重新读取加载,但mindspore框架搭建的模型则读取失败。

2.2 报错信息

AttributeError: 'Tensor' object has no attribute 'init'

3 根因分析

最终报错行

  File "D:\Anaconda3\lib\site-packages\mindspore\common\parameter.py", line 210, in __new__  
    init_data_flag = bool(isinstance(default_input, Tensor) and default_input.has_init)  
  File "D:\Anaconda3\lib\site-packages\mindspore\common\tensor.py", line 503, in has_init  
    return self.init is not None  
AttributeError: 'Tensor' object has no attribute 'init'

pickle在反序列化的时候会创建对应的对象.
最终报错是parameter的创建失败,所以问题等价于含有parameter的模型反序列化失败, 首先简化下出错的代码.

import mindspore as ms  
import numpy as np  
from mindspore import nn, ops, Tensor, Parameter  
import pickle  
  
class Network(nn.Cell):  
    def __init__(self):  
        super().__init__()  
        self.w = Parameter(Tensor(np.random.randn(5, 3), ms.float32), name='weight')  
        self.b = Parameter(Tensor(np.random.randn(3,), ms.float32), name='bias')  
        #self.w = Tensor(np.random.randn(5, 3), ms.float32)  
        #self.b = Tensor(np.random.randn(3,), ms.float32)  
  
    def construct(self, x):  
        out = ops.matmul(x, self.w)  
        out = out + self.b  
        return out  
  
x = ops.ones(5, ms.float32)  
model = Network()  
with open("d:\\pic2.txt",'wb') as f:  
  pickle.dump(model,f)  
with open("d:\\pic2.txt",'rb') as f:  
    b = pickle.load(f)  
print('out: ', b(x))

上面的代码和压缩包里的代码报错是一样的.
上面网络中如果

self.w = Tensor(np.random.randn(5, 3), ms.float32)
self.b = Tensor(np.random.randn(3,), ms.float32)

那就可以正常运行.
代码出错行

mindspore\common\parameter.py line 210

def __new__(cls, default_input, *args, **kwargs):
    init_data_flag = bool(isinstance(default_input, Tensor) and default_input.has_init)


mindspore\common\tensor.py line 503

@property
def has_init(self):
    """Whether tensor is initialized."""
    return self.init is not None

反序列化的时候对象创建的时候没有init属性, 所以调用has_init就报错了.

4 解决方案

修改mindspore\common\tensor.py line 503

增加判断

@property  
def has_init(self):  
"""Whether tensor is initialized."""  
    if hasattr(self, 'init'):  
        return self.init is not None  
    return None  

修改后正常运行