Как настроить заднее пороговое значение вероятности для двоичного классификатора, используя более одного показателя производительности с пакетом mlr в R? - PullRequest
1 голос
/ 12 апреля 2020

Следующая ссылка дала мне лучшее понимание включения обычных затрат в мою модель двоичной классификации: https://mlr.mlr-org.com/articles/tutorial/cost_sensitive_classif.html

При стандартном классификаторе порог по умолчанию обычно составляет 0,5, и цель состоит в том, чтобы максимально уменьшить общее количество ошибок ошибочной классификации (получить максимальную точность). Однако все ошибки ошибочной классификации обрабатываются одинаково. Обычно это не так в реальных условиях, поскольку стоимость ложного отрицания может быть намного выше стоимости ложного отрицания.

Используя эмпирический порог, я смог получить оптимальное пороговое значение для классификации экземпляра на хороший или плохой при минимизации средней стоимости. С другой стороны, это достигается ценой снижения точности и других показателей эффективности. Это показано на следующем рисунке:

На рисунке выше красной линией обозначен стандартный порог 0,5, который максимизирует точность, но дает неоптимальную среднюю стоимость кредита. Синяя линия обозначает желаемый порог, который минимизирует стоимость, но теперь точность резко снижена.

Как правило, меня не беспокоит снижение точности. Предположим, однако, что есть также стимул не только минимизировать стоимость, но и максимизировать точность. Обратите внимание, что точность является положительным прогнозирующим значением или ppv = TP / (TP + FP)). Тогда зеленая линия может быть хорошим компромиссом, который дает относительно низкую стоимость и относительно высокую PPV. Здесь я нарисовал зеленую линию как среднее значение красной и синей линий (кажется, что и кредитные затраты, и функции ppv имеют примерно одинаковый градиент между этими регионами, поэтому расчет оптимального порога таким образом, вероятно, дает хорошую оценку), но есть ли способ точно рассчитать этот порог?

Я думаю о том, чтобы создать новый показатель производительности как функцию затрат и PPV, а затем минимизировать этот показатель производительности. Пример: measure = credit.costs * (- ppv)

Но я не уверен, как закодировать это в R. Любой совет по поводу того, что должно быть сделано, будет с благодарностью.

Мой Код R выглядит следующим образом:

library(mlr)

## Load dataset
data(GermanCredit, package = "caret")
credit.task = makeClassifTask(data = GermanCredit, target = "Class")

## Removing 2 columns: Purpose.Vacation,Personal.Female.Single
credit.task = removeConstantFeatures(credit.task)

## Generate cost matrix
costs = matrix(c(0, 1, 5, 0), 2)
colnames(costs) = rownames(costs) = getTaskClassLevels(credit.task)

## Make cost measure
credit.costs = makeCostMeasure(id = "credit.costs", name = "Credit costs", costs = costs, best = 0, worst = 5)

## Set training scheme with repeated 10-fold cross-validation
set.seed(100)
rin = makeResampleInstance("RepCV", folds = 10, reps = 3, task = credit.task)


## Fit a logistic regression model (nnet::multinom()) 
lrn = makeLearner("classif.multinom", predict.type = "prob", trace = FALSE)
r = resample(lrn, credit.task, resampling = rin, measures = list(credit.costs, mmce), show.info = FALSE)
r

# Tune the threshold using average costs based on the predicted probabilities on the 3 test data sets
cost_tune.res = tuneThreshold(pred = r$pred, measure = credit.costs)

# Tune the threshold using precision based on the predicted probabilities on the 3 test data sets
ppv_tune.res = tuneThreshold(pred = r$pred, measure = ppv)

d = generateThreshVsPerfData(r, measures = list(credit.costs, ppv, acc))
plt = plotThreshVsPerf(d)
plt + geom_vline(xintercept=cost_tune.res$th, colour = "blue") + geom_vline(xintercept=0.5, colour = "red") +
geom_vline(xintercept=1/2*(cost_tune.res$th + 0.5), colour = "green")


calculateConfusionMatrix(r$pred)
performance(r$pred, measures = list(acc, ppv, credit.costs))

Наконец, я также немного запутался в том, что касается моего значения ppv. Когда я наблюдаю свою матрицу путаницы, я вычисляю свою PPV как 442 / (442 + 289) = 0,6046512, но сообщаемое значение немного отличается (0,6053531). Что-то не так с моими расчетами?

...