Визуализация калибровки прогнозируемой вероятности модели


23

Предположим, у меня есть прогностическая модель, которая выдает для каждого случая вероятность для каждого класса. Теперь я признаю, что есть много способов оценить такую ​​модель, если я хочу использовать эти вероятности для классификации (точность, отзыв и т. Д.). Я также признаю, что кривая ROC и область под ней могут использоваться для определения того, насколько хорошо модель различает классы. Это не то, о чем я спрашиваю.

Я заинтересован в оценке калибровки модели. Я знаю, что правило подсчета очков, такое как оценка Бриера, может быть полезным для этой задачи. Это нормально, и я, вероятно, включу что-то в том же духе, но я не уверен, насколько интуитивно понятны такие показатели для непрофессионала. Я ищу что-то более визуальное. Я хочу, чтобы человек, интерпретирующий результаты, мог видеть, может ли 70% прогнозировать, когда это что-то произойдет, что это на самом деле происходит ~ 70% времени и т. Д.

Я слышал (но никогда не использовал) графики QQ , и сначала я подумал, что это то, что я искал. Однако, похоже, что оно действительно предназначено для сравнения двух вероятностных распределений . Это не то, что у меня есть. Для некоторых случаев у меня есть прогнозируемая вероятность, а затем, действительно ли произошло событие:

Index    P(Heads)    Actual Result
    1          .4            Heads
    2          .3            Tails
    3          .7            Heads
    4         .65            Tails
  ...         ...              ...

Так что, сюжет QQ действительно то, что я хочу, или я ищу что-то еще? Если я должен использовать график QQ, как правильно преобразовать мои данные в вероятностные распределения?

Я полагаю, что могу отсортировать оба столбца по прогнозируемой вероятности, а затем создать несколько корзин. Это то, что я должен делать, или я где-то размышляю? Я знаком с различными методами дискретизации, но существует ли какой-то конкретный способ дискретизации в контейнеры, который является стандартным для такого рода вещей?

Ответы:


19

Ваше мышление хорошо.

Джон Тьюки рекомендовал разделить пополам на две части: разбить данные на верхнюю и нижнюю половинки, затем разбить эти половины, а затем рекурсивно разделить крайние половины. По сравнению с биннингом одинаковой ширины это позволяет визуально проверить поведение хвоста, не выделяя слишком много графических элементов в большую часть данных (в середине).

Вот пример (с использованием R) подхода Тьюки. (Это не совсем то же самое: он реализован mletterнемного по-другому.)

Во-первых, давайте создадим некоторые прогнозы и некоторые результаты, которые соответствуют этим прогнозам:

set.seed(17)
prediction <- rbeta(500, 3/2, 5/2)
actual <- rbinom(length(prediction), 1, prediction)
plot(prediction, actual, col="Gray", cex=0.8)

Сюжет не очень информативен, потому что все actualзначения, конечно, либо (не произошло), либо (произошло). (Это выглядит как фон серых открытых кругов на первом рисунке ниже.) Этот график нуждается в сглаживании. Для этого мы храним данные. Функция выполняет деление пополам. Его первый аргумент - это массив рангов от 1 до (второй аргумент). Он возвращает уникальные (числовые) идентификаторы для каждого бина:101mletterrn

mletter <- function(r,n) {
    lower <-  2 + floor(log(r/(n+1))/log(2))
    upper <- -1 - floor(log((n+1-r)/(n+1))/log(2))
    i <- 2*r > n
    lower[i] <- upper[i]
    lower
}

Используя это, мы сопоставляем как прогнозы, так и результаты и усредняем каждое в каждом из них. Попутно мы вычисляем популяции бинов:

classes <- mletter(rank(prediction), length(prediction))
pgroups <- split(prediction, classes)
agroups <- split(actual, classes)
bincounts <- unlist(lapply(pgroups, length)) # Bin populations
x <- unlist(lapply(pgroups, mean))           # Mean predicted values by bin
y <- unlist(lapply(agroups, mean))           # Mean outcome by bin

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

binprop <- bincounts / max(bincounts)
colors <- -log(binprop)/log(2)
colors <- colors - min(colors)
colors <- hsv(colors / (max(colors)+1))

Имея это в виду, мы теперь улучшаем предыдущий сюжет:

abline(0,1, lty=1, col="Gray")                           # Reference curve
points(x,y, pch=19, cex = 3 * sqrt(binprop), col=colors) # Solid colored circles
points(x,y, pch=1, cex = 3 * sqrt(binprop))              # Circle outlines

фигура

В качестве примера плохого прогноза давайте изменим данные:

set.seed(17)
prediction <- rbeta(500, 5/2, 1)
actual <- rbinom(length(prediction), 1, 1/2 + 4*(prediction-1/2)^3)

Повторение анализа дает этот график, на котором отклонения очевидны:

фигура 2

Эта модель имеет тенденцию быть чрезмерно оптимистичной (средний результат для прогнозов в диапазоне от 50% до 90% слишком низок). В тех немногих случаях, когда прогноз низкий (менее 30%), модель слишком пессимистична.


(+1) Очень приятно, спасибо. Я думаю, что цвета могут немного отвлекать от цели, но остальное было хорошей идеей и очень хорошим объяснением.
Майкл МакГоуэн

Майкл, я обнаружил, что нужен какой-то цвет, чтобы увидеть очень маленькие круги, которые появляются на обоих концах. Постоянный цвет, конечно же, достиг бы этого. Просто замените col=colorsцвет, который вы хотите, например col="Red".
whuber

+1, это очень мило. Однако я не совсем понимаю, почему контрольная линия - простая прямая 45-градусная линия вместо правильной линии логистической регрессии или лесса? Я должен подумать, что это были бы более подходящие ссылки, по которым можно судить о качестве прогнозов.
gung - Восстановить Монику

пп±[0,1]×[0,1]
whuber

п(1-п)/NпN

4

Другой вариант - изотоническая регрессия. Он аналогичен ответу whuber, за исключением того, что ячейки генерируются динамически, а не путем деления пополам, с требованием, чтобы выходные данные строго увеличивались.

Это первичное использование изотонической регрессии для перекалибровки ваших вероятностей, если показано, что они плохо откалиброваны, но также может использоваться для визуализации. По сути, если линия изотонической регрессии примерно следует линии Y = X, ваши вероятности правильно откалиброваны.

Изотоническая регрессия по вероятностям

Это изотоническая регрессия, примененная к проблеме, показанной Уубером.

import numpy as np
import matplotlib.pyplot as plt
from sklearn.isotonic import IsotonicRegression

prediction = np.random.beta(3.0/2.0, 5.0/2.0, size=500)
actual = np.random.binomial(1,prediction, len(prediction))
plt.scatter(prediction, actual,  facecolors='none', edgecolors=[0.3,0.3,0.3], label='Data')

ir = IsotonicRegression()
isotonic = ir.fit_transform(prediction, actual)
plt.plot(prediction, isotonic,'ok', label='Isotonic Fit')

plt.xlabel('Prediction')
plt.ylabel('Actual')
plt.plot([0,1],[0,1], '--k', label='y=x line')
plt.legend(loc = 'center left')

http://fa.bianp.net/blog/2013/isotonic-regression/

http://stat.wikia.com/wiki/Isotonic_regression


0

Вы также можете посмотреть на пакет «проверки»:

http://cran.r-project.org/web/packages/verification/index.html

В виньетке есть графики, которые могут быть полезны:

http://cran.r-project.org/web/packages/verification/vignettes/verification.pdf


1
Ссылка виньетки больше не работает, и первая ссылка CRAN, кажется, больше не имеет виньетки.
BLT
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.