我的 CNN 分类器对随机图像给出了错误的预测

Posted

技术标签:

【中文标题】我的 CNN 分类器对随机图像给出了错误的预测【英文标题】:My CNN classifier gives wrong prediction on random images 【发布时间】:2019-03-20 17:25:02 【问题描述】:

我用 3 个数据类别(身份证、护照、账单)训练了我的 CNN 分类器(使用 tensorflow)。 当我用属于 3 个类别之一的图像对其进行测试时,它给出了正确的预测。但是,当我用错误的图像(例如汽车图像)对其进行测试时,它一直在给我预测(即它预测汽车属于身份证类别)。

有没有办法让它显示错误消息而不是给出错误的预测?

【问题讨论】:

不是真的,这更像是一个研究问题而不是编程问题。 更准确地说,您可以使用 arxiv.org/abs/1802.04865 之类的技术来检测 Out of Distribution 示例,但正如我所说,它比编程问题更复杂。 我对预测的了解是,给定一张要预测的图像,分类器将看到哪个是最接近该图像的类别。换句话说,分类器假设给定的图像必须属于它训练过的类别之一,所以它只会给出一个概率。我说的对吗? 是的,分类器不知道任何其他类别,也不必预测最相似的类别,它几乎是随机的。对于概率,您通常无法检测到这一点,因为它们没有为此目的进行校准。 谢谢@MatiasValdenegro,请发布一个总结您的cmets的答案,以便其他有同样问题的人在将来找到它。 【参考方案1】:

最简单的方法是简单地为除其他三个类别之外的任何类别添加第四个类别,并使用各种完全随机的照片对其进行训练。

【讨论】:

我想过,但它没有效果,因为它就像第四类将包含 ANY OTHER THING 除了身份证、账单和护照。 它当然应该更容易忽略结果,就好像第四个输出 >0.5 并且其他输出几乎相等或者没有一个特别突出,那么你可以认为以上都不是. 是的,对,如果你从数学方面(概率)来看,如果你用随机图像测试模型,最高概率可能是第四类,因为它包含随机图像.这是最简单的开始方法。 是的,但正如你所做的那样,我绝对建议参考你标记的答案,这样会更好哈哈【参考方案2】:

这应该以不同的方式解决。这被称为开放集识别问题。你可以谷歌它并找到更多关于它的信息,但基本上是这样的: 你不能在每个可以想象的类上训练你的分类器。它总是会遇到一些它不熟悉并且以前从未见过的其他类。

有几个解决方案,我将从中挑选出其中的 3 个:

    单独的二元分类器 - 您可以构建单独的二元分类器来识别图像并将它们分类为两个类别,具体取决于票据、护照或身份证是否在图像中。如果是,它应该让您已经构建的算法来处理图像并将其分类为 3 个类别之一。如果第一个分类器说图像中有其他对象,您可以立即丢弃该图像,因为它不是票据/护照/身份证的图像。

    阈值。在身份证在图像上的情况下,身份证的概率很高,而票据和护照的概率相当低。在图像是其他东西(例如汽车)的情况下,所有 3 个类别的概率很可能大致相同。换句话说,这两个类别的概率都没有真正突出。在这种情况下,您选择生成的概率最高并将输出类设置为该概率的类,而不管概率的值是 0.4 还是类似的值。为了解决这个问题,您可以设置一个阈值,比如说 0.7,如果两个概率都没有超过这个阈值,那么图片上还有其他东西(不是身份证、护照或账单)。

    创建第四个类:Unknown。如果您选择此选项,您应该将一些其他图像添加到数据集中并标记它们未知。然后训练分类器,看看结果如何。

我会推荐 1 或 2 个。希望它有所帮助:)

【讨论】:

感谢您的详细解答。第一种方法对我来说听起来不错。恐怕第二种方法不适合我的问题,因为即使使用错误的图像,概率也很高(有时超过 90%) 至于第三种方法,正如您所说“您无法在可以想象的每个类上训练您的分类器。它总是会遇到一些它不熟悉并且以前从未见过的其他类。”所以我猜它不是很有效。我会尝试第一种方法。再次感谢您的详细解释。 为什么不推荐最后一个选项?是不是效果更差?选项 #1 和 #3 之间有什么根本区别吗?【参考方案3】:

这不是一个真正的编程问题,它的方式更复杂。你想要的是所谓的分布外检测,分类器有办法告诉你样本不在训练集上。

最近有研究论文处理这个问题,比如https://arxiv.org/abs/1802.04865和https://arxiv.org/abs/1711.09325

一般来说,您不能使用未经专门训练的模型,例如,softmax 分类器产生的概率没有为此目的进行校准,因此对这些概率进行阈值化根本不起作用。

【讨论】:

【参考方案4】:

我正在寻找相同的解决方案,它把我带到了这里。为了解决这个问题,我使用了math.isclose() 函数来比较我的预测值。

def check_distribution(self, prediction):
    checker = [x for x in prediction[0] if math.isclose(1, x, abs_tol=1e-9) ]
    for probability in prediction[0]:
        if len(checker) > 0:
            return True
        else:
            return False

随意更改 abs_tol 参数,具体取决于您想要的野蛮程度。

【讨论】:

以上是关于我的 CNN 分类器对随机图像给出了错误的预测的主要内容,如果未能解决你的问题,请参考以下文章

在 keras 中使用 CNN 对图像进行二值分类时正确预测的总数

MATLAB:使用 fitctree 训练的分类器对新数据进行标签预测

如何获得分类器对sklearn中预测的置信度分数?

CNN培训多标签分类---不起作用

渐进式随机森林?

使用 CNN 进行癌症预测的分类