Перейти к содержимому

Precision / Recall / F1

Accuracy показывает качество модели в целом. Но иногда нас интересует не вся модель сразу, а то, насколько хорошо она находит один конкретный класс.

Например, в задаче с породами собак нас может интересовать класс спаниель.

Тогда мы временно считаем:

спаниель — положительный класс
не спаниель — остальные объекты

Положительный класс — это не “хороший” класс и не обязательно класс с меткой 1. Это просто класс, на который мы сейчас обращаем внимание.

Когда выбран положительный класс, матрицу ошибок можно записать так:

Предсказано →
Реально ↓ спаниель не спаниель
спаниель TP FN
не спаниель FP TN

Здесь:

  • TP — настоящий спаниель предсказан как спаниель;
  • FP — не спаниель ошибочно предсказан как спаниель;
  • FN — настоящий спаниель ошибочно предсказан как не спаниель;
  • TN — не спаниель предсказан как не спаниель.

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

Например, в задаче диагностики:

болен — положительный класс
здоров — отрицательный класс

В такой задаче обычно важно найти людей, которым нужно дополнительное обследование. Поэтому положительным классом часто выбирают болен.

Тогда ошибки имеют разный смысл:

  • FP — здорового человека ошибочно отнесли к больным;
  • FN — больного человека ошибочно отнесли к здоровым.

Положительный класс выбирают не по номеру метки, а по смыслу задачи. Обычно это класс, который нужно обнаружить, найти или проконтролировать.

Precision отвечает на вопрос:

Если модель сказала “спаниель”, насколько ей можно доверять?

Формула:

Precision = TP / (TP + FP)

То есть среди всех объектов, которые модель назвала спаниелями, мы считаем долю настоящих спаниелей.

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

Recall отвечает на другой вопрос:

Какую долю настоящих спаниелей модель смогла найти?

Формула:

Recall = TP / (TP + FN)

То есть среди всех настоящих спаниелей мы считаем долю найденных.

Высокий Recall означает, что модель редко пропускает объекты выбранного класса.

Эти метрики смотрят на ошибки с разных сторон:

МетрикаГлавный вопрос
PrecisionНасколько точны предсказания выбранного класса?
RecallКакую долю объектов выбранного класса модель нашла?

В задаче диагностики высокий Precision означает меньше ложных тревог, а высокий Recall — меньше пропущенных больных.

F1 объединяет Precision и Recall в одно число.

F1 = 2 * Precision * Recall / (Precision + Recall)

F1 полезна, когда хочется учитывать и ложные срабатывания, и пропуски. Она принимает высокое значение только тогда, когда и Precision, и Recall достаточно высокие.

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

uses MLABC;
begin
var df := DataFrame.FromCsvText('''
Вес,ВысотаВХолке,Порода
20,33,бульдог
17,43,спаниель
16,41,спаниель
25,36,бульдог
26,34,бульдог
21,35,бульдог
24,35,бульдог
20,36,бульдог
14,39,спаниель
15,40,спаниель
19,39,бульдог
18,42,спаниель
22,34,бульдог
15,38,спаниель
19,40,спаниель
16,40,спаниель
''');
var X := df.ToMatrix(['Вес', 'ВысотаВХолке']);
var target := df.EncodeTarget('Порода');
var y := target.Labels;
var (Xtrain, Xtest, ytrain, ytest) :=
Validation.TrainTestSplit(X, y, testRatio := 0.25, seed := 42);
var model := new KNNClassifier(3);
model.Fit(Xtrain, ytrain);
var ypred := model.Predict(Xtest);
Println('Precision:', Metrics.Precision(ytest, ypred):0:3);
Println('Recall:', Metrics.Recall(ytest, ypred):0:3);
Println('F1:', Metrics.F1(ytest, ypred):0:3);
end.

Вывод программы:

Precision: 1.000
Recall: 0.500
F1: 0.667

Для этих значений матрица ошибок относительно положительного класса спаниель выглядит так:

Предсказано →
Реально ↓ спаниель не спаниель
спаниель 1 1
не спаниель 0 2

Разберём результат для класса спаниель:

  • Precision = 1.000: если модель сказала спаниель, она не ошиблась;
  • Recall = 0.500: модель нашла только половину настоящих спаниелей;
  • F1 = 0.667: итоговая оценка с учётом и точности, и полноты.

В этом примере задача бинарная: есть спаниель и не спаниель. Поэтому можно использовать прямые функции Metrics.Precision, Metrics.Recall и Metrics.F1.

МетрикаКогда особенно полезна
AccuracyНужна общая доля правильных ответов
PrecisionВажно, чтобы предсказания выбранного класса были надёжными
RecallВажно не пропустить объекты выбранного класса
F1Нужен баланс между Precision и Recall

Precision, Recall и F1 особенно важны, когда классы несбалансированы или когда ошибки разных типов имеют разную цену.