我正在使用图像实现一个语义分割模型。作为一个很好的实践,我只用一张图像测试了我的训练管道,并试图过拟合该图像。令我惊讶的是,当使用完全相同的图像进行训练时,损失接近0,但当评估相同的图像时,损失要高得多,所以当training=False
运行时,分割输出是垃圾,但是当运行training=True
时,它可以完美地工作。
为了能够让任何人重现这一点,我采取了官方的segmentation tutorial,并对其进行了一些修改,以便从头开始训练一个convnet,只有1张图像。模型非常简单,只是一个Conv2D序列,带有批量归一化和Relu。结果如下
正如你所看到的,loss和eval_loss是完全不同的,对图像进行推断在训练模式下会得到完美的结果,而在eval模式下则是垃圾。
我知道Batchnormalization在推理时间上的行为不同,因为它使用在训练时计算的平均统计数据。然而,由于我们只使用1个相同的图像进行训练并在同一图像中进行评估,这不应该发生,对吗?此外,我在Pytorch中使用相同的优化器实现了相同的架构,并且在那里没有发生这种情况。使用Pytorch,它训练并且eval_loss收敛到训练损失
在这里你可以找到上面提到的https://colab.research.google.com/drive/18LipgAmKVDA86n3ljFW8X0JThVEeFf0a#scrollTo=TWDATghoRczu,最后还有Pytorch实现
2条答案
按热度按时间cxfofazt1#
它必须对tensorflow使用的默认值做更多的处理。Batchnormalization有一个参数
momentum
,它控制批量统计的平均值。公式为:moving_mean = moving_mean * momentum + mean(batch) * (1 - momentum)
如果你在BatchNorm层中设置
momentum=0.0
,平均统计数据应该与当前批次的统计数据(只有1张图像)完全匹配。如果你这样做,你会看到验证损失几乎立即与训练损失相匹配。如果你尝试使用momentum=0.9
(这是pytorch中的等效默认值),它会工作并收敛得更快(如pytorch中)。tjvv9vkg2#
这是旧的,但我有同样的经历。我犯了一个错字,得到了一个模型,它可以在一个数据集上过度拟合,而这个数据集不可能适合它的内存。在训练模式下,一致的接近100%的猜测,在相同数据的评估中胡言乱语。我深入研究了一下,只是出于好奇,发现模型学会了“故意”轻微地改变输出,牺牲了一小部分损失,但是这样做会产生一个梯度,作为一个额外的内存。它是如此的拼命过度拟合,显然,它走到外面去了。我不知道该怎么办,它看起来更像是一个功能,而不是一个错误。