PyTorch 常见问题整理

最近刚刚开始从 Keras 换成 PyTorch,在使用过程中可能会遇到一些常见的问题,做一些整理。

1 Loss 为 NaN

可以在 python 文件头部使用如下函数打开 nan 检查:

如果遇到了 nan 的 Tensor,它会抛出异常。幸运的话它会告诉你 nan 产生的位置。比如说我遇到过:

有些时候,往往会遇到比如 Adam 就没有 nan 而 SGD 就会出现 nan,这种通常都是 Loss 设得太大,可以调低学习率试试。
其他可能产生 nan 的地方可以尝试定位下:
1、脏数据,输入有 NaN
2、设置 clip gradient
3、更换初始化参数方法

2 正确测试模型运行时间

如果是为了测试模型的前向运算运行时间,需要设置 model 为评估模式:

同时在 GPU 上测速时需要使用 torch.cuda.synchronize() 同步 CUDA 操作:

3 参数初始化

在一些任务中,如果不是使用已有训练参数而是从 0 开始训练一个空白的网络,进行参数的初始化(例如 Conv2D)会有利于加快模型的收敛,例如下面参数初始化方式是(通常可以放在 model 的 init 函数结尾):

4 获取 torchvision 中某一层的输出

工程实践中经常用 torchvision 预训练参数然后提取其中部分层进行修改。这里面可以有两种方式:
第一种,直接 copy 全部的代码,然后根据自身需要输出中间层:
例如对于 shufflenetv2 代码可以这样修改返回你需要的层(_forward_impl 是原始的,_forward_impl_with_layers 是修改的):

另外一种方法不下载代码直接调用 torchvision 中的层,这个可能需要分析每个代码的实现才能知道想要的层,比如这样打印:

打印结果类似:

比如获得 conv1 层输出就是

5 修正 The NVIDIA driver on your system is too old 错误

有时在你安装某一个版本的 PyTorch (比如 1.5.0) 时会出现如下错误提示:

在安装 PyTorch 的时候往往会指定相应的 CUDA 版本,这个错误的意思可能是你没有安装特定版本的 CUDA 或者你的 CUDA 版本与你的 GPU Driver 版本不匹配。
在 Nvidia 官网中给了我们如下的版本匹配:https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html

如果需要升级,你可以使用如下方式升级:
1)增加软件源:

2)查看可以使用的版本:

例如我这里查询结果是:

3)升级指定版本(根据上面表格找到合适的版本升级):

如果出现某些冲突问题可以尝试先卸载再安装:

PS:另外一种方式你也可以先不升级指定版本,先使用如下命令查看本地版本:

比如我这里显示的就是:

那么我就应该安装支持 CUDA 10.0 的版本。可能 PyTorch 1.5 就不可用了,但是 PyTorch 1.4 还是可以的,可以使用如下命令安装:

具体什么版本支持可以参考:
https://download.pytorch.org/whl/torch_stable.html
这个页面。

6 修正 Expected more than 1 value per channel when training 错误

如果在训练时遇到如下错误:

一个可能的原因是出现了输入 batch_size = 1 的情况,这时可以考虑在 DataLoader 属性加上 drop_last=True 解决,它会抛弃掉不够一个 batch size 的情况。例如:

如果实在无法避免或者就需要 batch_size = 1 的训练方式,还可以考虑把网络中的 BatchNorm 换成 InstanceNorm。

7 修正 Can't call numpy() on Variable that requires grad. Use var.detach().numpy() instead 错误

如果获取变量值时,遇到下面错误:

这里面通常有两种情况:
一种是这个变量是含有训练参数的,需要反向传播,则使用 var.detach().numpy() 获取。
另一种如果这个变量是不进行训练的不需要反向传播,则将相关的代码用如下方式(with torch.no_grad())修饰即可:

8 修正 RuntimeError: error executing torch_shm_manager 错误

如果在运行多线程训练时出现类似如下错误:

可能的解决方法是注释掉如下设置(如果有的话):

9 修正 RuntimeError: Cowardly refusing to serialize non-leaf tensor which requires_grad 错误

如果在运行多线程训练时出现类似如下错误:

我们看下相关报错的函数是这样的:

经过分析我这里的发生的原因是在多线程 DataLoader 中使用了一个模型生成数据,然而这个模型的参数有一部分却是 requires_grad = True 属性的。
可以采用如下方式处理模型让生成的 Tensor 都为 no_grad:

10 修正多线程 DataLoade rnumpy random 不变错误

由于 numpy 中的 random 不是 thread safe 的,因此在多线程中,其不同线程的 random 无法生成不同的随机数,需要每个线程重新设置 random.seed 才可以。因此对于 DataLoader 在 num_workers > 0 时就可能产生问题(比如需要每次生成不同的随机数据)。对于此问题有几种修改方式:

第一种
利用 worker_init_fn 每个线程重新设置种子,示例代码如下:

第二种
在文件开头加上下面两行设置:

参考文献

[1] https://blog.csdn.net/weixin_41278720/article/details/80778640
[2] https://discuss.pytorch.org/t/getting-nan-after-first-iteration-with-custom-loss/25929/14
[3] https://zllrunning.github.io/2018/03/24/20180324/
[4] https://github.com/MVIG-SJTU/AlphaPose/issues/402
[5] https://github.com/pytorch/pytorch/issues/5059

Add a Comment

Your email address will not be published.