Как рассчитать неопределенность прогноза с помощью Keras?

Я хотел бы рассчитать достоверность / достоверность модели 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,))

Как мне предсказать с помощью этой модели, чтобы я был уверен в предсказаниях? Я был бы признателен за несколько практических примеров (желательно в Керасе, но подойдет любой).

Чтобы уточнить, я ищу пример того, как получить уверенность, используя метод, описанный Юрин Гал (или объяснение того, почему какой-то другой метод дает лучшие результаты).


person johndodo    schedule 20.04.2017    source источник


Ответы (4)


Если вы хотите реализовать подход dropout для измерения неопределенности, вам следует сделать следующее:

  1. Реализуйте функцию, которая применяет dropout также во время тестирования:

    import keras.backend as K
    f = K.function([model.layers[0].input, K.learning_phase()],
                   [model.layers[-1].output])
    
  2. Используйте эту функцию как предсказатель неопределенности, например следующим образом:

    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
    

Конечно, вы можете использовать любую другую функцию для вычисления неопределенности.

person Marcin Możejko    schedule 27.04.2017
comment
Похоже, это именно то, что я искал! К сожалению, награда истекла, пока меня не было), поэтому я начну и награду еще одну. Спасибо! (РЕДАКТИРОВАТЬ: но, конечно, я могу наградить только двойным, и только через 24 часа ... так что до завтра ... :)) - person johndodo; 01.05.2017
comment
Что n_iter представляет в вашей функции @Marcin Możejko - person Vincent Pakson; 23.04.2018
comment
Когда вы говорите «неопределенность», когда вы говорите о 0,93, подразумевается ли это, что неопределенность составляет 93% или это 93% уверенности в том, что это правильный выбор? - person Vincent Pakson; 23.04.2018
comment
Возникли проблемы с этой функцией. с какой версией tensorflow, keras это было написано? - person hisairnessag3; 25.05.2018
comment
Я этого не понимаю ... не будет ли модель каждый раз предсказывать одно и то же значение для одного и того же входа? В этом случае var (дисперсия) будет каждый раз равняться 0 .. Когда я реализовал это для своего кода .. Я получил одно и то же значение, предсказанное все 10 раз (n_iter = 10) - person sand; 10.04.2019
comment
один вопрос к этому ответу. Такой способ реализации байесовского отсева не заставит другие слои (например, BN) вести себя также в режиме обучения ?. - person jdeJuan; 05.05.2019

Внесен несколько изменений в ответ, получивший наибольшее количество голосов. Теперь у меня работает.

Это способ оценки неопределенности модели. В качестве другого источника неопределенности я нашел https://eng.uber.com/neural-networks-unsurety-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
person Chexn    schedule 27.02.2019
comment
Я пробовал использовать здесь вашу реализацию, и хотя она, кажется, работает, мне кажется, что я получаю только матрицу тех же прогнозов и матрицу неопределенностей, содержащую 0? Любая помощь с благодарностью получена! Благодарность! - person cmp; 05.12.2019

Более простой способ - установить 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)

Приведенный выше код взят из этой проблемы.

person abagshaw    schedule 17.05.2019
comment
Как я могу использовать ваш подход, если я использую keras.Sequential([])? - person Samuel; 04.02.2020
comment
@Samuel Я опаздываю на вечеринку, но, возможно, это поможет другим: Нет, training=True нельзя установить, если вы используете последовательный API - вам нужно использовать функциональный API, как показано в примере. Тем не менее, вы можете попробовать мастер неопределенности, который позволяет добиться того же в последовательном API (отказ от ответственности: я автор) - person miwe; 10.02.2021

В вашей модели используется активация softmax, поэтому самый простой способ получить некоторую меру неопределенности - это посмотреть на выходные вероятности softmax:

probs = model.predict(some input data)[0]

Тогда массив probs будет 10-элементным вектором чисел в диапазоне [0, 1], сумма которых равна 1,0, поэтому их можно интерпретировать как вероятности. Например, вероятность цифры 7 равна probs[7].

Затем с помощью этой информации вы можете выполнить некоторую постобработку, обычно прогнозируемый класс имеет самую высокую вероятность, но вы также можете посмотреть на класс со второй по величине вероятностью и т. Д.

person Dr. Snoopy    schedule 20.04.2017
comment
Спасибо за ответ, однако ссылка на запись не согласна с you: В этой модели мы передаем наш прогноз в softmax, который дает нам вероятности для различных классов (10 цифр). Интересно, что этих вероятностей недостаточно, чтобы увидеть, уверена ли наша модель в своем прогнозе или нет. Это связано с тем, что стандартная модель будет передавать прогнозное среднее через softmax, а не через все распределение. Я что-то упускаю? - person johndodo; 21.04.2017
comment
@johndodo Это не противоречит моему ответу, я никогда не утверждал, что у меня есть лучший метод, только самый простой. - person Dr. Snoopy; 21.04.2017
comment
Правда. Хотя это работает? :) Я все еще надеюсь найти и другой ответ ... - person johndodo; 21.04.2017
comment
Кривая не соответствует кривой функции хорошей уверенности. Вы можете получить окольную идею (очень высокая или очень низкая), но это все. Вы не можете полагаться на результат прогноза с уверенностью - person Araymer; 26.08.2017
comment
этот работает для меня. У меня 4 класса. и я мог бы использовать вероятность для определения доверительного интервала? - person Nufa; 15.10.2018
comment
Я согласен с тем, что вероятность дает некоторое представление о неопределенности результата, но спрашивающий ссылается на неопределенность модели, что похоже на вопрос: какова неопределенность вероятностного предсказания модели? У вас может быть очень высокая уверенность в очень «амбивалентной» вероятности, и наоборот. Например. Вы можете быть уверены на 99% в том, что вероятность находится в диапазоне [49,9–50,1%], например, когда вы подбрасываете монету, вы знаете, что вероятность выпадения орла составляет ~ 50%. - person Arjan Groen; 05.08.2019
comment
@ArjanGroen Я не понимаю, как ваш комментарий привносит сюда что-то новое, мы говорим о вероятностях модели, если вы откалибруете эти вероятности, они фактически означают то, что должны означать. - person Dr. Snoopy; 05.08.2019
comment
@MatiasValdenegro Я согласен с вашим комментарием о вероятностях. Мой комментарий призван внести свой вклад в прояснение разницы между понятиями неопределенности и вероятности. - person Arjan Groen; 05.08.2019
comment
Вероятности Softmax не являются хорошей метрикой для измерения неопределенности. См. arxiv.org/abs/1703.04977. - person Samuel; 04.02.2020