概述
前言
最近在做模型的量化与量化后模型在arm平台上的迁移工作,为了保证量化后的模型在python下与在arm下运行的一致性(相同输入下,不同环境下的输出完全一致),需要对python下模型前向传播的每个操作的激活值、权重、输入的量化参数(scale与zero_point)、权重的量化参数(scale与zero_point)都能查看,在这个查看的过程中,发现VSCODE帮了大忙,因此记录一下VSCODE调试控制台的使用,便于自己与他人后续参考使用。
查看加载模型的参数
我在保存模型时,仅保存了模型的参数信息,而非整个模型的结构信息:
torch.save(model_object.state_dict(), 'params.pth')
加载模型的参数信息,则需:
state_dict = model_object.load_state_dict(torch.load('params.pth'))
state_dict为OrderedDict类型,加载后,在左侧的变量栏可以看到state_dict包含的一些key, value
对于模型比较大的,在左侧栏可能看不全state_dict包含的所有key,value,可以通过遍历查看state_dict中的key值
for k,v in stat_dict.items():
# if `v` is `torch.Tensor`, then save it into dict:
print(k)
查看或修改state_dict中的值
这里以查看并修改模型中某一层的激活scale值、权重scale值为例
查看并修改激活scale的值
在调试控制台,可以通过state_dict的key值对其进行查看,并修改其中的值
查看修改权重scale的值
通过stat_dict['stage3.1.branch2.0.weight']
可以查看到stage3.1.branch2.0的权重是一个Tensor,这里是量化后的模型,可以看到tensor中还有scale, zero_point等属性,但是直接使用stat_dict['stage3.1.branch2.0.weight'].scale
是无法查看到scale的值的,也就无法通过这种方式对其进行修改。查看与修改应使用stat_dict['stage3.1.branch2.0.weight'].q_per_channel_scales()
,如下图:
对模型的前向传播进行跟踪
现在的网络大都不是简单的只有conv,fc这样的平直的结构,二是有一些其他的基本单元,如,Resnet的残差块,MobileNet中的瓶颈层等等。这种基本单元的构成会使得调试的时候,深入查看某个基本单元的某一层的值有点麻烦。以shufflenetv2的基本单元InvertedResidual为例。branch1为空,或depthwise conv + pointwise conv,branch2为pointwise conv + depthwise conv + pointwise conv。
class InvertedResidual(nn.Module):
def __init__(self, inp, oup, stride):
super(InvertedResidual, self).__init__()
if not (1 <= stride <= 3):
raise ValueError('illegal stride value')
self.stride = stride
branch_features = oup // 2
assert (self.stride != 1) or (inp == branch_features << 1)
if self.stride > 1:
self.branch1 = nn.Sequential(
self.depthwise_conv(inp, inp, kernel_size=3, stride=self.stride, padding=1),
nn.BatchNorm2d(inp),
nn.Conv2d(inp, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
)
else:
self.branch1 = nn.Sequential()
self.branch2 = nn.Sequential(
nn.Conv2d(inp if (self.stride > 1) else branch_features,
branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
self.depthwise_conv(branch_features, branch_features, kernel_size=3, stride=self.stride, padding=1),
nn.BatchNorm2d(branch_features),
nn.Conv2d(branch_features, branch_features, kernel_size=1, stride=1, padding=0, bias=False),
nn.BatchNorm2d(branch_features),
nn.ReLU(inplace=True),
)
@staticmethod
def depthwise_conv(i, o, kernel_size, stride=1, padding=0, bias=False):
return nn.Conv2d(i, o, kernel_size, stride, padding, bias=bias, groups=i)
def forward(self, x):
if self.stride == 1:
x1, x2 = x.chunk(2, dim=1)
out = torch.cat((x1, self.branch2(x2)), dim=1)
else:
out = torch.cat((self.branch1(x), self.branch2(x)), dim=1)
# 可在此处加断点
out = channel_shuffle(out, 2)
return out
查看基本单元中某一层权重的值
调试时,在前向传播里添加断点,在InvertedResidual中branch1,branch2是作为一个整体前向传播的,如果想要具体查看内部某一层的执行情况,可以在调试控制台中实现。
上图是branch1和branch2的结构,这里量化的时候CONV与BN进行了融合,因此CONV变成了QuantizedConv2d,BN变为了Identity()。如果想要查看branch1.0.weight则可以在调试控制台中使用self.branch1[0].state_dict()['weight']
进行查看
使用self.branch1[0].state_dict()['weight'].int_repr()
可以查看该层量化后的权重值
查看基本单元中某一层前向传播的值
以branch2.4的输出为例,可以通过以下代码得到brach2.4的输出
进一步,可以通过以下代码查看该层量化后的值
最后
以上就是喜悦雨为你收集整理的VSCODE调试控制台的使用——以pytorch下神经网络的加载模型前向传播为例前言查看加载模型的参数对模型的前向传播进行跟踪的全部内容,希望文章能够帮你解决VSCODE调试控制台的使用——以pytorch下神经网络的加载模型前向传播为例前言查看加载模型的参数对模型的前向传播进行跟踪所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复