如何使用Keras计算预测的不确定性?

43
我想计算NN模型的确定性/置信度(参见我的深度模型不知道什么)-当NN告诉我一张图片代表“8”时,我想知道它有多确定。我的模型是99%肯定它是“8”,还是51%肯定它是“8”,但也可能是“6”?某些数字相当模糊,我想知道哪些图像只是模型在“抛硬币”。
我已经找到了一些理论写作,但我无法将其编码。如果我理解正确,我应该对测试图像进行多次评估,同时“关闭”不同的神经元(使用辍学),然后...?
在MNIST数据集上工作,我正在运行以下模型:
from keras.models import Sequential
from keras.layers import Dense, Activation, Conv2D, Flatten, Dropout

model = Sequential()
model.add(Conv2D(128, kernel_size=(7, 7),
                 activation='relu',
                 input_shape=(28, 28, 1,)))
model.add(Dropout(0.20))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Dropout(0.20))
model.add(Flatten())
model.add(Dense(units=64, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(units=10, activation='softmax'))
model.summary()
model.compile(loss='categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])
model.fit(train_data, train_labels,  batch_size=100, epochs=30, validation_data=(test_data, test_labels,))

如何使用这个模型进行预测,以获取其关于预测的确定性?我希望能有一些实际的例子(最好是在Keras中,但任何例子都可以)。

为了澄清,我正在寻找一个使用Yurin Gal所概述的方法获取确定性的例子(或者解释为什么其他方法会产生更好的结果)。


您可以使用蒙特卡罗Dropout方法来计算预测的不确定性(https://dev59.com/qsPra4cB1Zd3GeqPfGVZ#71750927)。以下是分类(https://towardsdatascience.com/when-your-neural-net-doesnt-know-a-bayesian-approach-with-keras-4782c0818624)和回归(https://towardsdatascience.com/extreme-event-forecasting-with-lstm-autoencoders-297492485037)上两个有用的应用场景。 - Marco Cerliani
4个回答

34

如果您想实现dropout方法来衡量不确定性,应按以下步骤进行:

  1. 实现一种在测试时间也应用dropout的函数:

  2. import keras.backend as K
    f = K.function([model.layers[0].input, K.learning_phase()],
                   [model.layers[-1].output])
    
    使用此函数作为不确定性预测器,例如可以按以下方式使用:
    def predict_with_uncertainty(f, x, n_iter=10):
        result = numpy.zeros((n_iter,) + x.shape)
    
        for iter in range(n_iter):
            result[iter] = f(x, 1)
    
        prediction = result.mean(axis=0)
        uncertainty = result.var(axis=0)
        return prediction, uncertainty
    
    当然,您可以使用任何不同的函数来计算不确定性。

当然,您可以使用任何不同的函数来计算不确定性。


1
这看起来正是我在寻找的东西!不幸的是,在我离开时悬赏已经过期,所以我会重新开始并给予另一个悬赏。谢谢!(编辑:当然,我只能给予双倍奖励,并且只能在24小时后...所以明天才行... :) ) - johndodo
你的函数@Marcin Możejko中的n_iter代表什么? - Vincent Pakson
1
当你说不确定性时,当它说0.93时,它是意味着有93%的不确定性还是93%的确定性是正确的选择? - Vincent Pakson
使用此函数时遇到问题。这是使用什么版本的tensorflow和keras编写的? - hisairnessag3
1
我不太明白这个......模型不会每次对于相同的输入都预测出完全一样的值吗?那么方差应该每次都是0啊......当我在我的代码中实现这个时,我得到了10次(n_iter=10)完全相同的预测值。 - sand
这种实现贝叶斯Dropout的方式不会使其他层(如BN)也处于训练模式吗? - jdeJuan

6

我对得票最高的答案进行了一些更改,现在它对我有效了。

这是一种估算模型不确定性的方法。对于其他来源的不确定性,我发现https://eng.uber.com/neural-networks-uncertainty-estimation/很有帮助。

f = K.function([model.layers[0].input, K.learning_phase()],
               [model.layers[-1].output])


def predict_with_uncertainty(f, x, n_iter=10):
    result = []

    for i in range(n_iter):
        result.append(f([x, 1]))

    result = np.array(result)

    prediction = result.mean(axis=0)
    uncertainty = result.var(axis=0)
    return prediction, uncertainty

我在这里尝试使用了你的实现,虽然它似乎能够正常运行,但我只收到了一系列相同预测值的矩阵和一个只包含0的不确定性矩阵。非常感谢您提供的任何帮助!谢谢! - cmp
你得到了0,因为在推理期间禁用了dropout。只有在训练时启用它才会得到不同的结果。您可以在dropout层中设置可训练参数为True。您可以在此处找到详细的文章 - https://towardsdatascience.com/is-your-algorithm-confident-enough-1b20dfe2db08 - Malgo

3
更简单的方法是在任何你想要在推理期间运行的dropout层上设置training=True(本质上告诉层以训练模式运作,因此它始终存在于训练和推理中)。
import keras

inputs = keras.Input(shape=(10,))
x = keras.layers.Dense(3)(inputs)
outputs = keras.layers.Dropout(0.5)(x, training=True)

model = keras.Model(inputs, outputs)

上面的代码来自于这个问题


如果我使用 keras.Sequential([]),我该如何使用您的方法? - Gilfoyle
@Samuel 我来晚了,但也许对其他人有帮助: 如果您使用顺序 API,则无法设置 training=True - 您需要使用如示例中所示的函数式 API。 话虽如此,您可能想查看 uncertainty-wizard,它允许在顺序 API 中实现相同的功能(免责声明:我是作者)。 - miwe

3
您的模型使用softmax激活函数,因此获取某种不确定性度量的最简单方法是查看输出的softmax概率值:
probs = model.predict(some input data)[0]
probs数组将是一个包含10个元素的向量,其中的数字在[0, 1]范围内且总和为1.0,因此它们可以被解释为概率。例如,数字7的概率就是probs[7]
然后,您可以进行一些后处理,通常预测的类别是具有最高概率的类别,但您也可以查看具有第二高概率等的类别。

3
谢谢您的回答,但是链接的文章似乎与您的观点不一致:“在这个模型中,我们将预测结果输入到softmax函数中,它会为不同的类别(10个数字)给出概率。有趣的是,仅凭这些概率无法确定我们的模型是否对预测结果有把握。这是因为标准模型通过softmax函数传递的是预测均值而不是整个分布。”我漏掉了什么吗? - johndodo
2
@johndodo 这并不与我的答案相矛盾,我从未声称拥有最好的方法,只是最简单的方法。 - Dr. Snoopy
1
曲线与良好的确定性函数不匹配。您可以获得大致的想法(如果非常高或非常低),但仅此而已。您不能依赖预测输出来确定。 - Araymer
1
我确实同意概率可以给出一些关于结果不确定性的想法,但提问者引用了模型不确定性,这就像是在问一个问题:模型对概率预测的不确定性是什么?你可以对一个非常“暧昧”的概率有很高的确定性,反之亦然。例如,当你抛硬币时,你知道正面朝上的概率约为50%,你可以对概率在[49.9-50.1%]范围内非常确定。 - Arjan Groen
2
Softmax概率不是衡量不确定性的好度量标准。请参见https://arxiv.org/abs/1703.04977 - Gilfoyle
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接