AttributeError: Can't get attribute 'CNN' on <module '__main__' from XXX
这个错误是由于保存模型中,有CNN类的序列化导致的,我在网上也看了好多教程,方法各种各样(但有的不可行),总结一下:
(本人没有系统学过python,属于边用边学,有错误的话欢迎指正,序列化的话我在Java中学过,但相信原理都是相通的)
先说一下,我出现这个原因的时候,CNN构建的写法:
1、我在cnn_model.py文件中构建了一个CNN类,也就是卷积神经网络的架构
2、在类CNN的下面,我实体化了一个model = CNN(xxxx),然后利用数据集进行训练和测试
3、接下来我想弄出一个界面,我在gui.py文件中写出来了界面,但是我发现每次运行这个界面就需要训练一次模型,因此我想保存下来这个模型
4、我在cnn_model.py中使用torch.save()保存整个模型,然后在gui.py中用torch.load()加载
很好!!!Bug产生了
解决方式:(建议先看一下我的CNN构建写法)
- 将CNN类单独放一个文件
- 在另一个文件中训练和测试模型,然后保存模型即可。
- 也就是有的教程说的代码纯净化
1、也有教程说,将CNN类的定义显性声明在gui.py文件中(即将CNN的类再抄一遍),然后再torch.load()加载,亲测我这不可行。
看到一个最好的解释就是加载模型需要序列化类CNN,而CNN的定义后面还有很多代码的话,CNN类的序列化就不会单独产生,这样就导致加载模型的时候找不到CNN的序列化,报错。
而显性定义为什么不可行,用Java中的原理就是,新的CNN与模型中的CNN虽然长的一样,但是序列号不一样(即身份证号不一样),因此不被识别
2、也有一种解决办法说,import Class将这个类CNN导入,但是!!!如果此时CNN类定义的文件中还有训练的代码的话,相当于会再次训练,这样就违背了我想保存模型的初衷。
3、也有推荐保存模型参数而不是整个模型的,说保存整个模型非常容易出错,但由于我训练的这个模型比较小,我暂时没有尝试。
但是在加载模型参数的时候,需要先实例化整个模型,这样还是要import Class,结果无差。
4、但是我参考的一个教程代码,其将CNN定义和模型训练写一块的,居然不报错!!!
可能还有更多需要注意的,欢迎指正
总结:写CNN模型的时候还是要养成一个好习惯,不要将训练代码和模型定义写一块!!!