ValueError: Expected more than 1 value per channel when training-Pytorch的BN神坑

  最近在利用Pytorch写GAN测试代码的过程中,因为测试生成器生成的图像一般会将测试的batch-size设为1,如果使用了Batch Normalization,这个神坑错误就是非常常见的了:

  File "C:\Users\hu\AppData\Local\conda\conda\envs\pytorch\lib\site-packages\torch\nn\functional.py", line 1693, in batch_norm
    raise ValueError('Expected more than 1 value per channel when training, got input size {}'.format(size))
ValueError: Expected more than 1 value per channel when training, got input size torch.Size([1, 512, 1, 1])


  很多博客把它归结为加载训练集中剩下一个训练样例的情况,这并没有体现到它的本质。正好pycharm给出了最后错误的文件,让我们从源码的角度去分析一下:
  打开C:\Users\hu\AppData\Local\conda\conda\envs\pytorch\lib\site-packages\torch\nn\functional.py文件,可以看到如下一段代码:
ValueError: Expected more than 1 value per channel when training-Pytorch的BN神坑_第1张图片
  光标所指的代码行数(即倒数第二行和第三行)就是报错的根本原因所在了,当Batch Normalization的training参数被设置为True时(比如经过model.train()),如果输入的四维张量[N,C,H,W]的N为1,就会报错,即当Batch Normalization设为训练模式时(通过训练样本学习均值和方差),拒绝任何batch-size为1的情况。至于原因,简单地说就是BN归一化是依靠当前mini-batch的均值和方差进行归一化的,如果batch-size太小,显然所谓的均值和方差并不能代表不同sample之间的差距,各个mini-batch归一化结果的差异会非常大,归一化就没有意义了。另外,当batch-size设为1时,BN的结果近似于IN(引自何凯明等人“Group Normalization”论文)。

  回到正题上,如何解决这个错误呢?我在这里推荐以下两种方式:

  1. 既然知道BN在训练模式(training=True)时拒绝batch-size为1的情况,那么在训练的时候避免设置batch-size为1。在测试的时候把BN设置成测试模式(training=False)就好了,比如通过model.eval()方式
  2. 如果避无可避,期望在测试阶段,仍然需要BN保持训练模式(即所谓的用测试数据的方差和均值来归一化测试数据,而不是通过训练样本得到的方差和均值进行归一化测试数据)这种非正常的情况(对,说的就是Pixel-to-Pixel GAN这个逆天的东西),并且还需要batch-size为1时,那么就只能修改源码了:
    nn.functional文件中,把刚刚的那两行判断batch-size为1就报错的代码注释掉
    ,如下图所示:
    ValueError: Expected more than 1 value per channel when training-Pytorch的BN神坑_第2张图片
    这样就大功告成啦! 并且从理论上来说,只要你心里清楚原因,这是不会有什么特别负面的影响的。

你可能感兴趣的:(PyTorch)