问题描述
我正在用图像实现语义分割模型。作为一种好习惯,我只用一张图像测试了我的训练流水线,并尝试过分拟合该图像。令我惊讶的是,当使用完全相同的图像进行训练时,损失接近预期的零,但是当评估“相同图像”时,损失要高得多,并且随着训练的进行而不断增加。因此,在training=False
时,分段输出是垃圾,但是在与training=True
一起运行时,分段输出是完美的。
为了使任何人都可以复制此文件,我接受了官方segmentation tutorial的修改,并对其进行了一些修改,以便从头开始训练卷积网络,只需一张图像。该模型非常简单,只是一个具有批处理规范化和Relu的Conv2D序列。结果如下
如您所见,损失和eval_loss确实不同,并且在训练模式下对图像进行推断可以得出完美的结果,而在eval模式下则是垃圾。
我知道Batchnormalization在推理时间上的表现有所不同,因为它使用了训练时计算的平均统计量。但是,由于我们仅使用1张相同的图像进行训练并在同一张图像中进行评估,所以这不应该对吗?此外,我在Pytorch中使用相同的优化器实现了相同的体系结构,而这并没有发生。使用pytorch进行训练,eval_loss收敛以训练损失
在这里您可以找到上面提到的https://colab.research.google.com/drive/18LipgAmKVDA86n3ljFW8X0JThVEeFf0a#scrollTo=TWDATghoRczu 最后还有Pytorch的实现
解决方法
它必须对 tensorflow 使用的默认值做更多的事情。 Batchnormalization 有一个参数 momentum
,它控制批处理统计的平均。公式为:moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)
如果您在 BatchNorm 层中设置 momentum=0.0
,平均统计数据应该与当前批次的统计数据(只有 1 个图像)完美匹配。如果这样做,您会看到验证损失几乎立即与训练损失匹配。此外,如果您尝试使用 momentum=0.9
(这是 pytorch 中的等效默认值)并且它可以更快地工作和收敛(如在 pytorch 中)。