江大白共学计划_Pytorch推理及范式_Lesson2 课程作业
必做题:
(1) 从torchvision中加载resnet18模型结构,并载入预训练好的模型权重 ‘resnet18-5c106cde.pth’ (在物料包的weights文件夹中)。
import torch
import torchvision.models as model
# 从torchvision加载res18模型结构
model = model.resnet18()
# 加载权重
pretrained_state = torch.load("resnet18-5c106cde.pth")
model.load_state_dict(pretrained_state, strict=True)
(2) 将(1)中加载好权重的resnet18模型,保存成onnx文件。
import torch
import torchvision.models as model
# 从torchvision加载res18模型结构
model = model.resnet18()
# 加载权重
pretrained_state = torch.load("resnet18-5c106cde.pth")
model.load_state_dict(pretrained_state, strict=True)
model.to(torch.device('cpu'))
model.eval()
# 构建模型推理时需要的输入大小的单精度Tensor,并且防止模型所在的设备
inputs = torch.ones([1, 3, 224, 224]).type(torch.float32).to(torch.device('cpu'))
# 生成onnx
torch.onnx.export(model, inputs, 'resnet18.onnx', verbose=True)
(3)、(4) 以torch.rand([1,3,224,224]).type(torch.float32)作为输入,求resnet18的模型计算量和参数量。
from thop import profile
flops, params = profile(model=model, inputs=(inputs,))
print('Model: {:.2f} GFLOPs and {:.2f}M parameters'.format(flops/1e9, params/1e6))
a.输入为13224224时,计算量和参数量分别为: 1.82 GFLOPs and 11.69M parameters
b.输入为13448448时,计算量和参数量分别为:7.27 GFLOPs and 11.69M parameters
思考题:
(1) 比较必做题中的(3)和(4)的结果,有什么规律?
答:输入数据的宽增加m倍,高增加n倍,计算量增加m*n倍,参数量不随输入数据变换而变化。
(2) 尝试用netron可视化resnet18的onnx文件
(3) model作为torch.nn.Module的子类,除了用 model.state_dict()查看网络层外,还可以用model.named_parameters()和model.parameters()。它们三儿有啥不同?
答:
model.parameters()和model.named_parameters()这两者唯一的差别在于,named_parameters()返回的list中,每个元祖打包了2个内容,分别是layer-name和layer-param,而parameters()只有后者。后面只谈model.named_parameters()和model.state_dict()间的差别。
它们的差异主要体现在3方面:
a.返回值类型不同
b.存储的模型参数的种类不同
c.返回的值的require_grad属性不同
首先说第一个,这很简单,model.state_dict()是将layer_name : layer_param的键值信息存储为dict形式,而model.named_parameters()则是打包成一个元祖然后再存到list当中;
第二,model.state_dict()存储的是该model中包含的所有layer中的所有参数;而model.named_parameters()则只保存可学习、可被更新的参数,model.buffer()中的参数不包含在model.named_parameters()中
最后,model.state_dict()所存储的模型参数tensor的require_grad属性都是False,而model.named_parameters()的require_grad属性都是True
(4) 加载模型权重时用的model.load_state_dict(字典, strict=True),里面的strict参数什么情况下要赋值False?
答:如果要求预训练权重层数的键值与新构建的模型中的权重层数名称完全吻合,赋值strict=True;如果新构建的模型在层数上进行了部分微调,赋值strict=False。
课程总结:
虽然本节课比较简单,但还有有一些收货:
a.在打印网络时发现BN层有4个参数,之前我还以为BN层只有缩放因子和偏移2个参数,原来来由2个参数mean和val实在前向传播时更新,而缩放因子γ和偏移β是在反向传播时更新。
b.熟悉了netron的使用。
c.熟悉了计算量和参数量的计算方法以及thop的使用。