一、作业题目
必做题:
(1) 从torchvision中加载resnet18模型结构,并载入预训练好的模型权重 'resnet18-5c106cde.pth' (在物料包的weights文件夹中)。
(2) 将(1)中加载好权重的resnet18模型,保存成onnx文件。
(3) 以torch.rand([1,3,224,224]).type(torch.float32)作为输入,求resnet18的模型计算量和参数量。
(4) 以torch.rand([1,3,448,448]).type(torch.float32)作为输入,求resnet18的模型计算量和参数量。
思考题:
(1) 比较必做题中的(3)和(4)的结果,有什么规律?
(2) 尝试用netron可视化resnet18的onnx文件
(3) model作为torch.nn.Module的子类,除了用 model.state_dict()查看网络层外,还可以用model.named_parameters()和model.parameters()。它们三儿有啥不同?
(4) 加载模型权重时用的model.load_state_dict(字典, strict=True),里面的strict参数什么情况下要赋值False?
二、实现情况
1、总体实现源码
import torch
import torchvision.models as models
from thop import profile
path='./weights/resnet18-5c106cde.pth'
resnet18=models.resnet18()
trained_state_dict=torch.load(path)
resnet18.load_state_dict(trained_state_dict,strict=True)
# comparing state_dict() named_parameters() parameters()
model_state_dict=resnet18.state_dict()
''' #testing code for class
for key,value in model_state_dict.items():
print('Param name:', key)
print('Param shape:', value.shape)
print('-'*10)
layer0=model_state_dict['conv1.weight']
print(layer0)
'''
model_name_para=resnet18.named_parameters()
model_para=resnet18.parameters()
print("\n\tstate_dict\t\n")
print(model_state_dict)
print("\n\tnamed_parameters\t\n")
print(model_name_para)
for param in model_name_para:
print(param)
print("\n\tparameters\t\n")
print(model_para)
for param in model_para:
print(param)
# [448,448] size inputs GFLOPs
inputs=torch.ones([1,3,448,448]).type(torch.float32)
flops, params = profile(model=resnet18, inputs=(inputs,))
print('Model: {:.2f} GFLOPs and {:.2f}M parameters'.format(flops/1e9, params/1e6))
# [224,224] size inputs GFLOPs
inputs=torch.ones([1,3,224,224]).type(torch.float32)
flops, params = profile(model=resnet18, inputs=(inputs,))
print('Model: {:.2f} GFLOPs and {:.2f}M parameters'.format(flops/1e9, params/1e6))
#using cpu running | input as [224,224] | save onnx model
device=torch.device('cpu')
resnet18.to(device)
resnet18.eval()
inputs=inputs.to(device)
torch.onnx.export(resnet18,inputs,path.replace('pth','onnx'),verbose=False)
2、问题结果
必做题:
(2)onnx模型大小为46.8M
(3)1.82 GFLOPs and 11.69M parameters
(4)7.27 GFLOPs and 11.69M parameters
上半部分为448测试,下半部分为224测试
思考题:
(1)我认为,输入按比例则大,则进行的卷积次数同样按输入维数增长之积增大(在不严格的情况下,因为根据stride和kernel大小不同以及输入大小不同可能并不会严格按照比例增大),因此浮点计算次数也按输入维数增长之积增大,即如下:
(2)测试平台:mac版 Netron5.3.0 结果如下:
(3)根据目前代码中测试的部分,首先三者最大的不同为返回值的不同。
named_parameters()和parameters()方法返回的是一个generator,也就是说是可以进行遍历的类别,遍历出来的值才是真正的参数,而state_dict()直接返回各层的名字、参数等信息。
named_parameters()保留了参数名称,即'*.weight',而parameters()仅包含参数。
(4)该问题在本篇实验中没有可以进行测试的相关模型,使用的模型使用Ture or False结果一致,因此该问题我进行了查找。相关资料显示:
如果model中多了一些模型文件中不存在的参数,但是我们希望model将模型文件中的参数加载加载进来,就可以使用strict=False消除相关的限制,将模型文件中有的参数全部读入。
参考文献:
1、model.load_state_dict(state_dict, strict=False)_t20134297的博客-CSDN博客