[pytorch报错] 使用hidden layer绘图 报错Cannot insert a Tensor that requires grad as a constant.

现象

在修改网络结构之后,想用hidden layer库绘图观察一下网络结构是否修改正确
结果报错 RuntimeError: Cannot insert a Tensor that requires grad as a constant. Consider making it a parameter or input, or detaching the gradient

解决方案

  • 参考 https://blog.csdn.net/KyokoChen/article/details/105145724 的方案
  • torch官方手册的定义 https://pytorch.org/docs/stable/generated/torch.nn.ModuleList.html?highlight=modulelist#torch.nn.ModuleList

__init__ 中定义模块使用的list转换为ModuleList

经过

  • 首先是怀疑是不是自己hidden layer使用方法不对
    这里放一下自己的绘图的代码,其实代码是没有问题的
    from batchgenerators.utilities.file_and_folder_operations import join
    import hiddenlayer as hl
    
    g = hl.build_graph(model, torch.rand((1, 3, 48, 192, 192)), transforms=None)
    arch_folder = "/home/anaconda3/envs/py3.7_torch1.8.1/lib/python3.7/site-packages/nnunet/network_architecture"
    g.save(join(arch_folder, "Res_UNet_architecture.pdf"))
    
  • 怀疑是不是网络结构搭建的过程中有问题
    • 尝试print(model)y = model(x) 都没有报错
    • 观察到报错中有一行提到forword,于是去查自己写的forword代码
      File "/home/anaconda3/envs/py3.7_torch1.8.1/lib/python3.7/site- packages/nnunet/network_architecture/generic_UNet.py", line 294, in forward
      x = self.blocks[0](x)  
    File "/home/anaconda3/envs/py3.7_torch1.8.1/lib/python3.7/site-packages/torch/nn/modules/module.py", line 887, in _call_impl`
    

网络里的这个模块定义如下,代码过长,仅保留有关的部分

class StackedConvLayersWithRes(nn.Module):
    def __init__(self, input_feature_channels, output_feature_channels, num_convs,
                 conv_op=nn.Conv2d, conv_kwargs=None,
                 norm_op=nn.BatchNorm2d, norm_op_kwargs=None,
                 dropout_op=nn.Dropout2d, dropout_op_kwargs=None,
                 nonlin=nn.LeakyReLU, nonlin_kwargs=None, first_stride=None, basic_block=ConvDropoutNormNonlin):
  ''' 
  代码过长,仅保留有关的部分 此处省略很多定义....
  关键在下面三句
  '''
        self.blocks = []
        self.blocks.append( basic_block(input_feature_channels, output_feature_channels, self.conv_op,
                           self.conv_kwargs_first_conv,
                           self.norm_op, self.norm_op_kwargs, self.dropout_op, self.dropout_op_kwargs,
                           self.nonlin, self.nonlin_kwargs))
        for _ in range(num_convs - 1):
            self.blocks.append( basic_block(output_feature_channels, output_feature_channels, self.conv_op,
                           self.conv_kwargs,
                           self.norm_op, self.norm_op_kwargs, self.dropout_op, self.dropout_op_kwargs,
                           self.nonlin, self.nonlin_kwargs) )
    def forward(self, x):
        # 如果要加res的话 要改在这里
        x = self.blocks[0](x) # 第一个con会做下采样 channel数目不一致 
        skip = x
        # 取这里的feature map做Res
        for i in range(1,len(self.blocks)):
            x = self.blocks[i](x)
        
        return skip + x

问题出在这里,self.blocks使用的是list
只需要在l构建好之后,在后面加一句

	self.blocks = nn.ModuleList(self.blocks)

即可,使用的时候可以一样使用下标访问ModuleList中的内容,所以forword代码也不用改。
运行之后发现不会报错了!

hidden layer绘图效果参考:
在这里插入图片描述

你可能感兴趣的:(pytorch,深度学习,python)