В этом посте мы рассмотрим некоторые методы оценки задач классификации в машинном обучении. Методы, о которых мы поговорим:

  • Матрица путаницы
  • Точность
  • Точность
  • Отзывать
  • F1-счет
  • Кривая точности-отзыва (кривая PR)
  • Кривая ROC (кривая рабочих характеристик приемника)
  • Площадь под кривой (AUC)

Начнем с матрицы путаницы…

Матрица путаницы

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

Истинные положительные результаты (TP): прогнозируемые положительные результаты, которые на самом деле являются положительными.

Ложные срабатывания (FP): предсказано положительное, но на самом деле отрицательное.

Истинно отрицательные результаты (TN): прогнозируемый отрицательный результат, фактически отрицательный результат.

Ложноотрицательные результаты (FN): прогнозируемые отрицательные результаты, на самом деле положительные.

Для вычисления матрицы путаницы мы будем использовать класс ConfusionMatrixDisplay из библиотеки sklearn.

Документация для ConfusionMatrixDisplay

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import ConfusionMatrixDisplay
from sklearn.linear_model import LogisticRegression
X,y = load_breast_cancer(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
clf = LogisticRegression(max_iter=10000)
clf.fit(X_train, y_train)
ConfusionMatrixDisplay.from_estimator(clf, X_test, y_test, display_labels = ['malignant', 'benign'])

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

В этом случае у нас есть матрица точности для набора данных рака. Мы видим, что количество истинно положительных результатов равно 39. Это означает, что модель смогла правильно идентифицировать 39 образцов с раком.

Однако у нас также есть 1 ложноположительный результат (на самом деле у пациента нет рака, но модель говорит, что у пациента рак). Ложноположительные результаты в этом случае могут быть не столь критичны, так как дополнительный медицинский контроль позже выявит, что у пациента нет рака (за исключением нескольких дней тяжелых для пациента дней…).

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

Матрица путаницы для многоклассовой классификации

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

Размер матрицы путаницы такой же, как и количество целевых категорий. Одним из больших преимуществ матрицы путаницы является то, что она позволяет нам увидеть, сколько образцов того или иного класса было неправильно классифицировано и какой предсказанный класс был перепутан с каким фактическим классом.

Точность

Точность — это мера того, как часто классификатор делает правильный прогноз. Это отношение общего количества правильных прогнозов к общему количеству прогнозов.

Точность — это простая для понимания метрика, которая может быть очень полезна, когда набор данных сбалансирован. Однако это может ввести в заблуждение при оценке несбалансированных наборов данных. Когда целевые классы в наборе данных имеют большие различия с точки зрения выборок, это несбалансированный набор данных. Точность — не лучшая метрика для несбалансированных наборов данных. Давайте посмотрим на пример ниже.

Когда мы внимательно смотрим на матрицу путаницы, мы видим, что у нас есть только 25 пациентов, у которых действительно есть рак, по сравнению с 375, у которых на самом деле нет рака. Модель работает довольно хорошо с точностью 0,95 или нет? Не совсем так, модель довольно хорошо предсказывает пациентов, у которых нет рака, но мы не можем сказать то же самое о пациентах, у которых действительно есть рак (правильно предсказал только 10 из 25, у которых действительно есть рак). Поскольку точность учитывает только отношение правильных прогнозов к общему количеству прогнозов, наиболее частая производительность класса доминирует над метрикой, что приводит к вводящей в заблуждение интерпретации производительности модели, когда у нас несбалансированный набор данных.

Для расчета точности мы будем использовать функцию precision_score из библиотеки sklearn.

Документация для precision_score()

y_pred = clf.predict(X_test)
#calling the accuracy_score function from metrics
accuracy_score = metrics.accuracy_score(y_test, y_pred)
print("Accuracy score is: {:.2f}".format(accuracy_score))
Accuracy score is: 0.96
correct_predictions = [pred for i,pred in enumerate(y_pred) if pred == y_test[i]]
accuracy_manual = len(correct_predictions)/len(y_pred)
print("Accuracy score is: {:.2f}".format(accuracy_manual))
Accuracy score is: 0.96

Точность

Точность — это мера отношения истинных положительных прогнозов к общему количеству положительных прогнозов модели. Точность является полезной метрикой в ​​тех случаях, когда ложные срабатывания более значительны, чем ложноотрицательные. Такими случаями могут быть системы рекомендаций, где ложные срабатывания могут привести к оттоку клиентов, что, в свою очередь, снижает успех в бизнесе.

Точность из нашего предыдущего примера будет:

Не так хорошо, как точность, верно? В этом случае ложноотрицательные результаты более важны, чем ложноположительные, мы не хотим ошибочно диагностировать любого больного раком как отрицательный, если у него действительно есть рак! У нас также есть метрика для этого, Напомним!

Для вычисления точности мы будем использовать функцию precision_score из библиотеки sklearn.

Документация для precision_score()

precision_score = metrics.precision_score(y_test, y_pred)
print("Precision score is: {:.2f}".format(precision_score))
Precision score is: 0.95
TP = [pred for i,pred in enumerate(y_pred) if (pred == y_test[i] & pred == 1)]
TP_FP = [pred for i,pred in enumerate(y_pred) if (pred == 1)]
precision_manual = len(TP) / len(TP_FP)
print("Precision score is: {:.2f}".format(precision_manual))
Precision score is: 0.95

Отзывать

Отзыв — это отношение того, сколько положительных случаев модель смогла правильно предсказать. Отзыв является полезным показателем, когда ложноотрицательные результаты более значительны, чем ложноположительные. Как мы уже упоминали, это, например, важно в медицинских случаях (как у нас с набором данных по раку), когда мы не хотим пропустить какие-либо фактические положительные результаты, тогда как ложные тревоги (ложные срабатывания) можно считать менее важными.

Отзыв из нашего предыдущего примера будет таким:

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

Для расчета точности мы будем использовать функцию Recall_score из библиотеки sklearn.

Документация для функции Recall_score()

recall_score = metrics.recall_score(y_test, y_pred)
print("Recall score is: {:.2f}".format(recall_score))
Recall score is: 0.99
TP = [pred for i,pred in enumerate(y_pred) if (pred == y_test[i] & pred == 1)]
TP_FN = [pred for i,pred in enumerate(y_pred) if (y_test[i] == 1)]
recall_manual = len(TP) / len(TP_FN)
print("Precision score is: {:.2f}".format(recall_manual))
Precision score is: 0.99

F1-счет

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

Оценка F1 из нашего предыдущего примера будет следующей:

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

Для расчета точности мы будем использовать функцию f1_score из библиотеки sklearn.

Документация для f1_score()

f1_score = metrics.f1_score(y_test, y_pred)
print("F1-score is: {:.2f}".format(f1_score))
F1-score is: 0.97
f1_manual = 2*precision_manual*recall_manual/(precision_manual + recall_manual)
print("F1-score is: {:.2f}".format(f1_manual))
F1-score is: 0.97

Кривая точности-отзыва (кривая PR)

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

Он часто используется в задачах с несбалансированным набором данных. У нас есть значения точности по оси Y и значения отзыва по оси X. В более ранних примерах мы видели, для каких вариантов использования могут подойти метрики точности и полноты. Что ж, кривая PR позволяет рассматривать как метрики, так и изменение одной по отношению к другой.

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

Чтобы построить pr-кривую для классификатора, мы будем использовать функцию precision_recall_curve() из библиотеки sklearn.

Документация для precision_recall_curve()

Мы можем получить вероятности, используя метод predict_proba(), а затем использовать эти вероятности для построения кривой PR. Порог принятия решения обычно равен 0,5. Это означает, что если вероятность больше 0,5, то она будет прогнозироваться как положительная.

from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt
%matplotlib inline
probabilities = clf.predict_proba(X_test)[:,1]
precision_vals,recall_vals,thresholds = precision_recall_curve(y_test, probabilities)
plt.plot(recall_vals, precision_vals, label = 'PR Curve', marker='o')
for i,val in enumerate(precision_vals):
  if precision_vals[i] != precision_vals[-1]:
    plt.text(recall_vals[i], val, str(round(thresholds[i],3)), fontsize=10)
plt.axvline(x=1,ymin=0, ymax=0.95, color='r', label="Best Model")
plt.axhline(y=1, xmin=0, xmax=0.95, color='r')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.legend(['PR Curve', 'Best model'], loc = 'best')
plt.show()

Здесь мы рассчитали значения точности и полноты для каждого порога и нанесли их на график. Красные линии представляют собой идеальный классификатор. Наши кривые PR также, кажется, работают довольно хорошо. На каждом маркере мы также можем видеть соответствующее пороговое значение вероятности. Мы хотим выбрать тот порог, который лежит ближе к нашей красной линии совершенства. Здесь, в зависимости от того, какую метрику мы стремимся максимизировать, мы можем выбрать порог в соответствии с этим. Если у нас нет предпочтения к отзыву или точности, мы также можем рассчитать f1-оценку для каждого порога и сделать выбор в соответствии с этим.

f1_score = (2 * precision_vals * recall_vals) / (precision_vals + recall_vals)
f1_score:
array([0.96598639, 0.95890411, 0.96551724, 0.97222222, 0.97902098,
       0.97183099, 0.9787234 , 0.98571429, 0.97841727, 0.97101449,
       0.96350365, 0.95588235, 0.94814815, 0.94029851, 0.93233083,
       0.92424242, 0.91603053, 0.90769231, 0.89922481, 0.890625  ,
       0.88188976, 0.87301587, 0.864     , 0.85483871, 0.84552846,
       0.83606557, 0.82644628, 0.81666667, 0.80672269, 0.79661017,
       0.78632479, 0.77586207, 0.76521739, 0.75438596, 0.74336283,
       0.73214286, 0.72072072, 0.70909091, 0.69724771, 0.68518519,
       0.6728972 , 0.66037736, 0.64761905, 0.63461538, 0.62135922,
       0.60784314, 0.59405941, 0.58      , 0.56565657, 0.55102041,
       0.53608247, 0.52083333, 0.50526316, 0.4893617 , 0.47311828,
       0.45652174, 0.43956044, 0.42222222, 0.40449438, 0.38636364,
       0.36781609, 0.34883721, 0.32941176, 0.30952381, 0.28915663,
       0.26829268, 0.24691358, 0.225     , 0.20253165, 0.17948718,
       0.15584416, 0.13157895, 0.10666667, 0.08108108, 0.05479452,
       0.02777778, 0.        ])
import numpy as np
ix = np.argmax(f1_score)
print('Best Threshold=%f, F1-Score=%.3f' % (thresholds[ix], f1_score[ix]))
Best Threshold=0.851244, F1-Score=0.986

Кривая ROC (кривая рабочих характеристик приемника)

Кривая ROC представляет собой график, показывающий производительность модели классификации для различных порогов классификации путем построения графика истинной положительной скорости (отзыва) в сравнении с ложноположительной частотой (FPR). Она имеет ту же идею, что и кривая PR, но мы строим FPR вместо точности на этой кривой.

Чтобы построить ROC-кривую для классификатора, мы будем использовать функцию roc_curve() из библиотеки sklearn.

Документация для roc_curve()

from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_test, probabilities)
plt.plot( fpr, tpr,  label = 'ROC Curve', marker='o')
for i,val in enumerate(tpr):
    plt.text(fpr[i], val, str(round(thresholds[i],3)), fontsize=10)
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.legend(loc = 'best')
plt.show()

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

На кривой ROC мы ищем идеальную точку, ближайшую к верхнему левому углу. Было бы полезно иметь число для оценки того, насколько близка наша кривая к верхнему левому углу, верно? Площадь под кривой (AUC) — еще один метод, который может нам здесь помочь.

Площадь под кривой (AUC)

AUC/площадь под кривой — это вся двумерная площадь под кривой ROC. AUC помогает нам обобщить информацию из кривой ROC (также может использоваться для кривой PR) в одно значение.

Кривая ROC в основном представляет собой кривую вероятностей (порогов), а AUC в основном является мерой разделимости классов. Он говорит нам, насколько хорошо модель способна предсказывать классы. Следовательно, более высокое значение AUC означает лучший классификатор. Значение AUC варьируется от 0 до 1, то есть значение 1 будет означать идеальный классификатор.

Чтобы рассчитать показатель AUC для roc, мы будем использовать функцию roc_auc_score() из библиотеки sklearn.

Документация для roc_auc_score()

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

plt.plot( fpr, tpr,  label = 'ROC curve')
plt.fill_between(fpr, tpr, alpha=0.3)
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.legend(loc = 'best')
plt.grid()
plt.show()

Модель классификатора, которая не может различать два класса (классификатор без навыков), будет предсказывать наиболее часто встречающийся класс или случайный класс для всех прогнозов и будет иметь AUC 0,5. Его кривая ROC будет диагональной линией, как показано ниже. Классификатор, который все время предсказывает неправильно (0% правильных предсказаний), будет выглядеть прямо противоположно лучшей кривой.

from sklearn.metrics import roc_curve
pnt_1 = [0, 1]
pnt_2 = [0, 1]
fpr, tpr, thresholds = roc_curve(y_test, probabilities)
plt.plot( fpr, tpr,  label = 'ROC curve for DecisionTree')
plt.plot( pnt_1, pnt_2,  label = 'ROC curve for AUC=0.5', color='r')
plt.fill_between( pnt_1, pnt_2, alpha=0.3, facecolor='r')
plt.axvline(x=1,ymin=0.05, ymax=0.95, color='r', linestyle='--', label="ROC curve for AUC=0.0")
plt.axhline(y=0, xmin=0.05, xmax=0.95, color='r', linestyle='--')
plt.xlabel('FPR')
plt.ylabel('TPR')
plt.legend(loc = 'best')
plt.show()

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

from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, probabilities)
0.9977071732721913

Преимущества:

  • AUC не зависит от масштаба. Это мера того, насколько хороши прогнозы ранжированы, а не их абсолютные значения.
  • AUC не зависит от порога классификации. Это мера производительности модели (правильность прогнозов) независимо от выбранного порога классификации.

Недостатки:

  • Не всегда требуется инвариантность к масштабу. Иногда нам нужны хорошо адаптированные результаты oriability.
  • Также не всегда требуется инвариантность к порогу. Когда существуют большие различия в отношении ложноотрицательных и ложноположительных результатов, мы можем стремиться минимизировать только один из них. Например, ранее в примере с раком мы упоминали, как важно свести к минимуму ложноотрицательные результаты. В этом случае AUC не будет полезной метрикой.

Кривая PR против кривой ROC

  • Кривые ROC подходят, когда мы имеем дело с более сбалансированным набором данных, тогда как кривые PR подходят для несбалансированных наборов данных.
  • Кривая PR не учитывает истинные отрицательные значения, поэтому это полезная метрика, когда у нас несбалансированный набор данных, если отрицательный класс является классом большинства, учитывая, что правильные отрицательные прогнозы не так важны для проблемы.
  • Поскольку кривая ROC также учитывает истинные отрицательные значения, ее лучше использовать, если важен и отрицательный класс (когда важны как TP, так и TN).

В этом посте мы рассмотрели методы оценки для задач классификации. Я надеюсь, что было полезно понять эти широко используемые показатели. Если у вас есть какие-либо вопросы или отзывы, не стесняйтесь оставлять комментарии ниже!

Если вам это нравится, не стесняйтесь следовать за мной для получения дополнительных бесплатных руководств и курсов по машинному обучению!