3.3. Метрики и оценка: количественная оценка качества прогнозов

Существует 3 различных API для оценки качества прогнозов модели:

Наконец, Фиктивные модели (Dummy estimators) полезны для получения базового значения этих метрик для случайных прогнозов.

См. также

Информацию о “парных” метриках между выборками, а не моделями или прогнозами, см. в разделе Парные метрики, Cходство и Ядра.

3.3.1. Параметр scoring: определение правил оценки модели

Выбор и оценка модели с использованием таких инструментов, как model_selection.GridSearchCV и model_selection.cross_val_score, принимают параметр scoring, который контролирует, какую метрику они применяют для оценки.

3.3.1.1. Распространенные случаи: предопределенные значения

Для наиболее распространенных случаев использования вы можете назначить объект оценки с помощью параметра scoring; В таблице ниже показаны все возможные значения. Все объекты оценки следуют соглашению, согласно которому более высокие возвращаемые значения лучше, чем более низкие возвращаемые значения. Таким образом, метрики, которые измеряют расстояние между моделью и данными, такие как metrics.mean_squared_error, доступны как neg_mean_squared_error, которые возвращают отрицательное значение метрики.

scoring

Метод

Комментарий

Для задач классификации

‘accuracy’

metrics.accuracy_score

‘balanced_accuracy’

metrics.balanced_accuracy_score

‘top_k_accuracy’

metrics.top_k_accuracy_score

‘average_precision’

metrics.average_precision_score

‘neg_brier_score’

metrics.brier_score_loss

‘f1’

metrics.f1_score

для бинарного целевого значения

‘f1_micro’

metrics.f1_score

микроусредненный (micro-averaged)

‘f1_macro’

metrics.f1_score

макроусредненный (macro-averaged)

‘f1_weighted’

metrics.f1_score

средневзвешенное

‘f1_samples’

metrics.f1_score

по многокомпонентному образцу

‘neg_log_loss’

metrics.log_loss

требует predict_proba

‘precision’ etc.

metrics.precision_score

суффиксы применяются так же, как и ‘f1’

‘recall’ etc.

metrics.recall_score

суффиксы применяются так же, как и ‘f1’

‘jaccard’ etc.

metrics.jaccard_score

суффиксы применяются так же, как и ‘f1’

‘roc_auc’

metrics.roc_auc_score

‘roc_auc_ovr’

metrics.roc_auc_score

‘roc_auc_ovo’

metrics.roc_auc_score

‘roc_auc_ovr_weighted’

metrics.roc_auc_score

‘roc_auc_ovo_weighted’

metrics.roc_auc_score

Для задач кластеризации

‘adjusted_mutual_info_score’

metrics.adjusted_mutual_info_score

‘adjusted_rand_score’

metrics.adjusted_rand_score

‘completeness_score’

metrics.completeness_score

‘fowlkes_mallows_score’

metrics.fowlkes_mallows_score

‘homogeneity_score’

metrics.homogeneity_score

‘mutual_info_score’

metrics.mutual_info_score

‘normalized_mutual_info_score’

metrics.normalized_mutual_info_score

‘rand_score’

metrics.rand_score

‘v_measure_score’

metrics.v_measure_score

Для задач регрессии

‘explained_variance’

metrics.explained_variance_score

‘max_error’

metrics.max_error

‘neg_mean_absolute_error’

metrics.mean_absolute_error

‘neg_mean_squared_error’

metrics.mean_squared_error

‘neg_root_mean_squared_error’

metrics.root_mean_squared_error

‘neg_mean_squared_log_error’

metrics.mean_squared_log_error

‘neg_root_mean_squared_log_error’

metrics.root_mean_squared_log_error

‘neg_median_absolute_error’

metrics.median_absolute_error

‘r2’

metrics.r2_score

‘neg_mean_poisson_deviance’

metrics.mean_poisson_deviance

‘neg_mean_gamma_deviance’

metrics.mean_gamma_deviance

‘neg_mean_absolute_percentage_error’

metrics.mean_absolute_percentage_error

‘d2_absolute_error_score’

metrics.d2_absolute_error_score

‘d2_pinball_score’

metrics.d2_pinball_score

‘d2_tweedie_score’

metrics.d2_tweedie_score

Примеры использования:

>>> from sklearn import svm, datasets
>>> from sklearn.model_selection import cross_val_score
>>> X, y = datasets.load_iris(return_X_y=True)
>>> clf = svm.SVC(random_state=0)
>>> cross_val_score(clf, X, y, cv=5, scoring='recall_macro')
array([0.96..., 0.96..., 0.96..., 0.93..., 1.        ])

Примечание

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

3.3.1.2. Определение стратегии оценки с помощью метрических функций

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

  • функции, оканчивающиеся на _score, возвращают максимальное значение, чем выше, тем лучше.

  • функции, оканчивающиеся на _error или _loss, возвращают значение для минимизации, чем меньше, тем лучше. При преобразовании в объект оценки с помощью make_scorer установите для параметра greater_is_better значение False (True по умолчанию; см. описание параметра ниже).

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

Многим метрикам не присвоены имена для использования в качестве scoring значений, иногда потому, что они требуют дополнительных параметров, таких как fbeta_score. В таких случаях необходимо создать соответствующий объект оценки. Самый простой способ создать вызываемый объект для оценки - использовать make_scorer. Эта функция преобразует метрики в вызываемые объекты, которые можно использовать для оценки модели.

Одним из типичных вариантов использования является обертывание существующей метрической функции из библиотеки значениями ее параметров, отличными от значений по умолчанию, например, параметром beta для функции fbeta_score:

>>> from sklearn.metrics import fbeta_score, make_scorer
>>> ftwo_scorer = make_scorer(fbeta_score, beta=2)
>>> from sklearn.model_selection import GridSearchCV
>>> from sklearn.svm import LinearSVC
>>> grid = GridSearchCV(LinearSVC(dual="auto"), param_grid={'C': [1, 10]},
...                     scoring=ftwo_scorer, cv=5)

Пользовательские объекты оценки Click for more details

Второй вариант использования - создать полностью собственный объект оценки из простой функции Python с использованием make_scorer, который может принимать несколько параметров:

  • функция Python, которую вы хотите использовать (my_custom_loss_func в примере ниже)

  • функция Python возвращает оценку (greater_is_better=True, значение по умолчанию) или лос (greater_is_better=False). В случае лос выходные данные функции Python выдает отрицательные значения объекта оценки, что соответствует соглашению перекрестной проверки (кросс-валации), согласно которому скоры возвращают более высокие значения для лучших моделей.

  • только для метрик классификации: независимо от того требует ли предоставленная вами функция Python непрерывной уверенности в принятии решений. Если функция оценки принимает только оценки вероятности (например, metrics.log_loss), тогда необходимо установить параметр response_method, то есть в данном случае response_method="predict_proba". Некоторые функции оценки не обязательно требуют оценок вероятности, а скорее непороговых значений решения (например, metrics.roc_auc_score). В этом случае предоставляется такой список, как response_method=["decision_function", "predict_proba"]. В этом случае для оценки будет использоваться первый доступный метод в порядке, указанном в списке.

  • любые дополнительные параметры, такие как beta или labels в f1_score.

Вот пример создания пользовательской оценки и использование параметра greater_is_better:

>>> import numpy as np
>>> def my_custom_loss_func(y_true, y_pred):
...     diff = np.abs(y_true - y_pred).max()
...     return np.log1p(diff)
...
>>> # результат функции my_custom_loss_func оценки возвращаемого значения будет отрицательным,
>>> # которая будет np.log(2), 0.693, учитывая значения X и y определены ниже.
>>> score = make_scorer(my_custom_loss_func, greater_is_better=False)
>>> X = [[1], [1]]
>>> y = [0, 1]
>>> from sklearn.dummy import DummyClassifier
>>> clf = DummyClassifier(strategy='most_frequent', random_state=0)
>>> clf = clf.fit(X, y)
>>> my_custom_loss_func(y, clf.predict(X))
0.69...
>>> score(clf, X, y)
-0.69...

3.3.1.3. Реализация собственного объекта оценки

Вы можете создать еще более гибкие оценки моделей, создав свой собственный объект оценки с нуля, без использования фабрики make_scorer.

Как построить объект оценки с нуля Click for more details

Чтобы вызываемый объект был оценкой, он должен соответствовать протоколу, указанному следующими двумя правилами:

  • Его можно вызвать с параметрами (estimator, X, y), где estimator - это модель, которую следует оценить, X - валидационные данные, а y является базовой целью для X (в обучении с учителем) или None (в обучении без учителя).

  • Он возвращает число с плавающей точкой, которое количественно определяет качество прогноза estimator для X со ссылкой на y. Опять же, по соглашению, чем выше число, тем лучше, поэтому, если ваш объект оценки возвращает лос, это значение должно быть отрицательным.

  • Дополнение: если требуется передать дополнительные метаданные, он должен предоставить метод get_metadata_routing, возвращающий запрошенные метаданные. Пользователь должен иметь возможность устанавливать запрошенные метаданные с помощью метода set_score_request. Дополнительную информацию см. в Руководстве пользователя и Руководстве разработчика.

Примечание

Использование пользовательских оценок в функциях, где n_jobs > 1

Хотя определение пользовательской функции оценки вместе с вызывающей функцией должно работать “из коробки” с бэкэндом joblib по умолчанию (loky), импорт ее из другого модуля будет более надежным подходом и будет работать независимо от бэкэнда joblib.

Например, чтобы использовать n_jobs больше 1 в приведенном ниже примере, функция custom_scoring_function сохраняется в созданном пользователем модуле (custom_scorer_module.py) и импортируется:

>>> from custom_scorer_module import custom_scoring_function 
>>> cross_val_score(model,
...  X_train,
...  y_train,
...  scoring=make_scorer(custom_scoring_function, greater_is_better=False),
...  cv=5,
...  n_jobs=-1) 

3.3.1.4. Использование множественной метрической оценки

Scikit-learn также позволяет оценивать несколько метрик в GridSearchCV, RandomizedSearchCV и cross_validate.

Существует три способа указать несколько метрик оценки для параметра scoring:

  • Как итерация строковых метрик:

    >>> scoring = ['accuracy', 'precision']
    
  • Как dict, сопоставляющий имя модели на функцию оценки:

    >>> from sklearn.metrics import accuracy_score
    >>> from sklearn.metrics import make_scorer
    >>> scoring = {'accuracy': make_scorer(accuracy_score),
    ...            'prec': 'precision'}
    

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

  • Как вызываемый объект, возвращающий словарь оценок:

    >>> from sklearn.model_selection import cross_validate
    >>> from sklearn.metrics import confusion_matrix
    >>> # A sample toy binary classification dataset
    >>> X, y = datasets.make_classification(n_classes=2, random_state=0)
    >>> svm = LinearSVC(dual="auto", random_state=0)
    >>> def confusion_matrix_scorer(clf, X, y):
    ...      y_pred = clf.predict(X)
    ...      cm = confusion_matrix(y, y_pred)
    ...      return {'tn': cm[0, 0], 'fp': cm[0, 1],
    ...              'fn': cm[1, 0], 'tp': cm[1, 1]}
    >>> cv_results = cross_validate(svm, X, y, cv=5,
    ...                             scoring=confusion_matrix_scorer)
    >>> # Getting the test set true positive scores
    >>> print(cv_results['test_tp'])
    [10  9  8  7  8]
    >>> # Getting the test set false negative scores
    >>> print(cv_results['test_fn'])
    [0 1 2 3 2]
    

3.3.2. Метрики классификации

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

Некоторые из них ограничены случаем бинарной классификации:

precision_recall_curve(y_true, probas_pred, *)

Compute precision-recall pairs for different probability thresholds.

roc_curve(y_true, y_score, *[, pos_label, ...])

Compute Receiver operating characteristic (ROC).

class_likelihood_ratios(y_true, y_pred, *[, ...])

Compute binary classification positive and negative likelihood ratios.

det_curve(y_true, y_score[, pos_label, ...])

Compute error rates for different probability thresholds.

Другие также работают в многоклассовом случае:

balanced_accuracy_score(y_true, y_pred, *[, ...])

Compute the balanced accuracy.

cohen_kappa_score(y1, y2, *[, labels, ...])

Compute Cohen's kappa: a statistic that measures inter-annotator agreement.

confusion_matrix(y_true, y_pred, *[, ...])

Compute confusion matrix to evaluate the accuracy of a classification.

hinge_loss(y_true, pred_decision, *[, ...])

Average hinge loss (non-regularized).

matthews_corrcoef(y_true, y_pred, *[, ...])

Compute the Matthews correlation coefficient (MCC).

roc_auc_score(y_true, y_score, *[, average, ...])

Compute Area Under the Receiver Operating Characteristic Curve (ROC AUC) from prediction scores.

top_k_accuracy_score(y_true, y_score, *[, ...])

Top-k Accuracy classification score.

Некоторые из них также работают в случае с несколькими метками:

accuracy_score(y_true, y_pred, *[, ...])

Accuracy classification score.

classification_report(y_true, y_pred, *[, ...])

Build a text report showing the main classification metrics.

f1_score(y_true, y_pred, *[, labels, ...])

Compute the F1 score, also known as balanced F-score or F-measure.

fbeta_score(y_true, y_pred, *, beta[, ...])

Compute the F-beta score.

hamming_loss(y_true, y_pred, *[, sample_weight])

Compute the average Hamming loss.

jaccard_score(y_true, y_pred, *[, labels, ...])

Jaccard similarity coefficient score.

log_loss(y_true, y_pred, *[, eps, ...])

Log loss, aka logistic loss or cross-entropy loss.

multilabel_confusion_matrix(y_true, y_pred, *)

Compute a confusion matrix for each class or sample.

precision_recall_fscore_support(y_true, ...)

Compute precision, recall, F-measure and support for each class.

precision_score(y_true, y_pred, *[, labels, ...])

Compute the precision.

recall_score(y_true, y_pred, *[, labels, ...])

Compute the recall.

roc_auc_score(y_true, y_score, *[, average, ...])

Compute Area Under the Receiver Operating Characteristic Curve (ROC AUC) from prediction scores.

zero_one_loss(y_true, y_pred, *[, ...])

Zero-one classification loss.

А некоторые работают с двоичными и несколькими метками (но не многоклассовыми) задачами:

average_precision_score(y_true, y_score, *)

Compute average precision (AP) from prediction scores.

В следующих подразделах мы опишем каждую из этих функций, а затем приведем некоторые примечания по общему API и определению метрик.

3.3.2.1. От двоичного кода к мультиклассам и нескольким меткам

Некоторые метрики по существу определены для задач бинарной классификации (например, f1_score, roc_auc_score). В этих случаях по умолчанию оценивается только положительная метка, предполагая, что по умолчанию положительный класс помечен 1 (хотя это можно настроить с помощью параметра pos_label).

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

  • "macro" просто вычисляет среднее значение бинарных метрик, придавая каждому классу одинаковый вес. В задачах, где нечасто встречающиеся классы все же важны, макроусреднение может стать средством выделения их эффективности. С другой стороны, предположение о том, что все классы одинаково важны, часто не соответствует действительности, поэтому макроусреднение будет чрезмерно подчеркивать обычно низкие показатели по редко встречающимся классам.

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

  • "micro" дает каждой паре классов выборки равный вклад в общую метрику (за исключением веса выборки). Вместо того чтобы суммировать метрики по классам, здесь суммируются делители и делимые, составляющие метрики по классам, чтобы вычислить общий коэффициент. Микроусреднение может быть предпочтительным в данных с несколькими метками, включая многоклассовую классификацию, когда класс большинства игнорируется.

  • "samples" применяется только к задачам с несколькими метками. Он не вычисляет показатель для каждого класса, а вместо этого рассчитывает метрику по истинным и прогнозируемым классам для каждой выборки в оценочных данных и возвращает их (взвешенное по sample_weight) среднее значение.

  • Выбор average=None вернет массив с оценкой для каждого класса.

Хотя мультиклассовые данные предоставляются метрике, как и двоичные целевые объекты, в виде массива меток классов, данные с несколькими метками указываются в виде единичной матрицы, в которой ячейка [i, j] имеет значение 1, если выборка i имеет метку j и значение 0 в противном случае.

3.3.2.2. Оценка точности (accuracy)

Функция accuracy_score вычисляет точность, либо долю (по умолчанию), либо количество (normalize=False) правильных прогнозов.

При классификации по нескольким меткам функция возвращает точность подмножества. Если весь набор предсказанных меток для выборки строго соответствует истинному набору меток, то точность подмножества равна 1.0; в противном случае это 0.0.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то доля правильных предсказаний по сравнению с \(n_\text{samples}\) определяется как

\[\texttt{accuracy}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} 1(\hat{y}_i = y_i)\]

где \(1(x)\) is the индикатор.

>>> import numpy as np
>>> from sklearn.metrics import accuracy_score
>>> y_pred = [0, 2, 1, 3]
>>> y_true = [0, 1, 2, 3]
>>> accuracy_score(y_true, y_pred)
0.5
>>> accuracy_score(y_true, y_pred, normalize=False)
2.0

В случае нескольких меток с индикаторами двоичных меток:

>>> accuracy_score(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
0.5

3.3.2.3. Оценка точности Top-k

Функция top_k_accuracy_score является обобщением accuracy_score. Разница в том, что прогноз считается правильным, если истинная метка связана с одним из самых высоких прогнозируемых значений k. accuracy_score - это частный случай когда k = 1.

Функция охватывает случаи бинарной и многоклассовой классификации, но не случая классификации с несколькими метками.

Если \(\hat{f}_{i,j}\) является прогнозируемым классом для \(i\)-й выборки, соответствующей \(j\)-му наибольшему прогнозируемому результату и \(y_i\) - соответствующее истинное значение, тогда доля верных предсказаний по \(n_\text{samples}\) определяется как

\[\texttt{top-k accuracy}(y, \hat{f}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \sum_{j=1}^{k} 1(\hat{f}_{i,j} = y_i)\]

где \(k\) - количество разрешенных предположений, а \(1(x)\) - это индикатор.

>>> import numpy as np
>>> from sklearn.metrics import top_k_accuracy_score
>>> y_true = np.array([0, 1, 2, 2])
>>> y_score = np.array([[0.5, 0.2, 0.2],
...                     [0.3, 0.4, 0.2],
...                     [0.2, 0.4, 0.3],
...                     [0.7, 0.2, 0.1]])
>>> top_k_accuracy_score(y_true, y_score, k=2)
0.75
>>> # Not normalizing gives the number of "correctly" classified samples
>>> top_k_accuracy_score(y_true, y_score, k=2, normalize=False)
3

3.3.2.4. Сбалансированная оценка точности

Функция balanced_accuracy_score вычисляет сбалансированную точность, что позволяет избежать завышенных оценок на несбалансированных наборах данных. Это макросреднее значение полноты (recall) оценоки по классу или, что то же самое, необработанная точность, где каждый образец взвешивается в соответствии с обратной распространенностью его истинного класса. Таким образом, для сбалансированных наборов данных оценка равна точности.

В двоичном случае сбалансированная точность равна среднему арифметическому чувствительности (true positive rate) и специфичности (true negative rate) или площать под кривой ROC с двоичными прогнозами, а не оценками

\[\texttt{balanced-accuracy} = \frac{1}{2}\left( \frac{TP}{TP + FN} + \frac{TN}{TN + FP}\right )\]

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

Напротив, если традиционная точность выше случайности только потому, что классификатор использует преимущества несбалансированного набора тестов, тогда сбалансированная точность, в зависимости от обстоятельств, упадет до \(\frac{1}{n\_classes}\) .

Оценка варьируется от 0 до 1, или при использовании adjusted=True масштабируется в диапазоне он \(\frac{1}{1 - n\_classes}\) до 1 включительно, с представлением в случайной оценке 0.

Если \(y_i\) - истинное значение \(i\)-й выборки, а \(w_i\) - соответствующий вес выборки, то мы корректируем вес выборки следующим образом

\[\hat{w}_i = \frac{w_i}{\sum_j{1(y_j = y_i) w_j}}\]

где \(1(x)\) - это индикатор. Учитывая прогнозируемую \(\hat{y}_i\) для выборки \(i\), сбалансированная точность определяется как

\[\texttt{balanced-accuracy}(y, \hat{y}, w) = \frac{1}{\sum{\hat{w}_i}} \sum_i 1(\hat{y}_i = y_i) \hat{w}_i\]

При adjusted=True сбалансированная точность сообщает об относительном увеличении от \(\texttt{balanced-accuracy}(y, \mathbf{0}, w) = \frac{1}{n\_classes}\). В двоичном случае это также известно как J-статистика Юдена или информированность.

Примечание

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

  • Наше определение: [Mosley2013], [Kelleher2015] и [Guyon2015], где [Guyon2015] принимает скорректированную версию, чтобы гарантировать, что случайные прогнозы имеют оценку \(0\), а идеальные прогнозы имеют оценку \(1\)..

  • Точность, сбалансированная по классам, как описано в [Mosley2013]: вычисляется минимум между точностью (precision) и полнотой (recall) для каждого класса. Затем эти значения усредняются по общему количеству классов, чтобы получить сбалансированную точность.

  • Сбалансированная точность, как описано в [Urbanowicz2015]: среднее значение чувствительности и специфичности вычисляется для каждого класса, а затем усредняется по общему числу классов.

3.3.2.5. Оценка Каппа Коэна (Сohen Kappa)

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

Оценка каппа (см. документацию) представляет собой число от -1 до 1. Оценка выше 0.8 обычно считается хорошим согласием; ноль или меньше означает отсутствие согласия (практически случайные метки).

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

>>> from sklearn.metrics import cohen_kappa_score
>>> y_true = [2, 0, 2, 2, 0, 1]
>>> y_pred = [0, 0, 2, 2, 0, 2]
>>> cohen_kappa_score(y_true, y_pred)
0.4285714285714286

3.3.2.6. Матрица ошибок (Confusion matrix)

Функция confusion_matrix оценивает точность классификации, вычисляя матрицу ошибок (или как еще называют Матрицу Несоответствий), где каждая строка соответствует истинному классу (Википедия и другие ссылки могут используйте другое соглашение для осей).

По определению, запись \(i, j\) в матрице ошибок - это количество наблюдений, фактически находящихся в группе \(i\), но по прогнозу находящихся в группе \(j\). Вот пример:

>>> from sklearn.metrics import confusion_matrix
>>> y_true = [2, 0, 2, 2, 0, 1]
>>> y_pred = [0, 0, 2, 2, 0, 2]
>>> confusion_matrix(y_true, y_pred)
array([[2, 0, 0],
       [0, 0, 1],
       [1, 0, 2]])

ConfusionMatrixDisplay можно использовать для визуального представления матрицы ошибок, как показано в примере Confusion matrix, который создает следующую фигуру:

../_images/sphx_glr_plot_confusion_matrix_001.png

Параметр normalize позволяет сообщать о соотношениях вместо количества. Матрицу ошибок можно нормализовать тремя различными способами: 'pred', 'true' и 'all', которые будут делить значения на сумму каждого столбца, строки или всю матрицу соответственно.

>>> y_true = [0, 0, 0, 1, 1, 1, 1, 1]
>>> y_pred = [0, 1, 0, 1, 0, 1, 0, 1]
>>> confusion_matrix(y_true, y_pred, normalize='all')
array([[0.25 , 0.125],
       [0.25 , 0.375]])

Для бинарных задач мы можем получить количество истинных отрицательных (true negatives), ложных положительных (false positives), ложных отрицательных (false negatives) и истинных положительных (true positives) результатов следующим образом:

>>> y_true = [0, 0, 0, 1, 1, 1, 1, 1]
>>> y_pred = [0, 1, 0, 1, 0, 1, 0, 1]
>>> tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
>>> tn, fp, fn, tp
(2, 1, 2, 3)

3.3.2.7. Отчет о классификации

Функция classification_report создает текстовый отчет, показывающий основные метрики классификации. Вот небольшой пример с пользовательскими target_names и выведенными метками:

>>> from sklearn.metrics import classification_report
>>> y_true = [0, 1, 2, 2, 0]
>>> y_pred = [0, 0, 2, 1, 0]
>>> target_names = ['class 0', 'class 1', 'class 2']
>>> print(classification_report(y_true, y_pred, target_names=target_names))
              precision    recall  f1-score   support

     class 0       0.67      1.00      0.80         2
     class 1       0.00      0.00      0.00         1
     class 2       1.00      0.50      0.67         2

    accuracy                           0.60         5
   macro avg       0.56      0.50      0.49         5
weighted avg       0.67      0.60      0.59         5

3.3.2.8. Потеря Хэмминга (Hamming loss)

Функция hamming_loss вычисляет средние потери Хэмминга или Расстояние Хэмминга между двумя наборами выборок.

Если \(\hat{y}_{i,j}\) является предсказанным значением для \(j\)-й метки данного образца \(i\), \(y_ {i,j}\) - соответствующее истинное значение, \(n_\text{samples}\) - количество выборок и \(n_\text{labels}\) - количество меток, затем потери Хэмминга. \(L_{Hamming}\) определяется как:

\[L_{Hamming}(y, \hat{y}) = \frac{1}{n_\text{samples} * n_\text{labels}} \sum_{i=0}^{n_\text{samples}-1} \sum_{j=0}^{n_\text{labels} - 1} 1(\hat{y}_{i,j} \not= y_{i,j})\]

где \(1(x)\) - это индикатор.

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

>>> from sklearn.metrics import hamming_loss
>>> y_pred = [1, 2, 3, 4]
>>> y_true = [2, 2, 3, 4]
>>> hamming_loss(y_true, y_pred)
0.25

В случае с несколькими метками и индикаторами двоичных меток:

>>> hamming_loss(np.array([[0, 1], [1, 1]]), np.zeros((2, 2)))
0.75

Примечание

В мультиклассовой классификации потери Хэмминга соответствуют расстоянию Хэмминга между y_true и y_pred, что аналогично функции 0-1 функция потерь (zero-one loss). Однако, в то время как потеря нуля и единицы штрафуют наборы предсказаний, которые не строго соответствуют истинным наборам, потеря Хэмминга наказывает отдельные метки. Таким образом, потери Хэмминга, ограниченные сверху потерями ноль-единица, всегда находятся между нулем и единицей включительно; и прогнозирование правильного подмножества или надмножества истинных меток даст потерю Хэмминга от нуля до единицы, исключая.

3.3.2.9. Точность (precision), полнота (recall) и F-меры

Интуитивно, точность (precision) - это способность классификатора не помечать как положительный образец, который является отрицательным, и полнота (recall) - это способность классификатора находить все положительные образцы.

F-мера (\(F_\beta\) и \(F_1\)) можно интерпретировать как средневзвешенное гармоническое значение точности и полноты. Показатель \(F_\beta\) достигает наилучшего значения при 1 и худшего результата при 0. При \(\beta = 1\), \(F_\beta\) и \(F_1\) эквивалентны, а точность и полнота одинаково важны.

precision_recall_curve вычисляет кривую точности-полноты на основе реального значения метки и оценки, полученной классификатором, путем изменения порога принятия решения.

Функция average_precision_score вычисляет Среднюю Точность (Average Precision) (AP) на основе оценок прогноза. Значение находится между 0 и 1, чем выше, тем лучше. AP определяется как

\[\text{AP} = \sum_n (R_n - R_{n-1}) P_n\]

где \(P_n\) и \(R_n\) - точность и полнота на n-м пороге. При случайных прогнозах AP представляет собой долю положительных образцов.

В ссылках [Manning2008] и [Everingham2010] представлены альтернативные варианты AP, которые интерполируют кривую точности-полноты. В настоящее время average_precision_score не реализует какой-либо интерполированный вариант. В ссылках [Davis2006] и [Flach2015] описывается, почему линейная интерполяция точек на кривой точности-полноты обеспечивает слишком оптимистичные оценки классификатора. Эта линейная интерполяция используется при вычислении площади под кривой с помощью правила трапеций в auc.

Несколько функций позволяют анализировать точность, полноту и оценку F-мер:

average_precision_score(y_true, y_score, *)

Compute average precision (AP) from prediction scores.

f1_score(y_true, y_pred, *[, labels, ...])

Compute the F1 score, also known as balanced F-score or F-measure.

fbeta_score(y_true, y_pred, *, beta[, ...])

Compute the F-beta score.

precision_recall_curve(y_true, probas_pred, *)

Compute precision-recall pairs for different probability thresholds.

precision_recall_fscore_support(y_true, ...)

Compute precision, recall, F-measure and support for each class.

precision_score(y_true, y_pred, *[, labels, ...])

Compute the precision.

recall_score(y_true, y_pred, *[, labels, ...])

Compute the recall.

class score in a One-vs-the-rest (OvR) fashion and averaging them or not depending of its average argument value.

Обратите внимание, что функция precision_recall_curve ограничена двоичным случаем. Функция average_precision_score поддерживает форматы с несколькими классами и несколькими метками, вычисляя оценку каждого класса по принципу “один против остальных” (One-vs-the-rest - OvR) и усредняя их или нет, в зависимости от значения аргумента average.

Функции PrecisionRecallDisplay.from_estimator и PrecisionRecallDisplay.from_predictions построят кривую точности-полноты следующим образом.

../_images/sphx_glr_plot_precision_recall_001.png

3.3.2.9.1. Бинарная классификация

В задаче бинарной классификации термины положительный (positive) и отрицательный (negative) относятся к предсказанию классификатора, а термины истина (true) и ложь (false) относятся к тому, соответствует ли этот прогноз истинным значениям (иногда называемое наблюдением). Учитывая эти определения, можно сформулировать следующую таблицу:

Actual class (Наблюдение)

Predicted class (Ожидание)

tp (true positive) Правильный результат

fp (false positive) Неожиданный результат

fn (false negative) Отсутствует результат

tn (true negative) Правильное отсутствие результата

В этом контексте мы можем определить понятия точности и полноты:

\[\text{precision} = \frac{\text{tp}}{\text{tp} + \text{fp}},\]
\[\text{recall} = \frac{\text{tp}}{\text{tp} + \text{fn}},\]

(Иногда полноту также называют “чувствительностью”).

F-мера - это взвешенное гармоническое среднее точности и полноты, причем вклад точности в среднее значение взвешивается по некоторому параметру \(\beta\):

\[F_\beta = (1 + \beta^2) \frac{\text{precision} \times \text{recall}}{\beta^2 \text{precision} + \text{recall}}\]

Чтобы избежать деления на ноль, когда точность и полнота равны нулю, Scikit-Learn вычисляет F-меру по следующей эквивалентной в остальном формуле:

\[F_\beta = \frac{(1 + \beta^2) \text{tp}}{(1 + \beta^2) \text{tp} + \text{fp} + \beta^2 \text{fn}}\]

Обратите внимание, что эта формула по-прежнему не определена, если нет истинно-положительных (TP - true positives), ложно-положительных (FP - false positives) или ложно-отрицательных (FN - false negatives) результатов. По умолчанию F-1 для набора исключительно истинных отрицательных значений рассчитывается как 0, однако это поведение можно изменить с помощью параметра zero_division. Вот несколько небольших примеров бинарной классификации:

>>> from sklearn import metrics
>>> y_pred = [0, 1, 0, 0]
>>> y_true = [0, 1, 0, 1]
>>> metrics.precision_score(y_true, y_pred)
1.0
>>> metrics.recall_score(y_true, y_pred)
0.5
>>> metrics.f1_score(y_true, y_pred)
0.66...
>>> metrics.fbeta_score(y_true, y_pred, beta=0.5)
0.83...
>>> metrics.fbeta_score(y_true, y_pred, beta=1)
0.66...
>>> metrics.fbeta_score(y_true, y_pred, beta=2)
0.55...
>>> metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5)
(array([0.66..., 1.        ]), array([1. , 0.5]), array([0.71..., 0.83...]), array([2, 2]))
>>> import numpy as np
>>> from sklearn.metrics import precision_recall_curve
>>> from sklearn.metrics import average_precision_score
>>> y_true = np.array([0, 0, 1, 1])
>>> y_scores = np.array([0.1, 0.4, 0.35, 0.8])
>>> precision, recall, threshold = precision_recall_curve(y_true, y_scores)
>>> precision
array([0.5       , 0.66..., 0.5       , 1.        , 1.        ])
>>> recall
array([1. , 1. , 0.5, 0.5, 0. ])
>>> threshold
array([0.1 , 0.35, 0.4 , 0.8 ])
>>> average_precision_score(y_true, y_scores)
0.83...

3.3.2.9.2. Классификация по нескольким классам и по нескольким меткам.

В задаче классификации с несколькими классами и несколькими метками понятия точности, полноты и F-меры могут применяться к каждой метке независимо. Существует несколько способов объединения результатов по меткам, заданным аргументом average для average_precision_score, f1_score, fbeta_score, precision_recall_fscore_support, функции precision_score и recall_score, как описано above.

Обратите внимание, что если включены все метки, “микро”-усреднение в многоклассовой настройке даст точность, полноту и \(F\), которые идентичны accuracy. Также обратите внимание, что “взвешенное” усреднение может дать F-показатель, который не находится между точностью и полнотой.

Чтобы сделать это более понятным, рассмотрим следующее обозначение:

  • \(y\) the set of true \((sample, label)\) pairs

  • \(\hat{y}\) the set of predicted \((sample, label)\) pairs

  • \(L\) the set of labels

  • \(S\) the set of samples

  • \(y_s\) the subset of \(y\) with sample \(s\), i.e. \(y_s := \left\{(s', l) \in y | s' = s\right\}\)

  • \(y_l\) the subset of \(y\) with label \(l\)

  • similarly, \(\hat{y}_s\) and \(\hat{y}_l\) are subsets of \(\hat{y}\)

  • \(P(A, B) := \frac{\left| A \cap B \right|}{\left|B\right|}\) for some sets \(A\) and \(B\)

  • \(R(A, B) := \frac{\left| A \cap B \right|}{\left|A\right|}\) (Conventions vary on handling \(A = \emptyset\); this implementation uses \(R(A, B):=0\), and similar for \(P\).)

  • \(F_\beta(A, B) := \left(1 + \beta^2\right) \frac{P(A, B) \times R(A, B)}{\beta^2 P(A, B) + R(A, B)}\)

Тогда метрики определяются как:

average

Precision

Recall

F_beta

"micro"

\(P(y, \hat{y})\)

\(R(y, \hat{y})\)

\(F_\beta(y, \hat{y})\)

"samples"

\(\frac{1}{\left|S\right|} \sum_{s \in S} P(y_s, \hat{y}_s)\)

\(\frac{1}{\left|S\right|} \sum_{s \in S} R(y_s, \hat{y}_s)\)

\(\frac{1}{\left|S\right|} \sum_{s \in S} F_\beta(y_s, \hat{y}_s)\)

"macro"

\(\frac{1}{\left|L\right|} \sum_{l \in L} P(y_l, \hat{y}_l)\)

\(\frac{1}{\left|L\right|} \sum_{l \in L} R(y_l, \hat{y}_l)\)

\(\frac{1}{\left|L\right|} \sum_{l \in L} F_\beta(y_l, \hat{y}_l)\)

"weighted"

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| P(y_l, \hat{y}_l)\)

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| R(y_l, \hat{y}_l)\)

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| F_\beta(y_l, \hat{y}_l)\)

None

\(\langle P(y_l, \hat{y}_l) | l \in L \rangle\)

\(\langle R(y_l, \hat{y}_l) | l \in L \rangle\)

\(\langle F_\beta(y_l, \hat{y}_l) | l \in L \rangle\)

>>> from sklearn import metrics
>>> y_true = [0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 2, 1, 0, 0, 1]
>>> metrics.precision_score(y_true, y_pred, average='macro')
0.22...
>>> metrics.recall_score(y_true, y_pred, average='micro')
0.33...
>>> metrics.f1_score(y_true, y_pred, average='weighted')
0.26...
>>> metrics.fbeta_score(y_true, y_pred, average='macro', beta=0.5)
0.23...
>>> metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5, average=None)
(array([0.66..., 0.        , 0.        ]), array([1., 0., 0.]), array([0.71..., 0.        , 0.        ]), array([2, 2, 2]...))

Для мультиклассовой классификации с “отрицательным классом” можно исключить некоторые метки:

>>> metrics.recall_score(y_true, y_pred, labels=[1, 2], average='micro')
... # excluding 0, no labels were correctly recalled
0.0

Точно так же метки, отсутствующие в выборке данных, могут быть учтены при макроусреднении.

>>> metrics.precision_score(y_true, y_pred, labels=[0, 1, 2, 3], average='macro')
0.166...

3.3.2.10. Оценка коэффициента сходства Жаккара.

Функция jaccard_score вычисляет среднее значение коэффициентов сходства Жаккара, также называемых индексом Жаккара, между парами наборов меток.

Коэффициент сходства Жаккара с набором основных истинностных меток \(y\) и предсказанным набором меток \(\hat{y}\) определяется как

\[J(y, \hat{y}) = \frac{|y \cap \hat{y}|}{|y \cup \hat{y}|}.\]

jaccard_score (например, precision_recall_fscore_support) изначально применяется к двоичным меткам. Вычислив его по множествам, его можно расширить для применения к нескольким метками и мультиклассам с помощью “среднего” (см. above).

В двоичном случае:

>>> import numpy as np
>>> from sklearn.metrics import jaccard_score
>>> y_true = np.array([[0, 1, 1],
...                    [1, 1, 0]])
>>> y_pred = np.array([[1, 1, 1],
...                    [1, 0, 0]])
>>> jaccard_score(y_true[0], y_pred[0])
0.6666...

В случае 2D-сравнения (например, сходство изображений):

>>> jaccard_score(y_true, y_pred, average="micro")
0.6

В случае с несколькими метками и индикаторами двоичных меток:

>>> jaccard_score(y_true, y_pred, average='samples')
0.5833...
>>> jaccard_score(y_true, y_pred, average='macro')
0.6666...
>>> jaccard_score(y_true, y_pred, average=None)
array([0.5, 0.5, 1. ])

Проблемы с несколькими классами преобразуются в бинарную форму и обрабатываются как соответствующая проблема с несколькими метками:

>>> y_pred = [0, 2, 1, 2]
>>> y_true = [0, 1, 2, 2]
>>> jaccard_score(y_true, y_pred, average=None)
array([1. , 0. , 0.33...])
>>> jaccard_score(y_true, y_pred, average='macro')
0.44...
>>> jaccard_score(y_true, y_pred, average='micro')
0.33...

3.3.2.11. Шарнирная потеря (Hinge loss)

Функция hinge_loss вычисляет среднее расстояние между моделью и данными, используя hinge loss, одностороннюю метрику, которая учитывает только ошибки прогнозирования. (Шарнирная потеря используется в классификаторах максимального запаса, таких как Метод опорных векторов.)

Если истинная метка \(y_i\) задачи двоичной классификации закодирована как \(y_i=\left\{-1, +1\right\}\) для каждого образца \(i\); и \(w_i\) - соответствующее прогнозируемое решение (массив формы (n_samples,) в виде вывода метода decision_function), тогда потери шарнира определяются как:

\[L_\text{Hinge}(y, w) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \max\left\{1 - w_i y_i, 0\right\}\]

Если меток более двух, hinge_loss использует мультиклассовый вариант, предложенный Crammer & Singer. тут документ, описывающий это.

В этом случае прогнозируемое решение представляет собой массив формы (n_samples, n_labels). Если \(w_{i, y_i}\) является предсказанным решением для истинной метки \(y_i\) \(i\)-й выборки; и \(\hat{w}_{i, y_i} = \max\left\{w_{i, y_j}~|~y_j \ne y_i \right\}\) - максимальное из предсказанных решений для всех других меток, то потери на шарнирах нескольких классов определяются следующим образом:

\[L_\text{Hinge}(y, w) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \max\left\{1 + \hat{w}_{i, y_i} - w_{i, y_i}, 0\right\}\]

Вот небольшой пример, демонстрирующий использование функции hinge_loss с классификатором svm в задаче двоичного класса:

>>> from sklearn import svm
>>> from sklearn.metrics import hinge_loss
>>> X = [[0], [1]]
>>> y = [-1, 1]
>>> est = svm.LinearSVC(dual="auto", random_state=0)
>>> est.fit(X, y)
LinearSVC(dual='auto', random_state=0)
>>> pred_decision = est.decision_function([[-2], [3], [0.5]])
>>> pred_decision
array([-2.18...,  2.36...,  0.09...])
>>> hinge_loss([-1, 1, 1], pred_decision)
0.3...

Вот пример, демонстрирующий использование функции hinge_loss с классификатором svm в многоклассовой задаче:

>>> X = np.array([[0], [1], [2], [3]])
>>> Y = np.array([0, 1, 2, 3])
>>> labels = np.array([0, 1, 2, 3])
>>> est = svm.LinearSVC(dual="auto")
>>> est.fit(X, Y)
LinearSVC(dual='auto')
>>> pred_decision = est.decision_function([[-1], [2], [3]])
>>> y_true = [0, 2, 3]
>>> hinge_loss(y_true, pred_decision, labels=labels)
0.56...

3.3.2.12. Log loss

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

Для двоичной классификации с истинной меткой \(y \in \{0,1\}\) и оценкой вероятности \(p = \operatorname{Pr}(y = 1)\), Log loss на выборка - это отрицательное логарифмическое правдоподобие классификатора с учетом истинной метки:

\[L_{\log}(y, p) = -\log \operatorname{Pr}(y|p) = -(y \log (p) + (1 - y) \log (1 - p))\]

Это распространяется на случай мультиклассов следующим образом. Пусть истинные метки для набора выборок закодированы как матрица двоичного индикатора 1 из K \(Y\), т. е. \(y_{i,k} = 1\), если выборка \(i ` имеет метку :math:`k\), взятую из набора меток \(K\). Пусть \(P\) - матрица оценок вероятности, где \(p_{i,k} = \operatorname{Pr}(y_{i,k} = 1)\). Тогда Log loss всего набора равен

\[L_{\log}(Y, P) = -\log \operatorname{Pr}(Y|P) = - \frac{1}{N} \sum_{i=0}^{N-1} \sum_{k=0}^{K-1} y_{i,k} \log p_{i,k}\]

Чтобы увидеть, как это обобщает приведенную выше двоичный Log loss, обратите внимание, что в двоичном случае \(p_{i,0} = 1 - p_{i,1}\) и \(y_{i, 0} = 1 - y_{i,1}\), поэтому расширение внутренней суммы по \(y_{i,k} \in \{0,1\}\) дает двоичный Log loss.

Функция log_loss вычисляет Log loss по списку основных меток и матрице вероятности, возвращаемой методом модели predict_proba.

>>> from sklearn.metrics import log_loss
>>> y_true = [0, 0, 1, 1]
>>> y_pred = [[.9, .1], [.8, .2], [.3, .7], [.01, .99]]
>>> log_loss(y_true, y_pred)
0.1738...

Первое [.9, .1] в y_pred обозначает 90% вероятность того, что первая выборка имеет метку 0. Log loss неотрицательный.

3.3.2.13. Коэффициент корреляции Мэтьюза (Matthews correlation coefficient - MCC)

Функция matthews_corrcoef вычисляет коэффициент корреляции Мэтью (MCC) для двоичных классов. Цитата из Википедии:

“Коэффициент корреляции Мэтьюза используется в машинном обучении как мера качества бинарных (двухклассовых) классификаций. Он учитывает истинные и ложные положительные и отрицательные результаты и обычно рассматривается как сбалансированная мера, которую можно использовать даже если классы имеют очень разные размеры. MCC, по сути, представляет собой значение коэффициента корреляции между -1 и +1. Коэффициент +1 представляет собой идеальный прогноз, 0 - средний случайный прогноз, а -1 - обратный прогноз. также известный как коэффициент фи”.

В двоичном (двухклассовом) случае \(tp\), \(tn\), \(fp\) и \(fn\) представляют собой соответственно количество истинно-положительных значений (TP - true positives), истинно-отрицательных значений (TN - true negatives), ложно-положительных (FP - false positives) и ложно-отрицательных (FN - false negatives) значение, MCC определяется как

\[MCC = \frac{tp \times tn - fp \times fn}{\sqrt{(tp + fp)(tp + fn)(tn + fp)(tn + fn)}}.\]

В случае мультиклассовой классификации коэффициент корреляции Мэтьюза может быть определен в терминах confusion_matrix \(C\) для классов \(K\).

Чтобы упростить определение, рассмотрим следующие промежуточные переменные:

  • \(t_k=\sum_{i}^{K} C_{ik}\) сколько раз класс \(k\) действительно произошло,

  • \(p_k=\sum_{i}^{K} C_{ki}\) сколько раз класс \(k\) был предсказан,

  • \(c=\sum_{k}^{K} C_{kk}\) общее количество правильно предсказанных образцов,

  • \(s=\sum_{i}^{K} \sum_{j}^{K} C_{ij}\) общее количество образцов.

Тогда мультиклассовый MCC определяется как:

\[MCC = \frac{ c \times s - \sum_{k}^{K} p_k \times t_k }{\sqrt{ (s^2 - \sum_{k}^{K} p_k^2) \times (s^2 - \sum_{k}^{K} t_k^2) }}\]

При наличии более двух меток значение MCC больше не будет находиться в диапазоне от -1 до +1. Вместо этого минимальное значение будет где-то между -1 и 0 в зависимости от количества и распределения основных истинных меток. Максимальное значение всегда +1.

Вот небольшой пример, иллюстрирующий использование функции matthews_corrcoef:

>>> from sklearn.metrics import matthews_corrcoef
>>> y_true = [+1, +1, +1, -1]
>>> y_pred = [+1, -1, +1, +1]
>>> matthews_corrcoef(y_true, y_pred)
-0.33...

3.3.2.14. Матрица ошибок с несколькими метками (Multi-label confusion matrix)

Функция multilabel_confusion_matrix вычисляет по классам (по умолчанию) или по выборке (samplewise=True) матрицу ошибок с несколькими метками для оценки точности классификации. multilabel_confusion_matrix также обрабатывает мультиклассовые данные так, как если бы они были с несколькими метками, поскольку это преобразование обычно применяется для оценки многоклассовых проблем с помощью метрик двоичной классификации (таких как точность, полнота и т. д.).

При вычислении матрицы ошибок с несколькими метками по классам \(C\) количество истинных отрицательных значений для класса \(i\) равно \(C_{i,0,0}\), ложных отрицательных значений равно \(C_{i,1,0}\), истинные положительные результаты - это \(C_{i,1,1}\), а ложные положительные - это \(C_{i,0,1}\).

Вот пример, демонстрирующий использование функции multilabel_confusion_matrix с входными данными multilabel indicator matrix:

>>> import numpy as np
>>> from sklearn.metrics import multilabel_confusion_matrix
>>> y_true = np.array([[1, 0, 1],
...                    [0, 1, 0]])
>>> y_pred = np.array([[1, 0, 0],
...                    [0, 1, 1]])
>>> multilabel_confusion_matrix(y_true, y_pred)
array([[[1, 0],
        [0, 1]],

       [[1, 0],
        [0, 1]],

       [[0, 1],
        [1, 0]]])

Или можно построить матрицу ошибок для меток каждого образца:

>>> multilabel_confusion_matrix(y_true, y_pred, samplewise=True)
array([[[1, 0],
        [1, 1]],

       [[1, 1],
        [0, 1]]])

Вот пример, демонстрирующий использование функции multilabel_confusion_matrix с вводом multiclass:

>>> y_true = ["cat", "ant", "cat", "cat", "ant", "bird"]
>>> y_pred = ["ant", "ant", "cat", "cat", "ant", "cat"]
>>> multilabel_confusion_matrix(y_true, y_pred,
...                             labels=["ant", "bird", "cat"])
array([[[3, 1],
        [0, 2]],

       [[5, 0],
        [1, 0]],

       [[2, 1],
        [1, 2]]])

Вот несколько примеров, демонстрирующих использование функции multilabel_confusion_matrix для расчета полноты (или чувствительности - recall), специфичности, частоты выпадений и ошибок для каждого класса в задаче классифкации нескольких меток.

Вычисление recall (также называемый истинно положительным показателем - true positive rate или чувствительностью) для каждого класса:

>>> y_true = np.array([[0, 0, 1],
...                    [0, 1, 0],
...                    [1, 1, 0]])
>>> y_pred = np.array([[0, 1, 0],
...                    [0, 0, 1],
...                    [1, 1, 0]])
>>> mcm = multilabel_confusion_matrix(y_true, y_pred)
>>> tn = mcm[:, 0, 0]
>>> tp = mcm[:, 1, 1]
>>> fn = mcm[:, 1, 0]
>>> fp = mcm[:, 0, 1]
>>> tp / (tp + fn)
array([1. , 0.5, 0. ])

Расчет specificity (также называемый истинно отрицательным коэффициентом - true negative rate) для каждого класса:

>>> tn / (tn + fp)
array([1. , 0. , 0.5])

Calculating fall out (также называемый ложноположительным коэффициентом - false positive rate) для каждого класса:

>>> fp / (fp + tn)
array([0. , 1. , 0.5])

Calculating miss rate (также называемый ложноотрицательным коэффициентом - false negative rate) для каждого класса:

>>> fn / (fn + tp)
array([0. , 0.5, 1. ])

3.3.2.15. Рабочая характеристика приемника (Receiver operating characteristic - ROC)

The function roc_curve computes the ROC-кривая (англ. receiver operating characteristic, рабочая характеристика приёмника). Цитата из Википедии :

“Рабочая характеристика приемника (ROC), или ROC-кривая, -график, позволяющий оценить качество бинарной классификации, отображает соотношение между долей объектов от общего количества носителей признака, верно классифицированных как несущие признак (англ. true positive rate, TPR, называемой чувствительностью алгоритма классификации), и долей объектов от общего количества объектов, не несущих признака, ошибочно классифицированных как несущие признак (англ. false positive rate, FPR, величина 1-FPR называется специфичностью алгоритма классификации) при варьировании порога решающего правила.”

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

>>> import numpy as np
>>> from sklearn.metrics import roc_curve
>>> y = np.array([1, 1, 2, 2])
>>> scores = np.array([0.1, 0.4, 0.35, 0.8])
>>> fpr, tpr, thresholds = roc_curve(y, scores, pos_label=2)
>>> fpr
array([0. , 0. , 0.5, 0.5, 1. ])
>>> tpr
array([0. , 0.5, 0.5, 1. , 1. ])
>>> thresholds
array([ inf, 0.8 , 0.4 , 0.35, 0.1 ])

По сравнению с такими метриками, как accuracy подмножества, потеря Хэмминга или F1 мера, ROC не требует оптимизации порога для каждой метки.

Функция roc_auc_score, обозначаемая ROC-AUC или AUROC, вычисляет площадь под кривой ROC. При этом информация о кривой суммируется в одно число.

На следующем рисунке показаны кривая ROC и показатель ROC-AUC для классификатора, призванного отличить цветок вирджинии от остальных видов в Iris plants dataset:

../_images/sphx_glr_plot_roc_001.png

Для получения дополнительной информации см. ROC-кривая.

3.3.2.15.1. Двоичный случай

В двоичном случае вы можете либо предоставить оценки вероятности, используя метод classifier.predict_proba(), либо непороговые значения решения, заданные методом classifier.decision_function(). В случае предоставления оценок вероятности должна быть указана вероятность класса с “большей меткой”. “Большая метка” соответствует classifier.classes_[1] и, cоответственно, classifier.predict_proba(X)[:, 1]. Следовательно, параметр y_score имеет размер (n_samples,).

>>> from sklearn.datasets import load_breast_cancer
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.metrics import roc_auc_score
>>> X, y = load_breast_cancer(return_X_y=True)
>>> clf = LogisticRegression(solver="liblinear").fit(X, y)
>>> clf.classes_
array([0, 1])

Мы можем использовать оценки вероятности, соответствующие clf.classes_[1].

>>> y_score = clf.predict_proba(X)[:, 1]
>>> roc_auc_score(y, y_score)
0.99...

В противном случае мы можем использовать непороговые значения решения.

>>> roc_auc_score(y, clf.decision_function(X))
0.99...

3.3.2.15.2. Многоклассовый случай

Функцию roc_auc_score также можно использовать в многоклассовой классификации. В настоящее время поддерживаются две стратегии усреднения: алгоритм “один против одного” (one-vs-one - OvO) вычисляет среднее значение парных метрик ROC AUC, а алгоритм “один против остальных” (one-vs-rest - OvR) вычисляет среднее значение метрик ROC AUC для каждого класса по сравнению со всеми остальными классами. В обоих случаях предсказанные метки предоставляются в массиве со значениями от 0 до n_classes, а оценки соответствуют оценкам вероятности принадлежности выборки к определенному классу. Алгоритмы OvO и OvR поддерживают равномерное взвешивание (average='macro') и по распространенности (average='weighted').

Алгоритм “один против один”: вычисляет среднее значение AUC для всех возможных парных комбинаций классов. [HT2001] определяет мультиклассовую метрику AUC, взвешенную равномерно:

\[\frac{1}{c(c-1)}\sum_{j=1}^{c}\sum_{k > j}^c (\text{AUC}(j | k) + \text{AUC}(k | j))\]

где \(c\) - количество классов, а \(\text{AUC}(j | k)\) - это AUC с классом \(j\) как положительный класс и класс \(k\) как отрицательный. В общем случае \(\text{AUC}(j | k) \neq \text{AUC}(k | j))\) в многоклассовом случае. Этот алгоритм используется путем установки аргумента ключевого слова multiclass в 'ovo' и average в 'macro'.

Многоклассовая метрика AUC [HT2001] может быть расширена для взвешивания по распространенности:

\[\frac{1}{c(c-1)}\sum_{j=1}^{c}\sum_{k > j}^c p(j \cup k)( \text{AUC}(j | k) + \text{AUC}(k | j))\]

где \(c\) - количество классов. Этот алгоритм используется путем установки аргумента ключевого слова multiclass в 'ovo' и average в weighted'. Опция 'weighted' возвращает средневзвешенное значение распространенности, как описано в [FC2009].

Алгоритм “один против остальных”: вычисляет AUC каждого класса относительно остальных [PD2000]. Алгоритм функционально такой же, как и в случае с несколькими метками. Чтобы включить этот алгоритм, установите аргумент ключевого слова multiclass в 'ovr'. В дополнение к 'macro' [F2006] и 'weighted' [F2001] усреднению, OvR поддерживает 'micro' усреднение.

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

На следующем рисунке показана микроусредненная кривая ROC и соответствующий ей показатель ROC-AUC для классификатора, предназначенного для определения различных видов в Iris plants dataset:

../_images/sphx_glr_plot_roc_002.png

3.3.2.15.3. Случай с несколькими метками

В классификации по нескольким меткам функция roc_auc_score расширяется за счет усреднения по меткам как above. В этом случае вам следует предоставить y_score формы (n_samples, n_classes). Таким образом, при использовании оценок вероятности необходимо для каждого выхода выбирать вероятность класса с большей меткой.

>>> from sklearn.datasets import make_multilabel_classification
>>> from sklearn.multioutput import MultiOutputClassifier
>>> X, y = make_multilabel_classification(random_state=0)
>>> inner_clf = LogisticRegression(solver="liblinear", random_state=0)
>>> clf = MultiOutputClassifier(inner_clf).fit(X, y)
>>> y_score = np.transpose([y_pred[:, 1] for y_pred in clf.predict_proba(X)])
>>> roc_auc_score(y, y_score, average=None)
array([0.82..., 0.86..., 0.94..., 0.85... , 0.94...])

И значения решения не требуют такой обработки.

>>> from sklearn.linear_model import RidgeClassifierCV
>>> clf = RidgeClassifierCV().fit(X, y)
>>> y_score = clf.decision_function(X)
>>> roc_auc_score(y, y_score, average=None)
array([0.81..., 0.84... , 0.93..., 0.87..., 0.94...])

3.3.2.16. Компромисс ошибки обнаружения (Detection error tradeoff - DET)

Функция det_curve вычисляет кривую компромиссной кривой ошибки обнаружения (DET) (так же называемой - параметрической кривой ошибок (Detection Error Tradeoff, DET-curve)) [WikipediaDET2017]. Цитирую Википедию:

“График компромисса ошибок обнаружения (DET) представляет собой график частоты ошибок для систем двоичной классификации, показывающий процент ложных отклонений в сравнении с процентом ложных срабатываний. Оси X и Y масштабируются нелинейно по их стандартным нормальным отклонениям (или просто путем логарифмического преобразования), что дает компромиссные кривые (tradeoff curve), которые более линейны, чем кривые ROC, и используют большую часть области изображения, чтобы выделить важные различия в критической рабочей области”.

Кривые DET представляют собой разновидность кривых рабочих характеристик приемника (ROC), где на оси Y отображается ложно-отрицательный коэффицент (False Negative Rate) вместо истинно-положительного коэффицента (True Positive Rate).

Кривые DET обычно строятся в масштабе нормального отклонения путем преобразования с помощью \(\phi^{-1}\) (где \(\phi\) является кумулятивной функцией распределения).

Полученные кривые явно визуализируют соотношение типов ошибок для данных алгоритмов классификации. См. [Martin1997] для примеров и дополнительного изучения.

На этом рисунке сравниваются кривые ROC и DET двух примеров классификаторов при выполнении одной и той же задачи классификации:

../_images/sphx_glr_plot_det_001.png

Свойства:

  • Кривые DET образуют линейную кривую в масштабе нормального отклонения, если показатели обнаружения распределены нормально (или близко к нормальному). [Navratil2007] было показано, что обратное не обязательно верно и даже более общие распределения способны создавать линейные кривые DET.

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

  • Поскольку ложноотрицательный коэффициент является “обратным” истинно положительному коэффициенту, точкой совершенства для кривых DET является начало координат (в отличие от верхнего левого угла для кривых ROC).

Приложения и ограничения:

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

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

Это особенно полезно, если требуется сравнение типов ошибок.

С другой стороны, кривые DET не представляют свою метрику в виде одного числа.

Поэтому для автоматической оценки или сравнения с другими задачами классификации лучше подходят такие показатели, как производная площадь под кривой ROC.

3.3.2.17. 0-1 функция потерь (zero-one loss)

Функция zero_one_loss вычисляет сумму или среднее значение потерь классификации 0–1 (\(L_{0-1}\)) по \(n_{\text{samples}}\)

По умолчанию функция нормализует выборку. Чтобы получить сумму \(L_{0-1}\), установите для normalize значение False.

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

По умолчанию функция возвращает процент несовершенно предсказанных подмножеств (imperfectly predicted subsets). Чтобы вместо этого получить количество таких подмножеств, установите для normalize значение False.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то потеря 0-1 \(L_{0-1}\) определяется как:

\[L_{0-1}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} 1(\hat{y}_i \not= y_i)\]

где \(1(x)\) - это индикатор. 0-1 функцию потерь также можно рассчитать как \(zero-one loss = 1 - accuracy\).

>>> from sklearn.metrics import zero_one_loss
>>> y_pred = [1, 2, 3, 4]
>>> y_true = [2, 2, 3, 4]
>>> zero_one_loss(y_true, y_pred)
0.25
>>> zero_one_loss(y_true, y_pred, normalize=False)
1.0

В случае с несколькими метками и индикаторами двоичных меток, где первый набор меток [0,1] содержит ошибку:

>>> zero_one_loss(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
0.5
>>> zero_one_loss(np.array([[0, 1], [1, 1]]), np.ones((2, 2)),  normalize=False)
1.0

3.3.2.18. Потеря оценки Брайера (Brier score loss)

Функция brier_score_loss вычисляет Оценку Брайера для бинарных классов [Brier1950]. Цитирую Википедию:

“Оценка Брайера - это правильная функция оценки, которая измеряет точность (accuracy) вероятностных прогнозов. Она применима к задачам, в которых прогнозы должны назначать вероятности набору взаимоисключающих дискретных результатов”.

Эта функция возвращает среднеквадратическую ошибку фактического результата \(y \in \{0,1\}\) и прогнозируемую оценку вероятности \(p = \operatorname{Pr}(y = 1)\) (predict_proba) выражается как:

\[BS = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1}(y_i - p_i)^2\]

Потеря оценки Брайера также находится в диапазоне от 0 до 1, и чем ниже значение (меньше среднеквадратическая разница), тем точнее прогноз.

Вот небольшой пример использования этой функции:

>>> import numpy as np
>>> from sklearn.metrics import brier_score_loss
>>> y_true = np.array([0, 1, 1, 0])
>>> y_true_categorical = np.array(["spam", "ham", "ham", "spam"])
>>> y_prob = np.array([0.1, 0.9, 0.8, 0.4])
>>> y_pred = np.array([0, 1, 1, 0])
>>> brier_score_loss(y_true, y_prob)
0.055
>>> brier_score_loss(y_true, 1 - y_prob, pos_label=0)
0.055
>>> brier_score_loss(y_true_categorical, y_prob, pos_label="ham")
0.055
>>> brier_score_loss(y_true, y_prob > 0.5)
0.0

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

Это связано с тем, что, по аналогии с разложением среднеквадратической ошибки на дисперсию смещения, потерю оценки Брайера можно разложить как сумму потерь калибровки и потерь уточнения [Bella2012].

Потери калибровки определяются как среднеквадратичное отклонение от эмпирических вероятностей, полученных на основе наклона сегментов ROC.

Потери уточнения можно определить как ожидаемые оптимальные потери, измеряемые площадью под кривой оптимальных затрат. Потери уточнения могут меняться независимо от потерь калибровки, поэтому более низкие потери по шкале Брайера не обязательно означают лучшую откалиброванную модель. “Only when refinement loss remains the same does a lower Brier score loss always mean better calibration” [Bella2012], [Flach2008].

“Только когда потери уточнения остаются прежними, более низкие потери по шкале Брайера всегда означают лучшую калибровку” [Bella2012], [Flach2008].

3.3.2.19. Отношения правдоподобия классов

Функция class_likelihood_ratios вычисляет положительные и отрицательные отношения правдоподобия \(LR_\pm\) для бинарных классов, которые могут быть интерпретированы как отношение шансов после теста к шансам до теста, как описано ниже.

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

Таким образом, \(LR_\pm\) метрики очень полезны в условиях, когда данные, доступные для изучения и оценки классификатора, представляют собой исследуемую совокупность с почти сбалансированными классами, например исследование случай-контроль (case-control), в то время как целевое приложение, то есть генеральная совокупность, имеет очень низкую распространенность.

Положительное отношение правдоподобия \(LR_+\) - это вероятность классификатора правильно предсказать принадлежность выборки к положительному классу, деленная на вероятность предсказания положительного класса для выборки, принадлежащей отрицательному классу

\[LR_+ = \frac{\text{PR}(P+|T+)}{\text{PR}(P+|T-)}.\]

Обозначение здесь относится к предсказанной (\(P\)) или истинной (\(T\)) метке, а знаки \(+\) и \(-\) относятся к положительному и отрицательному классу, соответственно, напр. \(P+\) означает “прогнозируемый положительный результат”.

Аналогично, отрицательное отношение правдоподобия \(LR_-\) - это вероятность того, что образец положительного класса будет классифицирован как принадлежащий к отрицательному классу, деленная на вероятность того, что образец отрицательного класса будет правильно классифицирован

\[LR_- = \frac{\text{PR}(P-|T+)}{\text{PR}(P-|T-)}.\]

Для классификаторов выше шанса \(LR_+\) выше 1 чем выше, тем лучше, а \(LR_-\) варьируется от 0 до 1 и чем ниже, тем лучше. Значения \(LR_\pm\approx 1\) соответствуют уровню вероятности.

Обратите внимание, что вероятности отличаются от подсчетов, например: \(\operatorname{PR}(P+|T+)\) не равен количеству истинных положительных отсчетов tp (см. страницу Википедии для реальных формул).

Интерпретация в зависимости от распространенности:

Оба отношения правдоподобия класса интерпретируются с точки зрения отношения шансов (предварительные и последующие тесты)

\[\text{post-test odds} = \text{Likelihood ratio} \times \text{pre-test odds}.\]

Шансы в целом связаны с вероятностями посредством

\[\text{odds} = \frac{\text{probability}}{1 - \text{probability}},\]

или эквивалентно

\[\text{probability} = \frac{\text{odds}}{1 + \text{odds}}.\]

Для данной популяции вероятность до тестирования определяется распространенностью.

Преобразуя шансы в вероятности, отношения правдоподобия можно перевести в вероятность истинной принадлежности к тому или иному классу до и после предсказания классификатора

\[\text{post-test odds} = \text{Likelihood ratio} \times \frac{\text{pre-test probability}}{1 - \text{pre-test probability}},\]
\[\text{post-test probability} = \frac{\text{post-test odds}}{1 + \text{post-test odds}}.\]

Математические расхождения:

Положительное отношение правдоподобия не определено, если \(fp = 0\), что можно интерпретировать как классификатор, идеально определяющий положительные случаи. Если \(fp = 0\) и дополнительно \(tp = 0\), это приводит к делению ноль/ноль. Это происходит, например, при использовании DummyClassifier, который всегда предсказывает отрицательный класс, и поэтому интерпретация как идеального классификатора теряется.

Отрицательное отношение правдоподобия не определено, если \(tn = 0\). Такое расхождение недопустимо, поскольку \(LR_- > 1\) будет указывать на увеличение шансов принадлежности образца к положительному классу после того, как он был классифицирован как отрицательный, как если бы классификатор вызвал положительное состояние. Это включает в себя случай DummyClassifier, который всегда предсказывает положительный класс (т.е. когда \(tn=fn=0\)).

Коэффициенты правдоподобия обоих классов не определены, если \(tp=fn=0\), что означает, что в тестовом наборе не было образцов положительного класса. Это также может произойти при перекрестной проверке сильно несбалансированных данных.

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

Подробную демонстрацию функции class_likelihood_ratios смотрите в примере ниже.

3.3.3. Метрики ранжирования по нескольким критериям

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

3.3.3.1. Ошибка покрытия

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

Примечание

Оценка нашей реализации на 1 больше, чем оценка, указанная в Tsoumakas et al., 2010 [t1]. Это расширяет ее возможности для обработки вырожденного случая, в котором экземпляр имеет 0 истинных меток.

Формально, учитывая двоичную матрицу индикаторов основных меток истинности. \(y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}}\) и

оценка, связанная с каждой меткой \(\hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}}\), покрытие определяется как

\[coverage(y, \hat{f}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1} \max_{j:y_{ij} = 1} \text{rank}_{ij}\]

с \(\text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right|\).

Учитывая определение ранга, связи в y_scores разрываются путем присвоения максимального ранга, который был бы присвоен всем связанным значениям.

Вот небольшой пример использования этой функции:

>>> import numpy as np
>>> from sklearn.metrics import coverage_error
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> coverage_error(y_true, y_score)
2.5

3.3.3.2. Средняя точность ранжирования меток

Функция label_ranking_average_precision_score реализует среднюю точность ранжирования меток (Label ranking average precision - LRAP). Эта метрика связана с функцией average_precision_score, но основана на понятии ранжирования меток, а не на точности и полноте.

Средняя точность ранжирования меток (LRAP) усредняет по выборкам ответ на следующий вопрос: для каждой основной истинной метки какая часть меток с более высоким рейтингом была истинными метками? Этот показатель производительности будет выше, если вы сможете лучше ранжировать метки, связанные с каждым образцом. Полученный балл всегда строго больше 0, а наилучшее значение равно 1. Если в каждом образце имеется ровно одна релевантная метка, средняя точность ранжирования меток эквивалентна Среднеобратному рангу.

Формально, дана двоичная индикаторная матрица основных меток истинности \(y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}}\) и оценка, связанная с каждой меткой \(\hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}}\), средняя точность определяется как

\[LRAP(y, \hat{f}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1} \frac{1}{||y_i||_0} \sum_{j:y_{ij} = 1} \frac{|\mathcal{L}_{ij}|}{\text{rank}_{ij}}\]

где \(\mathcal{L}_{ij} = \left\{k: y_{ik} = 1, \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\), \(\text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right|\), \(|\cdot|\) вычисляет мощность набора (т. е. количество элементов в наборе) и \(||\cdot||_0\) это \(\ell_0\) “норма” (который вычисляет количество ненулевых элементов в векторе).

Вот небольшой пример использования этой функции:

>>> import numpy as np
>>> from sklearn.metrics import label_ranking_average_precision_score
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> label_ranking_average_precision_score(y_true, y_score)
0.416...

3.3.3.3. Метрика Потеря рейтинга (Ranking loss)

Функция label_ranking_loss вычисляет потерю ранжирования (Ranking loss), которая усредняет по выборкам количество неправильно упорядоченных пар меток, т. е. истинные метки имеют более низкий балл, чем ложные метки, взвешенные по обратному числу упорядоченных пар. ложных и истинных меток. Наименьшая достижимая потеря рейтинга равна нулю.

Формально, дана двоичная индикаторная матрица основных меток истинности \(y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}}\) и оценка, связанная с каждой меткой \(\hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}}\), потеря рейтинга определяется как

\[ranking\_loss(y, \hat{f}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1} \frac{1}{||y_i||_0(n_\text{labels} - ||y_i||_0)} \left|\left\{(k, l): \hat{f}_{ik} \leq \hat{f}_{il}, y_{ik} = 1, y_{il} = 0 \right\}\right|\]

где \(|\cdot|\) вычисляет мощность набора (т. е. количество элементов в наборе), а \(||\cdot||_0\) - это \(\ell_0\) “норма” (которая вычисляет количество ненулевых элементов в векторе).

Вот небольшой пример использования этой функции:

>>> import numpy as np
>>> from sklearn.metrics import label_ranking_loss
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> label_ranking_loss(y_true, y_score)
0.75...
>>> # With the following prediction, we have perfect and minimal loss
>>> y_score = np.array([[1.0, 0.1, 0.2], [0.1, 0.2, 0.9]])
>>> label_ranking_loss(y_true, y_score)
0.0

3.3.3.4. Нормализованная Дисконтированный совокупный доход (Normalized Discounted Cumulative Gain - NDCG)

Дисконтированный совокупный доход (DCG) и Нормализованный Дисконтированный совокупный доход (NDCG) - это показатели ранжирования, реализованные в dcg_score и ndcg_score ; они сравнивают прогнозируемый порядок с достоверными показателями, такими как релевантность ответов на запрос.

Со страницы Википедии, посвященной Дисконтированному совокупному доходу:

“Совокупный дисконтированный доход (DCG) является мерой качества ранжирования. При поиске информации он часто используется для измерения эффективности алгоритмов веб-поисковых систем или связанных с ними приложений. Использование градуированной шкалы релевантности документов в наборе результатов поисковых систем. DCG измеряет полезность или выгоду документа на основе его позиции в списке результатов. “Доход” накапливается от верхней части списка результатов к нижней, при этом выгода от каждого результата дисконтируется на более низких позициях.

DCG упорядочивает истинные цели (например, релевантность ответов на запросы) в предсказанном порядке, затем умножает их на логарифмическое затухание и суммирует результат. Сумма может быть усечена после первых результатов \(K\), и в этом случае мы называем ее DCG@K. NDCG, или NDCG@K, представляет собой DCG, разделенную на DCG, полученную в результате идеального прогнозирования, так что оно всегда находится между 0 и 1. Обычно NDCG предпочтительнее DCG.

По сравнению с “потерей рейтинга”, NDCG может учитывать оценки релевантности, а не рейтинг на основе истины. Таким образом, если основная истина состоит только из упорядочения, следует отдать предпочтение потере ранжирования; если основная истина состоит из фактических оценок полезности (например, 0 - нерелевантно, 1 - актуально, 2 - очень актуально), можно использовать NDCG.

Для одной выборки задан вектор непрерывных основных значений истинности для каждой цели \(y \in \mathbb{R}^{M}\), где \(M\) - количество выходных данных, и предсказание \(\hat{y}\), которое вызывает функцию ранжирования \(f\), оценка DCG равна

\[\sum_{r=1}^{\min(K, M)}\frac{y_{f(r)}}{\log(1 + r)}\]

и показатель NDCG - это показатель DCG, разделенный на показатель DCG, полученный для \(y\).

3.3.4. Метрики для задач регрессии

Модуль sklearn.metrics реализует несколько функций потерь, оценок и полезности для измерения эффективности регрессии. Некоторые из них были улучшены для обработки случая с несколькими выходами: mean_squared_error, mean_absolute_error, r2_score, explained_variance_score, mean_pinball_loss, d2_pinball_score и d2_absolute_error_score.

Эти функции имеют аргумент ключевого слова multioutput, который определяет способ усреднения очков или потерь для каждой отдельной цели. По умолчанию используется 'uniform_average', который определяет равномерно взвешенное среднее значение для выходных данных. Если передается ndarray формы (n_outputs,), то его записи интерпретируются как веса и возвращается соответствующее средневзвешенное значение. Если multioutput имеет значение 'raw_values', то все неизмененные отдельные оценки или потери будут возвращены в массиве формы (n_outputs,).

r2_score и explained_variance_score принимают дополнительное значение 'variance_weighted' для параметра multioutput. Эта опция приводит к взвешиванию каждого отдельноq оценки по дисперсии соответствующей целевой переменной. Этот параметр определяет количественную оценку глобально фиксируемой немасштабированной дисперсии. Если целевые переменные имеют разный масштаб, то этот балл придает большее значение объяснению переменных с более высокой дисперсией. multioutput='variance_weighted' - это значение по умолчанию для r2_score для обратной совместимости. В будущем это будет изменено на uniform_average.

3.3.4.1. Оценка R², коэффициент детерминации

Функция r2_score вычисляет Коэффициент детерминации, обычно обозначаемый как \(R^2\).

представляет собой долю дисперсии (y), которая была объяснена независимыми переменными в модели. Он указывает на степень соответствия и, следовательно, является мерой того, насколько хорошо невидимые выборки могут быть предсказаны моделью через долю объясненной дисперсии.

Поскольку такая дисперсия зависит от набора данных, \(R^2\) не может быть значимо сопоставимым в разных наборах данных. Наилучшая возможная оценка - 1.0, и она может быть отрицательной (поскольку модель может быть сколь угодно хуже). Константная модель, которая всегда предсказывает ожидаемое (среднее) значение y, независимо от входных признаков, получит оценку \(R^2\) 0.0.

Примечание: когда остатки прогноза имеют нулевое среднее, оценка \(R^2\) и Объясненный показатель дисперсии (Explained variance score) идентичны.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-й выборки, а \(y_i\) - соответствующее истинное значение для общего количества \(n\) выборок, предполагаемое \(R^2\) определяется как

\[R^2(y, \hat{y}) = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2}\]

где \(\bar{y} = \frac{1}{n} \sum_{i=1}^{n} y_i\) и \(\sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} \epsilon_i^2\).

Обратите внимание, что r2_score вычисляет нескорректированное \(R^2\) без поправки на смещение выборочной дисперсии y.

В частном случае, когда истинная цель постоянна, оценка \(R^2\) не является конечной: это либо NaN (идеальные прогнозы), либо -Inf (несовершенные прогнозы). Такие неконечные оценки могут помешать выполнению правильной оптимизации модели, такой как кросс-валидация поиска по сетке. По этой причине поведение r2_score по умолчанию заключается в замене их на 1.0 (идеальные прогнозы) или 0.0 (несовершенные прогнозы). Если для force_finite установлено значение False, эта оценка возвращается к исходному определению \(R^2\).

Вот небольшой пример использования функции r2_score:

>>> from sklearn.metrics import r2_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> r2_score(y_true, y_pred)
0.948...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> r2_score(y_true, y_pred, multioutput='variance_weighted')
0.938...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> r2_score(y_true, y_pred, multioutput='uniform_average')
0.936...
>>> r2_score(y_true, y_pred, multioutput='raw_values')
array([0.965..., 0.908...])
>>> r2_score(y_true, y_pred, multioutput=[0.3, 0.7])
0.925...
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2]
>>> r2_score(y_true, y_pred)
1.0
>>> r2_score(y_true, y_pred, force_finite=False)
nan
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2 + 1e-8]
>>> r2_score(y_true, y_pred)
0.0
>>> r2_score(y_true, y_pred, force_finite=False)
-inf

3.3.4.2. Средняя абсолютная ошибка (Mean absolute error - MAE)

Функция mean_absolute_error вычисляет среднюю абсолютную ошибку, метрику риска, соответствующую ожидаемому значению потерь по абсолютной ошибке или \(l1\)-норма потерь.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то средняя абсолютная ошибка (MAE), оцененный по \(n_{\text{samples}}\), определяется как

\[\text{MAE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \left| y_i - \hat{y}_i \right|.\]

Вот небольшой пример использования функции mean_absolute_error:

>>> from sklearn.metrics import mean_absolute_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_absolute_error(y_true, y_pred)
0.5
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_absolute_error(y_true, y_pred)
0.75
>>> mean_absolute_error(y_true, y_pred, multioutput='raw_values')
array([0.5, 1. ])
>>> mean_absolute_error(y_true, y_pred, multioutput=[0.3, 0.7])
0.85...

3.3.4.3. Среднеквадратическая ошибка (Mean squared error - MSE)

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

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то среднеквадратическая ошибка (MSE), оцененный по \(n_{\text{samples}}\), определяется как

\[\text{MSE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} (y_i - \hat{y}_i)^2.\]

Вот небольшой пример использования функции mean_squared_error:

>>> from sklearn.metrics import mean_squared_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_squared_error(y_true, y_pred)
0.375
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_squared_error(y_true, y_pred)
0.7083...

Извлечение квадратного корня из MSE, называемое среднеквадратичной ошибкой (root mean squared error - RMSE), является еще одной распространенной метрикой, которая обеспечивает измерение в тех же единицах, что и целевая переменная. RSME доступен через функцию root_mean_squared_error.

3.3.4.4. Среднеквадратическая логарифмическая ошибка (Mean squared logarithmic error - MSLE)

Функция mean_squared_log_error вычисляет метрику риска, соответствующую ожидаемому значению квадратичной логарифмической (квадратичной) ошибки или потери.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то среднеквадратическая логарифмическая ошибка (MSLE), оцененный по \(n_{\text{samples}}\), определяется как

\[\text{MSLE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} (\log_e (1 + y_i) - \log_e (1 + \hat{y}_i) )^2.\]

Где \(\log_e (x)\) означает натуральный логарифм \(x\). Эту метрику лучше всего использовать, когда цели имеют экспоненциальный рост, например численность населения, средние продажи товара за несколько лет и т. д. Обратите внимание, что эта метрика наказывает за недопрогнозированную оценку больше, чем за завышенную оценку.

Вот небольшой пример использования функции mean_squared_log_error:

>>> from sklearn.metrics import mean_squared_log_error
>>> y_true = [3, 5, 2.5, 7]
>>> y_pred = [2.5, 5, 4, 8]
>>> mean_squared_log_error(y_true, y_pred)
0.039...
>>> y_true = [[0.5, 1], [1, 2], [7, 6]]
>>> y_pred = [[0.5, 2], [1, 2.5], [8, 8]]
>>> mean_squared_log_error(y_true, y_pred)
0.044...

Среднеквадратическая логарифмическая ошибка (RMSLE) доступна через функцию root_mean_squared_log_error.

3.3.4.5. Средняя абсолютная процентная ошибка (Mean absolute percentage error - MAPE)

Функция mean_absolute_percentage_error (MAPE), также известный как среднее абсолютное процентное отклонение (mean absolute percentage deviation - MAPD), является показателем оценки для задач регрессии. Идея этой метрики заключается в том, чтобы быть чувствительной к относительным ошибкам. Например, оно не изменяется при глобальном масштабировании целевой переменной.

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то средняя абсолютная процентная ошибка (MAPE), оцененный по \(n_{\text{samples}}\), определяется как

\[\text{MAPE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \frac{{}\left| y_i - \hat{y}_i \right|}{\max(\epsilon, \left| y_i \right|)}\]

где \(\epsilon\) - произвольное маленькое, но строго положительное число, чтобы избежать неопределенных результатов, когда y равно нулю.

Функция mean_absolute_percentage_error поддерживает несколько выходов.

Вот небольшой пример использования функции mean_absolute_percentage_error:

>>> from sklearn.metrics import mean_absolute_percentage_error
>>> y_true = [1, 10, 1e6]
>>> y_pred = [0.9, 15, 1.2e6]
>>> mean_absolute_percentage_error(y_true, y_pred)
0.2666...

В приведенном выше примере, если бы мы использовали mean_absolute_error, он игнорировал бы небольшие значения магнитуды и отражал бы только ошибку в прогнозировании самого высокого значения магнитуды. Но эта проблема решена в случае MAPE, поскольку он вычисляет относительную процентную ошибку по отношению к фактическому выходу.

3.3.4.6. Медианная абсолютная ошибка (Median absolute error - MedAE)

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

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то медианная абсолютная ошибка (MedAE) оценка по \(n_{\text{samples}}\) определяется как

\[\text{MedAE}(y, \hat{y}) = \text{median}(\mid y_1 - \hat{y}_1 \mid, \ldots, \mid y_n - \hat{y}_n \mid).\]

Функция median_absolute_error не поддерживает несколько выходов.

Вот небольшой пример использования функции median_absolute_error:

>>> from sklearn.metrics import median_absolute_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> median_absolute_error(y_true, y_pred)
0.5

3.3.4.7. Максимальная ошибка

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

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то максимальная ошибка определяется как

\[\text{Max Error}(y, \hat{y}) = \max(| y_i - \hat{y}_i |)\]

Вот небольшой пример использования функции max_error:

>>> from sklearn.metrics import max_error
>>> y_true = [3, 2, 7, 1]
>>> y_pred = [9, 2, 7, 1]
>>> max_error(y_true, y_pred)
6

max_error не поддерживает несколько выходов.

3.3.4.8. Объясненный показатель дисперсии (Explained variance score)

Функция explained_variance_score вычисляет объяснённую оценку регрессии дисперсии.

Если \(\hat{y}\) - это предполагаемый целевой результат, \(y\) - соответствующий (правильный) целевой результат, а \(Var\) - это Дисперсия, квадрат стандартного отклонения, тогда объясненная дисперсия оценивается следующим образом

\[explained\_{}variance(y, \hat{y}) = 1 - \frac{Var\{ y - \hat{y}\}}{Var\{y\}}\]

Наилучший возможный балл - 1.0, более низкие значения хуже.

В частном случае, когда истинная цель постоянна, показатель объясненной дисперсии не является конечным: это либо NaN (идеальные прогнозы), либо -Inf (несовершенные прогнозы). Такие неконечные оценки могут помешать правильному выполнению правильной оптимизации модели, такой как кросс-валидация поиска по сетке. По этой причине поведение explained_variance_score по умолчанию заключается в замене их на 1,0 (идеальные прогнозы) или 0,0 (несовершенные прогнозы). Вы можете установить для параметра “force_finite” значение “False”, чтобы предотвратить это исправление и вернуться к исходной оценке объясненного отклонения.

Вот небольшой пример использования функции explained_variance_score:

>>> from sklearn.metrics import explained_variance_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> explained_variance_score(y_true, y_pred)
0.957...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> explained_variance_score(y_true, y_pred, multioutput='raw_values')
array([0.967..., 1.        ])
>>> explained_variance_score(y_true, y_pred, multioutput=[0.3, 0.7])
0.990...
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2]
>>> explained_variance_score(y_true, y_pred)
1.0
>>> explained_variance_score(y_true, y_pred, force_finite=False)
nan
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2 + 1e-8]
>>> explained_variance_score(y_true, y_pred)
0.0
>>> explained_variance_score(y_true, y_pred, force_finite=False)
-inf

3.3.4.9. Отклонения среднего Пуассона, Гаммы и Твиди

Функция mean_tweedie_deviance вычисляет среднюю ошибку отклонения Твиди с параметром power (\(p\)). Это метрика, которая позволяет получить прогнозируемые ожидаемые значения целей регрессии.

Существуют следующие особые случаи:

Если \(\hat{y}_i\) - предсказанное значение \(i\)-го образца, а \(y_i\) - соответствующее истинное значение, то средняя ошибка отклонения Твиди (D) для степени \(p\), оцененной по \(n_{\text{samples}}\), определяется как

\[\begin{split}\text{D}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} \begin{cases} (y_i-\hat{y}_i)^2, & \text{for }p=0\text{ (Normal)}\\ 2(y_i \log(y_i/\hat{y}_i) + \hat{y}_i - y_i), & \text{for }p=1\text{ (Poisson)}\\ 2(\log(\hat{y}_i/y_i) + y_i/\hat{y}_i - 1), & \text{for }p=2\text{ (Gamma)}\\ 2\left(\frac{\max(y_i,0)^{2-p}}{(1-p)(2-p)}- \frac{y_i\,\hat{y}_i^{1-p}}{1-p}+\frac{\hat{y}_i^{2-p}}{2-p}\right), & \text{otherwise} \end{cases}\end{split}\]

Отклонение Твиди является однородной функцией степени 2. Таким образом, гамма-распределение с power=2 означает, что одновременное масштабирование y_true и y_pred не влияет на отклонение. Для распределения Пуассона power=1 отклонение масштабируется линейно, а для нормального распределения (power=0) - квадратично. В общем, чем выше power, тем меньше внимания уделяется крайним отклонениям между истинными и прогнозируемыми целями.

Например, давайте сравним два прогноза 1.5 и 150, которые на 50% превышают соответствующее истинное значение.

Среднеквадратическая ошибка (power=0) очень чувствительна к разнице прогнозов второй точки:

>>> from sklearn.metrics import mean_tweedie_deviance
>>> mean_tweedie_deviance([1.0], [1.5], power=0)
0.25
>>> mean_tweedie_deviance([100.], [150.], power=0)
2500.0

Если мы увеличим power до 1:

>>> mean_tweedie_deviance([1.0], [1.5], power=1)
0.18...
>>> mean_tweedie_deviance([100.], [150.], power=1)
18.9...

разница в ошибках уменьшается. Наконец, установив power=2:

>>> mean_tweedie_deviance([1.0], [1.5], power=2)
0.14...
>>> mean_tweedie_deviance([100.], [150.], power=2)
0.14...

мы получим идентичные ошибки. Таким образом, отклонение при power=2 чувствительно только к относительным ошибкам.

3.3.4.10. Pinball loss

Функция mean_pinball_loss используется для оценки прогнозирующей эффективности моделей квантильной регрессии.

\[\text{pinball}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \alpha \max(y_i - \hat{y}_i, 0) + (1 - \alpha) \max(\hat{y}_i - y_i, 0)\]

Значение Pinball loss эквивалентно половине mean_absolute_error, когда параметр квантиля alpha установлен на 0.5.

Вот небольшой пример использования функции mean_pinball_loss:

>>> from sklearn.metrics import mean_pinball_loss
>>> y_true = [1, 2, 3]
>>> mean_pinball_loss(y_true, [0, 2, 3], alpha=0.1)
0.03...
>>> mean_pinball_loss(y_true, [1, 2, 4], alpha=0.1)
0.3...
>>> mean_pinball_loss(y_true, [0, 2, 3], alpha=0.9)
0.3...
>>> mean_pinball_loss(y_true, [1, 2, 4], alpha=0.9)
0.03...
>>> mean_pinball_loss(y_true, y_true, alpha=0.1)
0.0
>>> mean_pinball_loss(y_true, y_true, alpha=0.9)
0.0

Можно создать объект-скорер с определенным выбором alpha:

>>> from sklearn.metrics import make_scorer
>>> mean_pinball_loss_95p = make_scorer(mean_pinball_loss, alpha=0.95)

Такой объект можно использовать для оценки эффективности обобщения квантильного регрессора посредством перекрестной проверки:

>>> from sklearn.datasets import make_regression
>>> from sklearn.model_selection import cross_val_score
>>> from sklearn.ensemble import GradientBoostingRegressor
>>>
>>> X, y = make_regression(n_samples=100, random_state=0)
>>> estimator = GradientBoostingRegressor(
...     loss="quantile",
...     alpha=0.95,
...     random_state=0,
... )
>>> cross_val_score(estimator, X, y, cv=5, scoring=mean_pinball_loss_95p)
array([13.6..., 9.7..., 23.3..., 9.5..., 10.4...])

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

3.3.4.11. D² оценка

Оценка D² вычисляет долю объясненного отклонения. Это обобщение R², где квадрат ошибки обобщается и заменяется отклонением по выбору \(\text{dev}(y, \hat{y})\) (например, Твиди, pinball или средняя абсолютная ошибка) . D² - это форма оценки навыков. Он рассчитывается как

\[D^2(y, \hat{y}) = 1 - \frac{\text{dev}(y, \hat{y})}{\text{dev}(y, y_{\text{null}})} \,.\]

Где \(y_{\text{null}}\) - оптимальное предсказание модели, состоящей только из перехвата (например, среднее значение y_true для случая Твиди, медиана для абсолютной ошибки и альфа-квантиль для pinball loss).

Как и R², наилучший возможный балл равен 1.0 и может быть отрицательным (поскольку модель может быть сколь угодно хуже). Константная модель, которая всегда прогнозирует \(y_{\text{null}}\), независимо от входных признаков, получит оценку D², равную 0.0.

3.3.4.11.1. Оценка D² Твиди

Функция d2_tweedie_score реализует особый случай D².

где \(\text{dev}(y, \hat{y})\) - отклонение Твиди, см. Отклонения среднего Пуассона, Гаммы и Твиди.

Он также известен как D² Твиди и связан с индексом отношения правдоподобия Макфаддена.

Аргумент power определяет степерь Твиди как для mean_tweedie_deviance. Обратите внимание, что для power=0 d2_tweedie_score равно r2_score (для одиночных целей).

Объект оценки с определенным выбором power может быть построен:

>>> from sklearn.metrics import d2_tweedie_score, make_scorer
>>> d2_tweedie_score_15 = make_scorer(d2_tweedie_score, power=1.5)

3.3.4.11.2. D² pinball оценка

Функция d2_pinball_score реализует особый случай D² с pinball loss, см. Pinball loss, т.е.

\[\text{dev}(y, \hat{y}) = \text{pinball}(y, \hat{y}).\]

Аргумент alpha определяет наклон pinball loss, как для mean_pinball_loss (Pinball loss). Он определяет квантильный уровень alpha, для которого оптимален pinball loss, а также D². Обратите внимание, что для alpha=0.5 (по умолчанию) d2_pinball_score равно d2_absolute_error_score.

Объект оценки с определенным выбором alpha может быть построен:

>>> from sklearn.metrics import d2_pinball_score, make_scorer
>>> d2_pinball_score_08 = make_scorer(d2_pinball_score, alpha=0.8)

3.3.4.11.3. Оценка абсолютной ошибки D²

Функция d2_absolute_error_score реализует особый случай Средняя абсолютная ошибка (Mean absolute error - MAE)

\[\text{dev}(y, \hat{y}) = \text{MAE}(y, \hat{y}).\]

Вот несколько примеров использования функции d2_absolute_error_score:

>>> from sklearn.metrics import d2_absolute_error_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> d2_absolute_error_score(y_true, y_pred)
0.764...
>>> y_true = [1, 2, 3]
>>> y_pred = [1, 2, 3]
>>> d2_absolute_error_score(y_true, y_pred)
1.0
>>> y_true = [1, 2, 3]
>>> y_pred = [2, 2, 2]
>>> d2_absolute_error_score(y_true, y_pred)
0.0

3.3.4.12. Визуальная оценка регрессионных моделей

Среди методов оценки качества регрессионных моделей scikit-learn предоставляет класс PredictionErrorDisplay. Это позволяет визуально проверять ошибки прогнозирования модели двумя разными способами.

../_images/sphx_glr_plot_cv_predict_001.png

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

Обратите внимание, что вышеизложенное справедливо только в том случае, если прогнозируемые значения являются ожидаемым значением y при заданном X. Обычно это относится к моделям регрессии, которые минимизируют целевую функцию среднеквадратической ошибки (MSE) или, в более общем смысле, среднее отклонение Твиди для любого значения его параметра power.

При построении прогнозов класса оценок, который предсказывает квантиль y по заданному X, например. QuantileRegressor или любой другой модели, минимизирующей pinball loss, ожидается, что часть точек будет лежать выше или ниже диагонали в зависимости от предполагаемого уровня квантиля.

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

На правом графике показаны остатки (т.е. разница между фактическими и прогнозируемыми значениями) по сравнению с прогнозируемыми значениями.

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

В частности, если истинное распределение y|X является распределением Пуассона или гамма-распределением, ожидается, что дисперсия остатков оптимальной модели будет расти с прогнозируемым значением E[y|X] ( либо линейно для Пуассона, либо квадратично для Гаммы).

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

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

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

3.3.5. Метрики кластеризации

Модуль sklearn.metrics реализует несколько функций потерь, оценок и утилиты. Для получения дополнительной информации см. раздел Оценка производительности кластеризации для кластеризации и Оценка бикластеризации для бинарной кластеризации.

3.3.6. Фиктивные модели (Dummy estimators)

При обучении с учителем простая проверка работоспособности состоит в сравнении полученной оценки с простыми эмпирическими правилами.

Dummy estimators, или “Фиктивные модели”, - это простые модели метода в машинном обучении, которые используются в качестве базовой или первичной модели для сравнения с более сложными моделями. Они обычно предсказывают результат случайным образом или на основе простых правил, и их применение может быть полезным для понимания работы других моделей или для проверки, насколько хорошо работают выбранные модели в сравнении с самой простой базовой.

Dummy estimators могут называться таким образом из-за своей “дурацкой”, или “глупой” природы предсказаний, которые не имеют особой значимости или содержательности.

Класс DummyClassifier реализует несколько простых стратегий классификации:

  • stratified (Стратифицированный) генерирует случайные прогнозы с учетом распределения классов обучающего набора.

  • most_frequent всегда прогнозирует наиболее часто встречающуюся метку в обучающем наборе.

  • prior всегда прогнозирует класс, который максимизирует предшествующий класс (например, most_frequent), а predict_proba возвращает предшествующий класс.

  • uniform генерирует прогнозы равномерно и случайным образом.

  • constant всегда прогнозирует постоянную метку, предоставленную пользователем. Основной мотивацией этого метода является оценка F1, когда положительный класс находится в меньшинстве.

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

Чтобы проиллюстрировать DummyClassifier, сначала давайте создадим несбалансированный набор данных:

>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> X, y = load_iris(return_X_y=True)
>>> y[y != 1] = -1
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

Далее давайте сравним точность SVC и most_frequent:

>>> from sklearn.dummy import DummyClassifier
>>> from sklearn.svm import SVC
>>> clf = SVC(kernel='linear', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.63...
>>> clf = DummyClassifier(strategy='most_frequent', random_state=0)
>>> clf.fit(X_train, y_train)
DummyClassifier(random_state=0, strategy='most_frequent')
>>> clf.score(X_test, y_test)
0.57...

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

>>> clf = SVC(kernel='rbf', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.94...

Мы видим, что точность увеличена почти до 100%. Для лучшей оценки точности рекомендуется использовать стратегию перекрестной проверки (cross validation), если она не требует слишком больших затрат ресурсов ЦП. Для получения дополнительной информации см. раздел Кросс-валидация (Cross-validation или перекрестная проверка): оценка эффективности оценок. Более того, если вы хотите оптимизировать пространство параметров, настоятельно рекомендуется использовать соответствующую методологию; подробности см. в разделе Настройка гиперпараметров модели.

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

Класс DummyRegressor также реализует четыре простых практических правила регрессии:

  • mean всегда прогнозирует среднее значение тренировочной целевой переменной.

  • median всегда прогнозирует медиану тренировочной целевой переменной.

  • quantile всегда прогнозирует предоставленный пользователем квантиль тренировочной целевой переменной.

  • constant всегда прогнозирует постоянное значение, предоставленное пользователем.

Во всех этих стратегиях метод прогнозирования полностью игнорирует входные данные.