CNN入门讲解:准确率很高就感觉自己萌萌哒?NONONO,置信度也很重要

首发在知乎专栏:

https://zhuanlan.zhihu.com/c_141391545

个人知乎:蒋竺波

想要代码的小伙伴请去公众号:follow_bobo ,下载 回复“修正”,即可获得下载地址。

或者在评论下面留下邮箱,我单独发给你

麻烦大家给我点个赞,就是那种让我看起来,写的还不错的样子!

拜托了!!o(´^`)o

很久没更新了,很多小伙伴还以为我弃坑了

如果你们再不点赞的话,我可就真的弃坑啦

1. 1 你说的准确率,不是真正的准确率

很多时候,我们在准备一个CNN模型时,优先考虑是提高准确率(Accuracy)

我们会花费大量的时间去研究如何提高模型的准确率

毕竟抛开准确率,谈其他的东西都耍流氓

可是如果准确率不能保证永远100%

那么准确率的可靠性(Reliability)就值得商榷了

比如我们经常会看到如下标题:

是不是感觉很吊很厉害

抱着崇拜的心情,我试了试搜狗的语音输入,下面是结果:

一个人的牺牲是不信很多人的牺牲就是统计数字啊,其实并没有什么太大的意义他们的语音识别,我用我说实话有些还不错,然后这段话就是我用语音识别打的。问题是这段话你发现一定有很多错误啦。刚好我要花很多时间就跟那些错误真麻烦。

由上你应该也发现了,统计意义上的数字和我们实际生活中所用到的结果还是有一定差距的

1.1.1 准确率怎么算出来的

A,B 两类的特征分布

上图是A,B 两类的特征分布,假设A紫色点,B是灰色点

这时候一个测试数据的特征分布有一点点靠近A

或者说

这个测试数据集的特征分布有60% 的可能性像A类特征分布

40%可能性像B类特征分布

模型便预测它为A,如果实际标签(Ground Truth)是A, 我们就认为预测正确

依靠这种方法,假如100个数据测试集,准确率94%,说明我们预测(cai)对了94个

94%?????

94%的正确率,终究只是一个统计数字,换个数据测试集,还能有94%的准确率吗,不一定吧

其实对于一个测试数据,模型预测就是只有一种既定设置的可能

就好比

薛定谔的猫,它只有dead or live ,不会存在 dead and live

也就是说,统计数字对个体参考意义不大

那我们怎么办?

2. 我说的置信度,又是什么置信度

这里,就要引入一个概念:

置信度(Confidence)

让们回到上面那个例子,假如测试数据集的特征分布有60% 的可能性像A类特征分布

我们就假设他的置信度是0.6(不同的算法会得到不同置信度)

在分析数据或做出决定时,通常需要说明模型是否可以确定其输出,或者模型能够问“可能我需要使用更多不同的数据?或改变模型?或者在做出决定时小心一点?“

置信度越高,说明模型对输出的结果越肯定

这是啥子意思?

假设我设置一个置信度阈值(Threshold),比如0.9, 也就是说

置信度 > 0.9, 我才会 接受这个模型的判断

置信度

我举个例子:

左一:正确预测的置信度分布;右一:错误预测的信心值分布

从上图咋一看,emmm..., 只要置信度>0.9,那么我的预测结果竟然全对诶

就问你6不6

再举个例子:

A(红),B(蓝)数据集特征分布

你们看到那个黑框框里的红duoduo吗

一个A(红)落在了B(蓝色)的数据分布附近,系统预测结果肯定是B,并且我们知道这是错的

但是仔细看图,黑框框里的红duoduo 也没有很靠近B的分布,也没有离A分布很远

假设我们模型给出的黑框框里的红duoduo的置信度是:0.7 的可能是B, 0.3 的可能是A

而这个时候,我们是Threshold 设置为0.9,

系统会把这个数据交给人来做判

虽然没有结果,至少我们避免了错误结果

那么问题来了:

我们怎么样去获得一个模型的预测的置信度(Confidence)?

说的这,我相信大家第一想法就是

CNN网络的最后一层softmax的输出值作为置信度

如果你这么想就太naive了

为什么这么说?

3. 1 你不是真正的置信度

首先结论是:CNN网络的最后一层softmax的输出值本身的置信度不高

说到这你肯定会疑惑:

明明现在你在讲置信度然后举了一个置信度的例子告诉我们Softmax输出的置信度的置信度不高

我先把softmax 公式摆上来:

Softmax

从CNN最后一层全连接层到softmax输出 ,T表示T个类

( 不太会Softmax的朋友麻烦出门左转补一补相关知识)

3.1.1 我们先来看看一个实际例子中预测结果的置信度分布

左图是正确预测结果的置信度,右边是错误预测结果的置信度

基于上面的原则,我们会发现预测结果置信度都集中在1.0 附近

看来模型一直对自己的预测结果很有信心

原因是因为:

3.1.1.1 在softmax中取对数e, 从对数曲线e我们可以看出,输入越大,输出越大, 也就意味着对的更对,错的更错

对数e曲线

3.1.1.2 还有一个原因是模型的输出置信度是相对的,而不是绝对的

比如目标类是[ cat, dog, horse], 输入数据是一个cat, 那么softmax输出就可能会是[0.95,0.04,0.01],表示的意义是,在我目前这个输入图片里,真要模型去猜,模型觉得它更有可能是cat。 这个结果只是针对目前的这一个测试数据。也就是说,没有一个真正的,绝对的坐标系或者参考值,来判断这个模型输出的结果的置信度‘到底’是多少,这样针对模型设置一个统一的置信度阈值是很难make sense

4.1 又回到最初的CNN

接下来的分析主要基于以下的资料:

1.《Intriguing properties of neural networks》--https://arxiv.org/pdf/1312.6199.pdf

2. 《Uncertainty in Deep Learning》--http://mlg.eng.cam.ac.uk/yarin/thesis/thesis.pdf

由于以上资料论证太过冗长和复杂,我就直接上结论吧,反正也不是我想出来的

4.1.1 不可察觉的真实图像扰动可以将深度网络的softmax输出改变为任意值

举个例子:

左一实际图,中间是扰动,右图是左一加中间的合成图

左边的图在模型上预测正确,可是左图加上中间的扰动等于右边图,但右边的预测结果却完全错误

这就很奇怪了,不应该啊

也就是说CNN在和人类对数据的理解会很不一样,它可能存在某些反直觉的情况或者‘盲区’,也间接说明CNN可能有某些人类难以觉察的不确定性,这种不确定将会直接影响输出结果和置信度,

4.1.2 测试数据千奇百怪

我们知道,实际测试数据可能是千奇百怪

在输入域中,某些类的特征分布空间可能远大于该类中的训练样例占据的特征样本空间,这意味着远离训练数据特征空间的数据永远不会得到很高的信心,因为模型“不能”确定它(因为它从未见过它)

当然还有很多其他的原因啦,但是不适合我们入门的教学,这里就不赘述啦

其实我自己也不是很清楚

5.1 对模型做调整(Calibration)

想要代码的小伙伴请去公众号:follow_bobo ,下载 回复“修正”,即可获得下载地址。

或者在评论下面留下邮箱,我单独发给你

以下参考论文:

1.《On Calibration of Modern Neural Networks》https://arxiv.org/pdf/1706.04599.pdf

通过以上,我们知道模型的softmax输出值存在不可靠得情况,但实际上还是会有一定的可靠性的

那么我们能不能找到这个模型的不可靠程度,然后对它的不可靠性进行修正,使模型置信度能够代表真实的概率估计(True Correctness Likelihood)

也就是对模型输出置信度进行修正(Calibration)

举个例子:

上图中是两个不同网络的输出

X轴表示置信度(Confidence)区间, Y轴表示在某个预测置信度区间的数量占总测试集的百分比

这篇论文的idea是对于一定数量的测试集,模型越可靠,平均置信度(Average Confidence)越接近准确率(Accuracy)

从上图中可以发现,虽然Lenet 准确率比Resent低,但Lenet 模型输出置信度更能够代表真实的概率估计

那么我们要怎么做调整(Calibration)呢?

两个方法(只说方法名,就不一一介绍了):

(1)内部:模型输出置信度不能够代表真实的概率估计,说到底还是模型本身问题,可以调整网络结构,比如增加Batch Normalization, 修改网络的层数等等,因为要通过做大量的试验来验证,这里不再赘述,有兴趣的可以自己去看论文

(2)外部: 直接对softmax的输出做调整

可以使用的方法有:

Calibrating Binary Models:Isotonic regression, Histogram binning,Bayesian Binning into Quantiles,Platt scaling

Calibrating Multiclass Models : Extension of binning methods,Matrix and vector scaling , Temperature scaling

本人亲测,上面的方法表现一般般

6.1 啥都靠不住,不如自己定义置信度

肯定有人会问有咩有别的好技巧

嗷,其实没啥特别好的技巧

目前为止我也没找到什么解决模型输出置信度问题的特别好的解决方案

而我自己 的方法很普通,就是

Majority Voting with Predefined Confidence Value

下面我要说一堆的废话了:

Step 1 我会用同一套训练数据训练大概30种常用CNN模型,比如Resnet, Xception等等,然后再自己设计20种左右的CNN模型

Step 2 从上面50种模型中找出performance表现最好的3种模型,并且这3种模型的结构必须差异化明显,比如以深度为主的Resnet, 和宽度为主的Inception

Step 3 对这3个模型再次进行深度调参,直到3个模型达到最优performance

Step 4 用这3个模型进行Majority voting:

4.1 voting小于2个agrees,confidence value为0.1

4.2 voting等于2个agrees,confidence value为0.5

4.3 voting等于3个agrees,confidence value为1.0

左一为预测正确的分布,右一为预测错误的分布

于是我会把threshold设置在1.0,因为对我来说

我更希望模型做出判断,尽量是对的,哪怕有很多测试数据没法做出判断也没关系

当然这只是一种方法啦,小伙伴们还可以自己想想别 方法

哎哟我的老天爷

可给我写完了

能不能接着更

就看各位大大的赞了

写出黑圆圈

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180701G0UARW00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券