解决raise ValueError(“Expected more than 1 value per channel when training, got报错(亲测有效)

本文解析了Pytorch中使用BatchNormalization时遇到的常见错误,详细介绍了错误产生的根本原因,并提供了两种有效的解决方案。

最近在利用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文件,可以看到如下一段代码:
在这里插入图片描述

光标所指的代码行数(即倒数第二行和第三行)就是报错的根本原因所在了,当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就报错的代码注释掉,如下图所示:
在这里插入图片描述
这样就大功告成啦! 并且从理论上来说,只要你心里清楚原因,这是不会有什么特别负面的影响的。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值