PyTorc添加网络图结构add_graph报错:RuntimeError: Cannot insert a Tensor that requires grad as a constant. Consider making it a parameter or input, or detaching the gradient

错误说明

在使用PyTorch自带的TensorBoard的add_graph方法将网络图结构添加到监测信息中时,遇到如下报错:

1
RuntimeError: Cannot insert a Tensor that requires grad as a constant. Consider making it a parameter or input, or detaching the gradient.

这个信息其实有些tricky:

  • 告诉了是add_graph这一步有问题,但是具体哪个变量是带有不符合要求的属性不得而知
  • 格式是按照api照猫画虎的,怎么会不符合要求呢?

Debug过程

  1. 搜遍全网也没有找到结果,根据一些相关信息(见参考)的蛛丝马迹,首先怀疑是传入模型的Tensor的requires_grad设置问题,debug后发现其值为False(也应该是False,因为是从原始文件读入的数据)。

  2. 接下来,怀疑是模型output的Tensor的requires_grad的问题,但是没想到如何简便地更改add_graph中的模型输出Tensor的属性,因为这一步是在add_graph源码中的,当然也可以更改源码中的model(input_to_model)这里,使其所有输出的属性符合要求,但是这有点不elegant。

  3. 接下来从参考链接2中获得了一些启发,想到我使用的是多GPU训练,会不会是Dataparallel的问题呢?接下来又想到之前在知乎(链接3)看到关于读写Dataparallel的一些技巧,马上“灵光一闪”。先尝试了将add_graph放到模型并行化之前,果然没有报错,基本确定是Dataparallel的问题。

  4. 然后根据参考链接2和3,想到把模型先从并行化容器中取出来,再执行,果然问题完美解决。相关代码如下

    1
    2
    3
    4
    5
    6
     # setup the summary writer
    train_data_sample, label_sample = iter(dataloader_train).next()
    writer = SummaryWriter(args.summary_path, flush_secs=120)

    with writer:
    writer.add_graph(model.module,train_data_sample.to(device)) # model graph, with input

    重点就在model.module,这句话讲模型从并行化后的容器中取出来,以未并行化的模型(原始模型)返回,这样再执行就没有问题了。

参考

  1. https://github.com/pytorch/pytorch/issues/20101
  2. https://discuss.pytorch.org/t/how-to-reach-model-attributes-wrapped-by-nn-dataparallel/1373/4
  3. https://www.zhihu.com/question/67726969