文章目录


有三种不同的 API 用于评估模型预测的质量:
  • 估计器评分方法:估计器具有一个 score 方法,为其设计解决的问题提供了默认的评估标准。这在本页面中没有讨论,但在每个估计器的文档中有详细介绍。
  • 评分参数:使用交叉验证(如 model_selection.cross_val_scoremodel_selection.GridSearchCV)的模型评估工具依赖于内部的评分策略。这在评分参数部分中有详细介绍。
  • 度量函数sklearn.metrics 模块实现了用于特定目的评估预测误差的函数。这些度量在分类度量多标签排序度量回归度量聚类度量的各个部分中详细介绍。

最后,dummy_estimators 对于随机预测可以提供基准值。

对于“成对”度量,是针对样本而不是估计器或预测的,详见度量部分。

scoring 参数:定义模型评估规则

使用诸如 model_selection.GridSearchCVmodel_selection.cross_val_score 等工具进行模型选择和评估时,可以使用 scoring 参数来控制评估的估计器应用的度量标准。

常见情况:预定义值

对于最常见的用例,可以使用 scoring 参数指定一个评分器对象;下表显示了所有可能的值。所有评分器对象都遵循一个约定,即较高的返回值优于较低的返回值。因此,度量模型与数据之间的距离的度量,如 metrics.mean_squared_error,可以作为 neg_mean_squared_error 使用,它返回度量的负值。

使用示例:

>>> 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.        ])

sklearn.metrics

从度量函数定义评分策略

sklearn.metrics 模块还提供了一组简单的函数,用于根据真实值和预测值测量预测误差:

  • _score 结尾的函数返回要最大化的值,值越高越好。
  • _error_loss 结尾的函数返回要最小化的值,值越低越好。当使用 make_scorer 将其转换为评分器对象时,将 greater_is_better 参数设置为 False(默认为 True;请参见下面的参数描述)。

各种机器学习任务可用的度量在下面的各个部分中详细说明。

许多度量没有给出用作 scoring 值的名称,有时是因为它们需要额外的参数,例如 fbeta_score。在这种情况下,您需要生成一个适当的评分器对象。将度量转换为可调用对象以用于模型评估的最简单方法是使用 make_scorer。该函数将度量转换为可用于模型评估的可调用对象。

一个典型的用例是使用库中现有的度量函数包装非默认参数值,例如 fbeta_score 函数的 beta 参数:

>>> 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)

自定义评分器对象

第二种用例是使用 make_scorer 从简单的 Python 函数构建完全自定义的评分器对象,该函数可以接受多个参数:

  • 您要使用的 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"]。在这种情况下,评分器将使用列表中给定的顺序中的第一个可用方法来计算得分。
  • 任何其他参数,例如 f1_score 中的 betalabels

下面是构建自定义评分器的示例,并使用 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)
...
>>> # score will negate the return value of my_custom_loss_func,
>>> # which will be np.log(2), 0.693, given the values for X
>>> # and y defined below.
>>> 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...

实现自己的评分器对象

您可以通过从头开始构建自己的评分器对象,而不使用 make_scorer 工厂,生成更灵活的模型评分器。

如何从头构建评分器

要使可调用对象成为评分器,它需要满足以下两个规则指定的协议:

  • 它可以使用参数 (estimator, X, y) 调用,其中 estimator 是应该评估的模型,X 是验证数据,yX 的真实目标(在有监督的情况下)或 None(在无监督的情况下)。
  • 它返回一个浮点数,该浮点数量化了 estimatorX 上相对于 y 的预测质量。同样,按照约定,较高的数字更好,因此如果您的评分器返回损失,则该值应该取反。
  • 高级:如果它需要传递额外的元数据,则应该公开一个 get_metadata_routing 方法返回所请求的元数据。用户应该能够通过 set_score_request 方法设置所请求的元数据。有关更多详细信息,请参见 用户指南 <metadata_routing>开发者指南 <sphx_glr_auto_examples_miscellaneous_plot_metadata_routing.py>

使用多个评估指标

Scikit-learn 还允许在 GridSearchCVRandomizedSearchCVcross_validate 中评估多个指标。

有三种方法可以为 scoring 参数指定多个评分指标:

  • 作为字符串指标的可迭代对象:
>>> scoring = ['accuracy', 'precision']
  • 作为将评分器名称映射到评分函数的字典:
>>> from sklearn.metrics import accuracy_score
>>> from sklearn.metrics import make_scorer
>>> scoring = {'accuracy': make_scorer(accuracy_score),
...            'prec': 'precision'}

注意,字典的值可以是评分器函数,也可以是预定义的指标字符串。

  • 作为返回得分字典的可调用对象:
  >>> from sklearn.model_selection import cross_validate
  >>> from sklearn.metrics import confusion_matrix
  >>> # 一个示例的二元分类数据集
  >>> 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)
  >>> # 获取测试集的真阳性得分
  >>> print(cv_results['test_tp'])
  [10  9  8  7  8]
  >>> # 获取测试集的假阴性得分
  >>> print(cv_results['test_fn'])
  [0 1 2 3 2]

分类指标

sklearn.metrics

sklearn.metrics 模块实现了几个用于衡量分类性能的损失、得分和实用函数。一些指标可能需要正类的概率估计、置信度值或二进制决策值。大多数实现都允许每个样本通过 sample_weight 参数对整体得分做出加权贡献。

其中一些仅适用于二元分类情况:

其他指标也适用于多类别情况:

还有一些适用于多标签情况:

还有一些适用于二进制和多标签(但不适用于多类别)问题:

在接下来的子章节中,我们将描述每个函数,之前会有一些关于常见 API 和指标定义的注释。

从二元到多类和多标签

一些指标本质上是为二元分类任务定义的(例如 f1_scoreroc_auc_score)。在这些情况下,默认情况下只评估正类,假设默认情况下正类被标记为 1(尽管可以通过 pos_label 参数进行配置)。

将二元指标扩展到多类或多标签问题时,数据被视为一组二元问题,每个类别一个。然后有多种方法可以对类别集合中的二元指标计算进行平均,每种方法在某些情况下可能有用。如果可用,应该使用 average 参数在这些方法中进行选择。

  • "macro" 简单地计算二元指标的平均值,对每个类别给予相等的权重。在罕见类别仍然重要的问题中,宏平均可能是突出它们性能的一种方法。另一方面,所有类别都同等重要的假设通常是不正确的,因此宏平均会过分强调罕见类别的通常较低的性能。

  • "weighted" 通过计算每个类别在真实数据样本中的存在情况对二元指标的平均值进行加权,以解决类别不平衡的问题。

  • "micro" 为每个样本-类别对对整体指标(除了样本权重的影响)做出相等的贡献。与对每个类别求和指标不同,这个方法对构成每个类别指标的分子和分母进行求和,以计算总体商数。在多标签设置中,可能更喜欢使用微平均,包括要忽略大多数类别的多类别分类。

  • "samples" 仅适用于多标签问题。它不计算每个类别的度量,而是计算评估数据中每个样本的真实类别和预测类别之间的度量,并返回它们的(加权的 sample_weight)平均值。

  • 选择 average=None 将返回一个包含每个类别得分的数组。

虽然多类数据被提供给指标,就像二进制目标一样,作为类标签数组,但多标签数据是指定为指示器矩阵,其中单元格 [i, j] 的值为 1,如果样本 i 具有标签 j,否则为 0。

准确率得分

accuracy_score 函数计算准确率,默认情况下是正确预测的分数(分数的分数)。

在多标签分类中,该函数返回子集准确率。如果样本的整个预测标签集与真实标签集严格匹配,则子集准确率为 1.0;否则为 0.0。

如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,则在 n samples n_\text{samples} nsamples 上的正确预测的比例定义为

accuracy ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 1 ( y ^ i = y i ) \texttt{accuracy}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} 1(\hat{y}_i = y_i) accuracy(y,y^)=nsamples1i=0nsamples11(y^i=yi)

其中 1 ( x ) 1(x) 1(x)指示函数

>>> 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

示例:

  • 有关使用数据集排列测试的准确率得分用法示例,请参见 sphx_glr_auto_examples_model_selection_plot_permutation_tests_for_classification.py

Top-k 准确率得分

top_k_accuracy_score 函数是 accuracy_score 的一般化。不同之处在于,只要真实标签与前 k 个最高预测分数之一相关联,预测就被视为正确。accuracy_score 是 k = 1 的特殊情况。

该函数涵盖了二元和多类别分类情况,但不涵盖多标签情况。

如果 f ^ i , j \hat{f}_{i,j} f^i,j 是第 i i i 个样本对应于第 j j j 个最大预测分数的预测类别, y i y_i yi 是相应的真实值,则在 n samples n_\text{samples} nsamples 上的正确预测的比例定义为

top-k   accuracy ( y , f ^ ) = 1 n samples ∑ i = 0 n samples − 1 ∑ j = 1 k 1 ( f ^ i , j = y i ) \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) top-k accuracy(y,f^)=nsamples1i=0nsamples1j=1k1(f^i,j=yi)

其中 k k k 是允许的猜测次数, 1 ( x ) 1(x) 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

平衡准确率得分

在二分类情况下,平衡准确率等于敏感性(真阳性率)和特异性(真阴性率)的算术平均值,或者是二元预测的ROC曲线下的面积:

平衡准确率 = 1 2 ( T P T P + F N + T N T N + F P ) \texttt{平衡准确率} = \frac{1}{2}\left( \frac{TP}{TP + FN} + \frac{TN}{TN + FP}\right ) 平衡准确率=21(TP+FNTP+TN+FPTN)

如果分类器在两个类别上表现相同,这个术语就简化为传统准确率(即正确预测的数量除以总预测数量)。

相反,如果传统准确率仅因为分类器利用了一个不平衡的测试集而高于随机准确率,则平衡准确率将降至 1 n _ c l a s s e s \frac{1}{n\_classes} n_classes1

该分数的范围是从0到1,或者当使用 adjusted=True 时,重新缩放到范围 1 1 − n _ c l a s s e s \frac{1}{1 - n\_classes} 1n_classes1 到 1,包括边界,其中随机得分为0。

如果 y i y_i yi 是第 i i i 个样本的真实值, w i w_i wi 是相应的样本权重,则我们将样本权重调整为:

w ^ i = w i ∑ j 1 ( y j = y i ) w j \hat{w}_i = \frac{w_i}{\sum_j{1(y_j = y_i) w_j}} w^i=j1(yj=yi)wjwi

其中 1 ( x ) 1(x) 1(x)指示函数。给定预测的 y ^ i \hat{y}_i y^i 和样本 i i i,平衡准确率定义为:

平衡准确率 ( y , y ^ , w ) = 1 ∑ w ^ i ∑ i 1 ( y ^ i = y i ) w ^ i \texttt{平衡准确率}(y, \hat{y}, w) = \frac{1}{\sum{\hat{w}_i}} \sum_i 1(\hat{y}_i = y_i) \hat{w}_i 平衡准确率(y,y^,w)=w^i1i1(y^i=yi)w^i

使用 adjusted=True,平衡准确率报告相对于 平衡准确率 ( y , 0 , w ) = 1 n _ c l a s s e s \texttt{平衡准确率}(y, \mathbf{0}, w) = \frac{1}{n\_classes} 平衡准确率(y,0,w)=n_classes1 的相对增加。在二分类情况下,这也被称为*Youden’s J统计量*,或者称为信息度

参考文献:

[Guyon2015] (1,2)

I. Guyon, K. Bennett, G. Cawley, H.J. Escalante, S. Escalera, T.K. Ho, N. Macià, B. Ray, M. Saeed, A.R. Statnikov, E. Viegas, Design of the 2015 ChaLearn AutoML Challenge, IJCNN 2015.

[Mosley2013] (1,2)

L. Mosley, A balanced approach to the multi-class imbalance problem, IJCV 2010.

[Kelleher2015]

John. D. Kelleher, Brian Mac Namee, Aoife D’Arcy, Fundamentals of Machine Learning for Predictive Data Analytics: Algorithms, Worked Examples, and Case Studies, 2015.

[Urbanowicz2015]

Urbanowicz R.J., Moore, J.H. ExSTraCS 2.0: description and evaluation of a scalable learning classifier system, Evol. Intel. (2015) 8: 89.

Cohen’s kappa

函数 cohen_kappa_score 计算Cohen’s kappa统计量。该度量用于比较不同人类标注者的标注,而不是分类器与真实情况之间的比较。

Kappa统计量(参见文档字符串)是一个介于-1和1之间的数。大于0.8的分数通常被认为是良好的一致性;小于或等于0表示没有一致性(实际上是随机标签)。

Kappa统计量可以用于二分类或多分类问题,但不能用于多标签问题(除非手动计算每个标签的得分),也不能用于超过两个标注者的情况。

>>> 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

混淆矩阵

confusion_matrix 函数通过计算混淆矩阵来评估分类准确性,其中每一行对应于真实类别(Wikipedia和其他参考文献可能对轴使用不同的约定)。

根据定义,混淆矩阵中的第 i , j i, j i,j 个元素是实际属于第 i i i 类但被预测为第 j j 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 可以用于将混淆矩阵可视化,如 sphx_glr_auto_examples_model_selection_plot_confusion_matrix.py 示例中所示,它创建了以下图形:

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP

参数 normalize 允许报告比例而不是计数。混淆矩阵可以以3种不同的方式进行归一化:'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]])

对于二分类问题,我们可以按以下方式获取真负例、假正例、假负例和真正例的计数:

>>> 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)

示例:

  • 有关使用混淆矩阵评估分类器输出质量的示例,请参见sphx_glr_auto_examples_model_selection_plot_confusion_matrix.py
  • 有关使用混淆矩阵对手写数字进行分类的示例,请参见sphx_glr_auto_examples_classification_plot_digits_classification.py
  • 有关使用混淆矩阵对文本文档进行分类的示例,请参见sphx_glr_auto_examples_text_plot_document_classification_20newsgroups.py

分类报告

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
<BLANKLINE>
     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
<BLANKLINE>
    accuracy                           0.60         5
   macro avg       0.56      0.50      0.49         5
weighted avg       0.67      0.60      0.59         5
<BLANKLINE>

示例:

  • 有关使用分类报告评估手写数字的分类的示例,请参见sphx_glr_auto_examples_classification_plot_digits_classification.py
  • 有关使用分类报告进行网格搜索和嵌套交叉验证的示例,请参见sphx_glr_auto_examples_model_selection_plot_grid_search_digits.py

Hamming损失

hamming_loss 计算两组样本之间的平均Hamming损失Hamming距离

如果 y ^ i , j \hat{y}_{i,j} y^i,j 是给定样本 i i i 的第 j j j 个标签的预测值, y i , j y_{i,j} yi,j 是相应的真实值, n samples n_\text{samples} nsamples 是样本数, n labels n_\text{labels} nlabels 是标签数,则Hamming损失 L H a m m i n g L_{Hamming} LHamming 定义为:

L H a m m i n g ( y , y ^ ) = 1 n samples ∗ n labels ∑ i = 0 n samples − 1 ∑ j = 0 n labels − 1 1 ( y ^ i , j ≠ y i , j ) 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}) LHamming(y,y^)=nsamplesnlabels1i=0nsamples1j=0nlabels11(y^i,j=yi,j)

其中 1 ( x ) 1(x) 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)对应于y_truey_pred之间的汉明距离,类似于zero_one_loss函数。然而,零一损失函数惩罚不严格匹配真实集合的预测集合,而汉明损失函数惩罚个别标签。因此,汉明损失始终介于零和一之间(包括零和一),上界为零一损失。预测真实标签的真子集或超集将导致汉明损失介于零和一之间(不包括零和一)。

精确率、召回率和 F-度量

直观地说,精确率是分类器不将负样本错误标记为正样本的能力,而召回率是分类器找到所有正样本的能力。

F-度量 F β F_\beta Fβ F 1 F_1 F1度量)可以解释为精确率和召回率的加权调和平均值。当 β = 1 \beta=1 β=1时, F β F_\beta Fβ F 1 F_1 F1是等价的,精确率和召回率同等重要。

precision_recall_curve函数通过改变决策阈值,从真实标签和分类器给出的得分计算精确率-召回率曲线。

average_precision_score函数从预测得分计算平均精确率(AP)。该值介于0和1之间,越高越好。AP定义为:

AP = ∑ n ( R n − R n − 1 ) P n \text{AP} = \sum_n (R_n - R_{n-1}) P_n AP=n(RnRn1)Pn

其中 P n P_n Pn R n R_n Rn是第n个阈值处的精确率和召回率。对于随机预测,AP是正样本的比例。

参考文献和提出了插值的AP的替代变体。目前,average_precision_score函数没有实现任何插值变体。参考文献和说明了在计算使用梯形法则的曲线下面积时,对精确率-召回率曲线上的点进行线性插值会导致对分类器性能的过于乐观的度量。在auc中使用这种线性插值。

有几个函数可以用来分析精确率、召回率和F-度量得分:

请注意,precision_recall_curve函数仅适用于二分类情况。average_precision_score函数通过以一对多(OvR)的方式计算每个类别的得分,并根据其average参数的值进行平均,从而支持多类和多标签格式。

PrecisionRecallDisplay.from_estimatorPrecisionRecallDisplay.from_predictions函数将绘制精确率-召回率曲线,如下所示。

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP

示例:

  • 有关使用网格搜索和嵌套交叉验证估计参数的precision_scorerecall_score用法示例,请参见sphx_glr_auto_examples_model_selection_plot_grid_search_digits.py
  • 有关使用precision_recall_curve评估分类器输出质量的用法示例,请参见sphx_glr_auto_examples_model_selection_plot_precision_recall.py

参考文献:

References:

[Manning2008]

C.D. Manning, P. Raghavan, H. Schütze, Introduction to Information Retrieval, 2008.

[Everingham2010]

M. Everingham, L. Van Gool, C.K.I. Williams, J. Winn, A. Zisserman, The Pascal Visual Object Classes (VOC) Challenge, IJCV 2010.

[Davis2006]

J. Davis, M. Goadrich, The Relationship Between Precision-Recall and ROC Curves, ICML 2006.

[Flach2015]

P.A. Flach, M. Kull, Precision-Recall-Gain Curves: PR Analysis Done Right, NIPS 2015.

二分类

在二分类任务中,术语“正”和“负”指的是分类器的预测,术语“真”和“假”指的是该预测是否与外部判断(有时称为“观察”)相对应。在这些定义的基础上,我们可以制定以下表格:

在这种情况下,我们可以定义精确率和召回率的概念:

precision = tp tp + fp , \text{precision} = \frac{\text{tp}}{\text{tp} + \text{fp}}, precision=tp+fptp,

recall = tp tp + fn , \text{recall} = \frac{\text{tp}}{\text{tp} + \text{fn}}, recall=tp+fntp,

(有时将召回率称为“敏感性”)

F-度量是精确率和召回率的加权调和平均值,其中精确率对平均值的贡献由某个参数 β \beta β加权:

F β = ( 1 + β 2 ) precision × recall β 2 precision + recall F_\beta = (1 + \beta^2) \frac{\text{precision} \times \text{recall}}{\beta^2 \text{precision} + \text{recall}} Fβ=(1+β2)β2precision+recallprecision×recall

为了避免在精确率和召回率为零时除以零,Scikit-Learn使用以下等价公式计算F-度量:

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

请注意,当没有真正的阳性、假阳性或假阴性时,该公式仍未定义。默认情况下,对于一组完全为真阴性的情况,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...
多类和多标签分类

在多类和多标签分类任务中,精确率、召回率和F-度量的概念可以分别应用于每个标签。有几种方法可以通过average_precision_scoref1_scorefbeta_scoreprecision_recall_fscore_supportprecision_scorerecall_score函数中的average参数来组合跨标签的结果,如上所述。请注意,如果包括所有标签,则在多类设置中进行“微观”平均将产生精确率、召回率和 F F F都与准确率相同的结果。还要注意,“加权”平均可能会产生不在精确率和召回率之间的F-度量。

为了更明确地说明这一点,考虑以下符号:

  • y y y 是真实的 ( s a m p l e , l a b e l ) (sample, label) (sample,label)对的集合
  • y ^ \hat{y} y^ 是预测的 ( s a m p l e , l a b e l ) (sample, label) (sample,label)对的集合
  • L L L 是标签的集合
  • S S S 是样本的集合
  • y s y_s ys 是具有样本 s s s y y y的子集,即 y s : = { ( s ′ , l ) ∈ y ∣ s ′ = s } y_s := \left\{(s', l) \in y | s' = s\right\} ys:={(s,l)ys=s}
  • y l y_l yl 是具有标签 l l l y y y的子集
  • 类似地, y ^ s \hat{y}_s y^s y ^ l \hat{y}_l y^l y ^ \hat{y} y^ 的子集
  • P ( A , B ) : = ∣ A ∩ B ∣ ∣ B ∣ P(A, B) := \frac{\left| A \cap B \right|}{\left|B\right|} P(A,B):=BAB,其中 A A A B B B 是一些集合
  • R ( A , B ) : = ∣ A ∩ B ∣ ∣ A ∣ R(A, B) := \frac{\left| A \cap B \right|}{\left|A\right|} R(A,B):=AAB(关于处理 A = ∅ A = \emptyset A= 的约定有所不同;此实现使用 R ( A , B ) : = 0 R(A, B):=0 R(A,B):=0 P P P 的情况类似。)
  • F β ( A , B ) : = ( 1 + β 2 ) P ( A , B ) × R ( A , B ) β 2 P ( A , B ) + R ( A , B ) 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)} Fβ(A,B):=(1+β2)β2P(A,B)+R(A,B)P(A,B)×R(A,B)

然后,这些度量可以定义为:

>>> 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...

杰卡德相似系数

jaccard_score 函数计算标签集之间的杰卡德相似系数的平均值,也称为杰卡德指数。

杰卡德相似系数是通过真实标签集 y y y 和预测标签集 y ^ \hat{y} y^ 计算得到的,定义如下:

J ( y , y ^ ) = ∣ y ∩ y ^ ∣ ∣ y ∪ y ^ ∣ . J(y, \hat{y}) = \frac{|y \cap \hat{y}|}{|y \cup \hat{y}|}. J(y,y^)=yy^yy^.

jaccard_score 函数(与 precision_recall_fscore_support 类似)本身适用于二元目标。通过对集合进行计算,可以扩展到适用于多标签和多类别问题,通过使用平均值(见上文中的 average)。

对于二元问题:

>>> 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...

对于二维比较问题(例如图像相似性):

对于具有二进制标签指示符的多标签问题:

>>> 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...

合页损失

hinge_loss 函数计算模型与数据之间的平均距离,使用的是合页损失,这是一种只考虑预测错误的单侧度量(合页损失用于最大间隔分类器,如支持向量机)。

如果二元分类任务的真实标签 y i y_i yi 编码为 y i = { − 1 , + 1 } y_i=\left\{-1, +1\right\} yi={1,+1},对于每个样本 i i i w i w_i wi 是相应的预测决策(由 decision_function 方法输出的形状为 (n_samples,) 的数组),则合页损失定义如下:

L Hinge ( y , w ) = 1 n samples ∑ i = 0 n samples − 1 max ⁡ { 1 − w i y i , 0 } 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\} LHinge(y,w)=nsamples1i=0nsamples1max{1wiyi,0}

如果有多于两个标签,则 hinge_loss 使用 Crammer & Singer 的多类别变体。这里是描述该方法的论文。

在这种情况下,预测决策是形状为 (n_samples, n_labels) 的数组。如果 w i , y i w_{i, y_i} wi,yi 是第 i i i 个样本的真实标签 y i y_i yi 的预测决策; w ^ i , y i = max ⁡ { w i , y j   ∣   y j ≠ y i } \hat{w}_{i, y_i} = \max\left\{w_{i, y_j}~|~y_j \ne y_i \right\} w^i,yi=max{wi,yj  yj=yi}​ 是所有其他标签的预测决策的最大值,则多类别合页损失定义如下:
$$
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...

对数损失

对数损失(也称为逻辑回归损失或交叉熵损失)是基于概率估计定义的。它通常用于(多项式)逻辑回归和神经网络,以及某些期望最大化算法的变体,并且可以用于评估分类器的概率输出(predict_proba)而不是其离散预测。

对于二元分类,真实标签 y ∈ { 0 , 1 } y \in \{0,1\} y{0,1} 和概率估计 p = Pr ⁡ ( y = 1 ) p = \operatorname{Pr}(y = 1) p=Pr(y=1),每个样本的对数损失是分类器给定真实标签的负对数似然:

L log ⁡ ( y , p ) = − log ⁡ Pr ⁡ ( y ∣ p ) = − ( y log ⁡ ( p ) + ( 1 − y ) log ⁡ ( 1 − p ) ) L_{\log}(y, p) = -\log \operatorname{Pr}(y|p) = -(y \log (p) + (1 - y) \log (1 - p)) Llog(y,p)=logPr(yp)=(ylog(p)+(1y)log(1p))
L log ⁡ ( Y , P ) = − log ⁡ Pr ⁡ ( Y ∣ P ) = − 1 N ∑ i = 0 N − 1 ∑ k = 0 K − 1 y i , k log ⁡ p i , k 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} Llog(Y,P)=logPr(YP)=N1i=0N1k=0K1yi,klogpi,k

为了看到这个公式如何推广到上面给出的二分类对数损失,注意在二分类情况下, p i , 0 = 1 − p i , 1 p_{i,0} = 1 - p_{i,1} pi,0=1pi,1 y i , 0 = 1 − y i , 1 y_{i,0} = 1 - y_{i,1} yi,0=1yi,1,所以将内部求和展开,得到二分类对数损失。

log_loss 函数根据真实标签列表和概率矩阵计算对数损失,概率矩阵是由估计器的 predict_proba 方法返回的。

y_pred 中的第一个 [.9, .1] 表示第一个样本标签为 0 的概率为 90%。对数损失是非负的。

马修斯相关系数

matthews_corrcoef 函数计算二分类情况下的 马修斯相关系数 (MCC)。引用维基百科的解释:

在二分类情况下, t p tp tp t n tn tn f p fp fp f n fn fn 分别是真正例、真反例、假正例和假反例的数量,MCC 的定义如下:

M C C = t p × t n − f p × f n ( t p + f p ) ( t p + f n ) ( t n + f p ) ( t n + f n ) . MCC = \frac{tp \times tn - fp \times fn}{\sqrt{(tp + fp)(tp + fn)(tn + fp)(tn + fn)}}. MCC=(tp+fp)(tp+fn)(tn+fp)(tn+fn) tp×tnfp×fn.

在多分类情况下,马修斯相关系数可以根据 K K K 类的 confusion_matrix C C C 定义。为了简化定义,考虑以下中间变量:

  • t k = ∑ i K C i k t_k=\sum_{i}^{K} C_{ik} tk=iKCik 类别 k k k 真实出现的次数,
  • p k = ∑ i K C k i p_k=\sum_{i}^{K} C_{ki} pk=iKCki 类别 k k k 被预测的次数,
  • c = ∑ k K C k k c=\sum_{k}^{K} C_{kk} c=kKCkk 正确预测的样本总数,
  • s = ∑ i K ∑ j K C i j s=\sum_{i}^{K} \sum_{j}^{K} C_{ij} s=iKjKCij 样本总数。

那么多分类 MCC 的定义如下:

M C C = c × s − ∑ k K p k × t k ( s 2 − ∑ k K p k 2 ) × ( s 2 − ∑ k K t k 2 ) 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=(s2kKpk2)×(s2kKtk2) c×skKpk×tk

当标签数量超过两个时,MCC 的取值范围不再是 -1 到 +1。最小值将在 -1 到 0 之间,具体取决于真实标签的数量和分布。最大值始终为 +1。

下面是一个使用 matthews_corrcoef 函数的小例子:

>>> 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...

多标签混淆矩阵

multilabel_confusion_matrix 函数计算类别级别(默认)或样本级别(samplewise=True)的多标签混淆矩阵,用于评估分类的准确性。multilabel_confusion_matrix 还将多类数据视为多标签数据,因为这是一种常用的转换,用于使用二分类指标(如精确度、召回率等)评估多类问题。

在计算类别级别的多标签混淆矩阵 C C C 时,类别 i i i 的真反例数量为 C i , 0 , 0 C_{i,0,0} Ci,0,0,假反例数量为 C i , 1 , 0 C_{i,1,0} Ci,1,0,真正例数量为 C i , 1 , 1 C_{i,1,1} Ci,1,1,假正例数量为 C i , 0 , 1 C_{i,0,1} Ci,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]],
<BLANKLINE>
       [[1, 0],
        [0, 1]],
<BLANKLINE>
       [[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]],
<BLANKLINE>
       [[5, 0],
        [1, 0]],
<BLANKLINE>
       [[2, 1],
        [1, 2]]])

下面是一些示例,演示如何使用 multilabel_confusion_matrix 函数计算每个类别的召回率(或灵敏度)、特异度、误报率和漏报率。这些示例使用多标签指示矩阵作为输入。

计算每个类别的召回率(也称为真正例率或灵敏度):

>>> 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. ])

计算每个类别的特异度(也称为真反例率):

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

计算每个类别的误报率(也称为假正例率):

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

计算每个类别的漏报率(也称为假反例率):

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

受试者工作特征曲线(ROC)

roc_curve 函数计算受试者工作特征曲线(ROC 曲线)。引用维基百科的解释:

此函数需要真实的二进制值和目标分数,目标分数可以是正类的概率估计、置信度值或二进制决策。下面是如何使用 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 ])

与诸如子集准确度、汉明损失或 F1 分数等度量相比,ROC 不需要为每个标签优化阈值。
下图显示了一个分类器用于区分iris_dataset中的virginica花和其他物种的ROC曲线和ROC-AUC分数:

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP

更多信息请参见Wikipedia关于AUC的文章

二分类情况

二分类情况下,您可以使用分类器的predict_proba()方法提供概率估计,或者使用分类器的decision_function()方法提供未经阈值处理的决策值。如果提供概率估计,则应提供“较大标签”的类的概率。 "较大标签"对应于classifier.classes_[1]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...
多类别情况

roc_auc_score函数也可以用于多类别分类。目前支持两种平均策略:一对一算法计算成对ROC AUC分数的平均值,一对其余算法计算每个类别与所有其他类别的ROC AUC分数的平均值。在两种情况下,预测的标签以值从0到n_classes的数组形式提供,分数对应于样本属于特定类别的概率估计。OvO和OvR算法支持均匀加权(average='macro')和按流行度加权(average='weighted')。

一对一算法:计算所有可能的类别对的平均AUC。定义了一个均匀加权的多类别AUC度量:

1 c ( c − 1 ) ∑ j = 1 c ∑ k > j c ( AUC ( j ∣ k ) + AUC ( k ∣ j ) ) \frac{1}{c(c-1)}\sum_{j=1}^{c}\sum_{k > j}^c (\text{AUC}(j | k) + \text{AUC}(k | j)) c(c1)1j=1ck>jc(AUC(jk)+AUC(kj))

其中 c c c是类别数, AUC ( j ∣ k ) \text{AUC}(j | k) AUC(jk)是以类别 j j j为正类,类别 k k k为负类的AUC。一般来说,在多类别情况下, AUC ( j ∣ k ) ≠ AUC ( k ∣ j ) \text{AUC}(j | k) \neq \text{AUC}(k | j) AUC(jk)=AUC(kj)。通过将关键字参数multiclass设置为'ovo'average设置为'macro'来使用此算法。

[HT2001]多类别AUC度量可以通过流行度加权:

1 c ( c − 1 ) ∑ j = 1 c ∑ k > j c p ( j ∪ k ) ( AUC ( j ∣ k ) + AUC ( k ∣ j ) ) \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(c1)1j=1ck>jcp(jk)(AUC(jk)+AUC(kj))

其中 c c c是类别数。通过将关键字参数multiclass设置为'ovo'average设置为'weighted'来使用此算法。'weighted'选项返回按流行度加权的平均值,如[FC2009]中所述。

一对其余算法:计算每个类别与其他类别的AUC[PD2000]。该算法在功能上与多标签情况相同。要启用此算法,请将关键字参数multiclass设置为'ovr'。除了'macro'[F2006]和'weighted'[F2001]平均外,OvR还支持'micro'平均。

在不可容忍高假阳性率的应用中,可以使用roc_auc_scoremax_fpr参数来总结ROC曲线达到给定限制。

下图显示了用于区分iris_dataset中不同物种的分类器的微平均ROC曲线及其对应的ROC-AUC分数:

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP

多标签情况

多标签分类中,roc_auc_score函数通过对标签进行平均来扩展为above <average>。在这种情况下,应提供形状为(n_samples, n_classes)的y_score。因此,当使用概率估计时,需要为每个输出选择具有更大标签的类的概率。

>>> 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...])

示例:

  • 有关使用ROC评估分类器输出质量的示例,请参见sphx_glr_auto_examples_model_selection_plot_roc.py
  • 有关使用ROC评估分类器输出质量的交叉验证示例,请参见sphx_glr_auto_examples_model_selection_plot_roc_crossval.py
  • 有关使用ROC建模物种分布的示例,请参见sphx_glr_auto_examples_applications_plot_species_distribution_modeling.py

参考文献:

检测错误权衡(DET)

函数det_curve计算检测错误权衡(DET)曲线[WikipediaDET2017]。引用维基百科:

DET曲线是接收器操作特征(ROC)曲线的一种变体,其中在y轴上绘制的是假阴性率,而不是真阳性率。通过使用 ϕ − 1 \phi^{-1} ϕ1(其中 ϕ \phi ϕ是累积分布函数)对正态偏差进行转换,DET曲线通常以正态偏差尺度绘制。结果性能曲线明确可视化了给定分类算法的错误类型权衡。有关示例和进一步动机,请参见[Martin1997]。

该图比较了两个示例分类器在相同分类任务上的ROC曲线和DET曲线:

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP

属性:

  • 如果检测分数服从正态(或接近正态)分布,则DET曲线在正态偏差尺度上形成线性曲线。[Navratil2007]表明反过来不一定成立,甚至更一般的分布也能产生线性DET曲线。
  • 正态偏差尺度变换使得点扩散开,从而占据了相对较大的绘图空间。因此,在DET图上可能更容易区分具有类似分类性能的曲线。
  • 由于假阴性率与真阳性率“相反”,DET曲线的完美点是原点(与ROC曲线的左上角相反)。

应用和限制:
另一方面,DET曲线并不以单个数字的形式提供其度量结果。因此,无论是自动评估还是与其他分类任务进行比较,派生的ROC曲线下面积可能更适合。

示例:

  • 请参阅sphx_glr_auto_examples_model_selection_plot_det.py,了解接收器操作特性(ROC)曲线和检测错误权衡(DET)曲线之间的比较示例。

参考文献:

[WikipediaDET2017]

Wikipedia contributors. Detection error tradeoff. Wikipedia, The Free Encyclopedia. September 4, 2017, 23:33 UTC. Available at: https://en.wikipedia.org/w/index.php?title=Detection_error_tradeoff&oldid=798982054. Accessed February 19, 2018.

[Martin1997]

A. Martin, G. Doddington, T. Kamm, M. Ordowski, and M. Przybocki, The DET Curve in Assessment of Detection Task Performance, NIST 1997.

[Navratil2007]

J. Navractil and D. Klusacek, “On Linear DETs,” 2007 IEEE International Conference on Acoustics, Speech and Signal Processing - ICASSP ‘07, Honolulu, HI, 2007, pp. IV-229-IV-232.

零一损失

zero_one_loss函数计算 n samples n_{\text{samples}} nsamples个样本上的0-1分类损失( L 0 − 1 L_{0-1} L01)的总和或平均值。默认情况下,该函数对样本进行归一化。要获取 L 0 − 1 L_{0-1} L01的总和,请将normalize设置为False

在多标签分类中,如果标签严格匹配预测结果,则将子集视为1,如果存在任何错误,则视为0。默认情况下,该函数返回不完美预测子集的百分比。要获取这些子集的计数,请将normalize设置为False

如果 y ^ i \hat{y}_i y^i是第 i i i个样本的预测值, y i y_i yi是相应的真实值,则0-1损失 L 0 − 1 L_{0-1} L01定义为:

L 0 − 1 ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 1 ( y ^ i ≠ y i ) 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) L01(y,y^)=nsamples1i=0nsamples11(y^i=yi)

其中 1 ( x ) 1(x) 1(x)指示函数。零一损失也可以计算为 z e r o − o n e l o s s = 1 − a c c u r a c y zero-one loss = 1 - accuracy zerooneloss=1accuracy

>>> 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

示例:

  • 请参阅sphx_glr_auto_examples_feature_selection_plot_rfe_with_cross_validation.py,了解使用零一损失进行带交叉验证的递归特征消除的示例。

布里尔分数损失

brier_score_loss函数计算二元类别的布里尔分数 。引用维基百科的说法:

该函数返回实际结果 y ∈ { 0 , 1 } y \in \{0,1\} y{0,1}和预测概率估计 p = Pr ⁡ ( y = 1 ) p = \operatorname{Pr}(y = 1) p=Pr(y=1)predict_proba)之间的均方误差:

B S = 1 n samples ∑ i = 0 n samples − 1 ( y i − p i ) 2 BS = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1}(y_i - p_i)^2 BS=nsamples1i=0nsamples1(yipi)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

布里尔分数可以用于评估分类器的校准程度。然而,较低的布里尔分数损失并不总是意味着更好的校准。这是因为,类似于均方误差的偏差-方差分解,布里尔分数损失可以分解为校准损失和改进损失的总和。校准损失定义为从ROC曲线斜率导出的经验概率的均方偏差。改进损失可以定义为通过最优代价曲线下面积测量的预期最优损失。改进损失可以独立于校准损失而改变,因此较低的布里尔分数损失并不一定意味着更好的校准模型。只有当改进损失保持不变时,较低的布里尔分数损失才总是意味着更好的校准,。

示例:

  • 请参阅sphx_glr_auto_examples_calibration_plot_calibration.py,了解使用布里尔分数损失对分类器进行概率校准的示例。

参考文献:

类别似然比

class_likelihood_ratios函数计算二元类别的正似然比负似然比 L R ± LR_\pm LR±,可以解释为预测前后的先验概率与后验概率的比值。因此,该度量在类别患病率(阳性类别样本数除以总样本数)不平衡的情况下,可以在不考虑任何可能的类别不平衡的情况下在不同群体之间进行推广

因此,在学习和评估分类器的数据是一个几乎平衡类别的研究人群(例如病例对照研究)的情况下, L R ± LR_\pm LR±度量非常有用,而目标应用(即一般人群)的患病率非常低。

正似然比 L R + LR_+ LR+是分类器正确预测样本属于阳性类别的概率与将阴性类别样本预测为阳性类别的概率之比:

L R + = PR ( P + ∣ T + ) PR ( P + ∣ T − ) . LR_+ = \frac{\text{PR}(P+|T+)}{\text{PR}(P+|T-)}. LR+=PR(P+T)PR(P+T+).

这里的符号表示预测( P P P)或真实( T T T)标签,符号 + + + − - 表示阳性和阴性类别,例如 P + P+ P+表示“预测为阳性”。

类似地,负似然比 L R − LR_- LR是阳性类别样本被分类为阴性类别的概率与阴性类别样本被正确分类的概率之比:

L R − = PR ( P − ∣ T + ) PR ( P − ∣ T − ) . LR_- = \frac{\text{PR}(P-|T+)}{\text{PR}(P-|T-)}. LR=PR(PT)PR(PT+).

对于高于随机的分类器, L R + LR_+ LR+大于1越高越好,而 L R − LR_- LR在0到1之间,越低越好。 L R ± ≈ 1 LR_\pm\approx 1 LR±1的值对应于随机水平。

请注意,概率与计数不同,例如 PR ⁡ ( P + ∣ T + ) \operatorname{PR}(P+|T+) PR(P+T+)不等于真正阳性计数tp(请参阅维基百科页面获取实际公式)。

在不同患病率下的解释:

两个类别似然比可以解释为赔率比(先验和后验测试):

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

赔率通常通过概率关系:

odds = probability 1 − probability , \text{odds} = \frac{\text{probability}}{1 - \text{probability}}, odds=1probabilityprobability,

或等价地

probability = odds 1 + odds . \text{probability} = \frac{\text{odds}}{1 + \text{odds}}. probability=1+oddsodds.

在给定人群上,先验概率由患病率给出。通过将赔率转换为概率,可以将似然比转化为分类器预测之前和之后属于任一类别的概率:

post-test odds = Likelihood ratio × pre-test probability 1 − pre-test probability , \text{post-test odds} = \text{Likelihood ratio} \times \frac{\text{pre-test probability}}{1 - \text{pre-test probability}}, post-test odds=Likelihood ratio×1pre-test probabilitypre-test probability,

post-test probability = post-test odds 1 + post-test odds . \text{post-test probability} = \frac{\text{post-test odds}}{1 + \text{post-test odds}}. post-test probability=1+post-test oddspost-test odds.

数学差异:

f p = 0 fp = 0 fp=0时,正似然比未定义,这可以解释为分类器完全识别阳性病例。如果 f p < n samples fp < n_{\text{samples}} fp<nsamples,则负似然比未定义,这可以解释为分类器完全识别阴性病例。在这两种情况下,将 f p fp fp设置为一个非常小的正数,以避免除以零。

示例:

  • 请参阅sphx_glr_auto_examples_plot_roc_crossval.py,了解使用类别似然比计算二元分类器的ROC曲线和AUC的示例。

参考文献:
t n = 0 tn = 0 tn=0 时,负似然比 (negative likelihood ratio) 未定义。这种发散是无效的,因为 L R − > 1 LR_- > 1 LR>1 表示在将样本分类为负类后,样本属于正类的几率增加,就好像分类的行为导致了正类的出现。这包括了 DummyClassifier 总是预测正类的情况(即当 t n = f n = 0 tn=fn=0 tn=fn=0 时)。

t p = f n = 0 tp=fn=0 tp=fn=0 时,两种类别的似然比 (class likelihood ratios) 都未定义,这意味着测试集中没有正类样本。这也可能发生在交叉验证高度不平衡的数据中。

在上述所有情况下,class_likelihood_ratios 函数默认会引发适当的警告信息,并返回 nan,以避免在交叉验证折叠中进行平均时产生污染。

有关 class_likelihood_ratios 函数的详细演示,请参见下面的示例。

示例:

  • sphx_glr_auto_examples_model_selection_plot_likelihood_ratios.py

参考文献:

多标签排名指标

sklearn.metrics

在多标签学习中,每个样本可以与任意数量的真实标签相关联。目标是给予真实标签高分和更好的排名。

覆盖误差

coverage_error 函数计算必须包含在最终预测中的平均标签数量,以便预测所有真实标签。如果您想知道平均需要预测多少个得分最高的标签,以确保不会漏掉任何真实标签,这将非常有用。该指标的最佳值是真实标签的平均数量。

形式上,给定二进制指示矩阵的真实标签 y ∈ { 0 , 1 } n samples × n labels y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}} y{0,1}nsamples×nlabels 和与每个标签相关联的得分 f ^ ∈ R n samples × n labels \hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}} f^Rnsamples×nlabels,覆盖误差定义为

c o v e r a g e ( y , f ^ ) = 1 n samples ∑ i = 0 n samples − 1 max ⁡ j : y i j = 1 rank i j coverage(y, \hat{f}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1} \max_{j:y_{ij} = 1} \text{rank}_{ij} coverage(y,f^)=nsamples1i=0nsamples1j:yij=1maxrankij

其中 rank i j = ∣ { k : f ^ i k ≥ f ^ i j } ∣ \text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right| rankij= {k:f^ikf^ij} 。根据排名定义,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

标签排名平均精度

label_ranking_average_precision_score 函数实现了标签排名平均精度 (LRAP)。该指标与 average_precision_score 函数相关联,但基于标签排名的概念,而不是精确率和召回率。

标签排名平均精度 (LRAP) 对样本进行平均,回答以下问题:对于每个真实标签,排名更高的标签中有多少是真实标签?如果您能够为每个样本关联的标签提供更好的排名,这个性能指标将更高。得分始终严格大于 0,最佳值为 1。如果每个样本只有一个相关标签,则标签排名平均精度等同于平均倒数排名

形式上,给定二进制指示矩阵的真实标签 y ∈ { 0 , 1 } n samples × n labels y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}} y{0,1}nsamples×nlabels 和与每个标签相关联的得分 f ^ ∈ R n samples × n labels \hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}} f^Rnsamples×nlabels,平均精度定义为

L R A P ( y , f ^ ) = 1 n samples ∑ i = 0 n samples − 1 1 ∣ ∣ y i ∣ ∣ 0 ∑ j : y i j = 1 ∣ L i j ∣ rank i j 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}} LRAP(y,f^)=nsamples1i=0nsamples1∣∣yi01j:yij=1rankijLij

其中 L i j = { k : y i k = 1 , f ^ i k ≥ f ^ i j } \mathcal{L}_{ij} = \left\{k: y_{ik} = 1, \hat{f}_{ik} \geq \hat{f}_{ij} \right\} Lij={k:yik=1,f^ikf^ij} rank i j = ∣ { k : f ^ i k ≥ f ^ i j } ∣ \text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right| rankij= {k:f^ikf^ij} ∣ ⋅ ∣ |\cdot| 计算集合的基数(即集合中元素的数量), ∣ ∣ ⋅ ∣ ∣ 0 ||\cdot||_0 ∣∣0 ℓ 0 \ell_0 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...

排名损失

label_ranking_loss 函数计算排名损失,它对样本进行平均,计算标签对的数量,这些标签对的顺序不正确,即真实标签的得分低于错误标签的得分,权重为错误和真实标签的有序对数量的倒数。最低可达到的排名损失为零。

形式上,给定二进制指示矩阵的真实标签 y ∈ { 0 , 1 } n samples × n labels y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}} y{0,1}nsamples×nlabels 和与每个标签相关联的得分 f ^ ∈ R n samples × n labels \hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}} f^Rnsamples×nlabels,排名损失定义为

r a n k i n g _ l o s s ( y , f ^ ) = 1 n samples ∑ i = 0 n samples − 1 1 ∣ ∣ y i ∣ ∣ 0 ( n labels − ∣ ∣ y i ∣ ∣ 0 ) ∣ { ( k , l ) : f ^ i k ≤ f ^ i l , y i k = 1 , y i l = 0 } ∣ 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| ranking_loss(y,f^)=nsamples1i=0nsamples1∣∣yi0(nlabels∣∣yi0)1 {(k,l):f^ikf^il,yik=1,yil=0}

其中 ∣ ⋅ ∣ |\cdot| 计算集合的基数(即集合中元素的数量), ∣ ∣ ⋅ ∣ ∣ 0 ||\cdot||_0 ∣∣0 ℓ 0 \ell_0 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...
>>> # 使用以下预测,我们得到完美且最小的损失
>>> 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

参考文献:

  • Tsoumakas, G., Katakis, I., & Vlahavas, I. (2010). Mining multi-label data. In Data mining and knowledge discovery handbook (pp. 667-685). Springer US.

标准化折扣累积增益

折扣累积增益 (DCG) 和标准化折扣累积增益 (NDCG) 是 ~sklearn.metrics.dcg_score~sklearn.metrics.ndcg_score 中实现的排名指标;它们将预测的顺序与基准分数(例如查询答案的相关性)进行比较。

从维基百科关于折扣累积增益的页面:

“折扣累积增益 (DCG) 是一种衡量排名质量的指标。在信息检索中,它经常用于衡量网络搜索引擎算法或相关应用的效果。使用搜索引擎结果集中的文档的分级相关性标度,DCG 根据文档在结果列表中的位置衡量文档的有用性或增益。增益从结果列表的顶部到底部累积,每个结果的增益在较低的排名处被折扣”

与排序损失相比,NDCG可以考虑相关性分数,而不是真实排序。因此,如果真实排序只包含排序,应优先选择排序损失;如果真实排序包含实际的有用性分数(例如,无关为0,相关为1,非常相关为2),可以使用NDCG。

对于一个样本,给定每个目标 y ∈ R M y \in \mathbb{R}^{M} yRM的连续真实值向量,其中 M M M是输出的数量,以及预测值 y ^ \hat{y} y^,它引出了排名函数 f f f,DCG分数为

∑ r = 1 min ⁡ ( K , M ) y f ( r ) log ⁡ ( 1 + r ) \sum_{r=1}^{\min(K, M)}\frac{y_{f(r)}}{\log(1 + r)} r=1min(K,M)log(1+r)yf(r)

NDCG分数是DCG分数除以 y y y所得到的DCG分数。

参考文献:

  • 维基百科关于折扣累积增益的条目
  • Jarvelin, K., & Kekalainen, J. (2002). Cumulated gain-based evaluation of IR techniques. ACM Transactions on Information Systems (TOIS), 20(4), 422-446.
  • Wang, Y., Wang, L., Li, Y., He, D., Chen, W., & Liu, T. Y. (2013, May). A theoretical analysis of NDCG ranking measures. In Proceedings of the 26th Annual Conference on Learning Theory (COLT 2013)
  • McSherry, F., & Najork, M. (2008, March). Computing information retrieval performance measures efficiently in the presence of tied scores. In European conference on information retrieval (pp. 414-421). Springer, Berlin, Heidelberg.

回归指标

sklearn.metrics

sklearn.metrics模块实现了几个用于衡量回归性能的损失、得分和实用函数。其中一些已经增强以处理多输出情况:mean_squared_errormean_absolute_errorr2_scoreexplained_variance_scoremean_pinball_lossd2_pinball_scored2_absolute_error_score

这些函数有一个multioutput关键字参数,用于指定如何对每个单独的目标进行得分或损失的平均。默认值是'uniform_average',它指定了对输出进行均匀加权平均。如果传递了一个形状为(n_outputs,)ndarray,则其条目被解释为权重,并返回相应的加权平均。如果multioutput'raw_values',则所有未改变的单独得分或损失将以形状为(n_outputs,)的数组返回。

r2_scoreexplained_variance_score接受multioutput参数的附加值'variance_weighted'。此选项通过相应目标变量的方差对每个单独的得分进行加权。该设置量化了全局捕获的未缩放方差。如果目标变量具有不同的比例,则此得分更重视解释较高方差的变量。multioutput='variance_weighted'r2_score的默认值,以保持向后兼容性。将来将更改为uniform_average

R²得分,决定系数

r2_score函数计算决定系数,通常表示为 R 2 R^2 R2

它表示模型中独立变量解释的方差(y的方差)的比例。它提供了拟合优度的指示,因此是通过解释方差的比例来预测模型对未见样本的预测能力的度量。

由于方差是数据集相关的, R 2 R^2 R2在不同数据集之间可能没有可比性。最佳得分为1.0,可以是负数(因为模型可能任意糟糕)。一个始终预测y的期望(平均)值的常数模型,而不考虑输入特征,将得到一个 R 2 R^2 R2得分为0.0。

注意:当预测残差的均值为零时, R 2 R^2 R2得分和explained_variance_score是相同的。

如果 y ^ i \hat{y}_i y^i是第 i i i个样本的预测值, y i y_i yi是相应的真实值,对于总共 n n n个样本,估计的 R 2 R^2 R2定义为:

R 2 ( y , y ^ ) = 1 − ∑ i = 1 n ( y i − y ^ i ) 2 ∑ i = 1 n ( y i − y ˉ ) 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} R2(y,y^)=1i=1n(yiyˉ)2i=1n(yiy^i)2

其中 y ˉ = 1 n ∑ i = 1 n y i \bar{y} = \frac{1}{n} \sum_{i=1}^{n} y_i yˉ=n1i=1nyi ∑ i = 1 n ( y i − y ^ i ) 2 = ∑ i = 1 n ϵ i 2 \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} \epsilon_i^2 i=1n(yiy^i)2=i=1nϵi2

请注意,r2_score计算未经校正的未调整 R 2 R^2 R2,未校正y的样本方差的偏差。

在真实目标是常数的特殊情况下, R 2 R^2 R2得分是无限的:它要么是NaN(完美预测),要么是-Inf(不完美预测)。这样的非有限得分可能会阻止正确的模型优化,例如网格搜索交叉验证的正确执行。因此,r2_score的默认行为是将它们替换为1.0(完美预测)或0.0(不完美预测)。如果将force_finite设置为False,则此得分将回退到原始 R 2 R^2 R2定义。

以下是使用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

示例:

  • 有关使用R²得分评估稀疏信号上的Lasso和Elastic Net的示例,请参见sphx_glr_auto_examples_linear_model_plot_lasso_and_elasticnet.py

平均绝对误差

mean_absolute_error函数计算平均绝对误差,这是与绝对误差损失或 l 1 l1 l1-范数损失的期望值相对应的风险度量。

如果 y ^ i \hat{y}_i y^i是第 i i i个样本的预测值, y i y_i yi是相应的真实值,则在 n samples n_{\text{samples}} nsamples个样本上估计的平均绝对误差(MAE)定义为

MAE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ∣ y i − y ^ i ∣ . \text{MAE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \left| y_i - \hat{y}_i \right|. MAE(y,y^)=nsamples1i=0nsamples1yiy^i.

以下是使用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...

均方误差

mean_squared_error函数计算均方误差,这是与平方(二次)误差或损失的期望值相对应的风险度量。

如果 y ^ i \hat{y}_i y^i是第 i i i个样本的预测值, y i y_i yi是相应的真实值,则在 n samples n_{\text{samples}} nsamples个样本上估计的均方误差(MSE)定义为

MSE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ( y i − y ^ i ) 2 . \text{MSE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} (y_i - \hat{y}_i)^2. MSE(y,y^)=nsamples1i=0nsamples1(yiy^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)
>>> 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...

示例:

  • 有关均方误差用于评估梯度提升回归的示例,请参见sphx_glr_auto_examples_ensemble_plot_gradient_boosting_regression.py

将均方误差的平方根,称为均方根误差(RMSE),作为提供与目标变量相同单位的度量的另一种常见度量。RMSE 可通过 root_mean_squared_error 函数获得。

均方对数误差

mean_squared_log_error 函数计算与预期的平方对数(二次)误差或损失相对应的风险度量。

如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,则在 n samples n_{\text{samples}} nsamples 上估计的均方对数误差(MSLE)定义为

MSLE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ( log ⁡ e ( 1 + y i ) − log ⁡ e ( 1 + y ^ i ) ) 2 . \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. MSLE(y,y^)=nsamples1i=0nsamples1(loge(1+yi)loge(1+y^i))2.

其中 log ⁡ e ( x ) \log_e (x) loge(x) 表示 x 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 函数获得。

平均绝对百分比误差

mean_absolute_percentage_error(MAPE),也称为平均绝对百分比偏差(MAPD),是回归问题的评估度量。该度量的思想是对相对误差敏感。例如,它不会受到目标变量的整体缩放的影响。

如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,则在 n samples n_{\text{samples}} nsamples 上估计的平均绝对百分比误差(MAPE)定义为

MAPE ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 ∣ y i − y ^ i ∣ max ⁡ ( ϵ , ∣ y i ∣ ) \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|)} MAPE(y,y^)=nsamples1i=0nsamples1max(ϵ,yi)yiy^i

其中 ϵ \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 的情况下,这个问题得到了解决,因为它计算了相对百分比误差与实际输出相关。

中位绝对误差

median_absolute_error 特别有趣,因为它对异常值具有鲁棒性。该损失通过取目标和预测之间的所有绝对差异的中位数来计算。

如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,则在 n samples n_{\text{samples}} nsamples 上估计的中位绝对误差(MedAE)定义为

MedAE ( y , y ^ ) = median ( ∣ y 1 − y ^ 1 ∣ , … , ∣ y n − y ^ n ∣ ) . \text{MedAE}(y, \hat{y}) = \text{median}(\mid y_1 - \hat{y}_1 \mid, \ldots, \mid y_n - \hat{y}_n \mid). MedAE(y,y^)=median(y1y^1,,yny^n).

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

最大误差

max_error 函数计算预测值和真实值之间的最大残差误差,这是一种捕捉预测值和真实值之间最坏情况误差的度量。在一个完美拟合的单输出回归模型中,max_error 在训练集上为 0,虽然在现实世界中这种情况极不可能发生,但该度量显示了模型在拟合时的误差程度。

如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,则最大误差定义为

Max Error ( y , y ^ ) = max ⁡ ( ∣ y i − y ^ i ∣ ) \text{Max Error}(y, \hat{y}) = \max(| y_i - \hat{y}_i |) Max Error(y,y^)=max(yiy^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 不支持多输出。

解释方差得分

explained_variance_score 计算解释方差回归得分

如果 y ^ \hat{y} y^ 是估计的目标输出, y y y 是相应的(正确的)目标输出, V a r Var Var方差,即标准差的平方,则解释方差估计如下:

e x p l a i n e d _ v a r i a n c e ( y , y ^ ) = 1 − V a r { y − y ^ } V a r { y } explained\_{}variance(y, \hat{y}) = 1 - \frac{Var\{ y - \hat{y}\}}{Var\{y\}} explained_variance(y,y^)=1Var{y}Var{yy^}

最佳得分为 1.0,较低的值表示较差。

链接到 r2_score

解释方差得分与 r2_score 的区别在于解释方差得分不考虑预测中的系统偏差。因此,通常应优先选择 r2_score

在真实目标是常数的特殊情况下,解释方差得分不是有限的:它要么是 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

均值泊松、伽玛和 Tweedie 偏差

mean_tweedie_deviance 函数计算具有 power 参数 ( p p p) 的均值 Tweedie 偏差误差。这是一种引出回归目标的预测期望值的度量。

存在以下特殊情况,

  • power=0 时,它等同于 mean_squared_error
  • power=1 时,它等同于 mean_poisson_deviance
    如果 y ^ i \hat{y}_i y^i 是第 i i i 个样本的预测值, y i y_i yi 是相应的真实值,那么对于给定的功率 p p p,在 n samples n_{\text{samples}} nsamples 个样本上估计的 Tweedie 偏差误差 (D) 定义如下:

D ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 { ( y i − y ^ i ) 2 , 当  p = 0  (正态分布) 2 ( y i log ⁡ ( y i / y ^ i ) + y ^ i − y i ) , 当  p = 1  (泊松分布) 2 ( log ⁡ ( y ^ i / y i ) + y i / y ^ i − 1 ) , 当  p = 2  (伽马分布) 2 ( max ⁡ ( y i , 0 ) 2 − p ( 1 − p ) ( 2 − p ) − y i   y ^ i 1 − p 1 − p + y ^ i 2 − p 2 − p ) , 其他情况 \begin{aligned} \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{当 }p=0\text{ (正态分布)}\\ 2(y_i \log(y_i/\hat{y}_i) + \hat{y}_i - y_i), & \text{当 }p=1\text{ (泊松分布)}\\ 2(\log(\hat{y}_i/y_i) + y_i/\hat{y}_i - 1), & \text{当 }p=2\text{ (伽马分布)}\\ 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{其他情况} \end{cases} \end{aligned} D(y,y^)=nsamples1i=0nsamples1 (yiy^i)2,2(yilog(yi/y^i)+y^iyi),2(log(y^i/yi)+yi/y^i1),2((1p)(2p)max(yi,0)2p1pyiy^i1p+2py^i2p), p=0 (正态分布) p=1 (泊松分布) p=2 (伽马分布)其他情况

Tweedie 偏差是一个关于 2-power 的齐次函数。因此,当 power=2 时,伽马分布意味着同时缩放 y_truey_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 时,偏差只对相对误差敏感。

分位数损失

mean_pinball_loss 函数用于评估分位数回归模型的预测性能。

pinball ( y , y ^ ) = 1 n samples ∑ i = 0 n samples − 1 α max ⁡ ( y i − y ^ i , 0 ) + ( 1 − α ) max ⁡ ( y ^ i − y i , 0 ) \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(y,y^)=nsamples1i=0nsamples1αmax(yiy^i,0)+(1α)max(y^iyi,0)

当分位数参数 alpha 设置为 0.5 时,损失值等于 mean_absolute_error 的一半。

以下是使用 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...])

也可以为超参数调优构建评分器对象。为了确保较大的值意味着更好,必须改变损失的符号,具体解释请参见下面链接中的示例。

示例:

  • 有关在具有非对称噪声和异常值的数据上使用分位数回归模型评估和调优超参数的示例,请参见 sphx_glr_auto_examples_ensemble_plot_gradient_boosting_quantile.py

D² 分数

D² 分数计算解释的偏差比例。它是 R² 的一种推广,其中平方误差被选择的偏差 dev ( y , y ^ ) \text{dev}(y, \hat{y}) dev(y,y^)(例如 Tweedie、pinball 或平均绝对误差)替代。D² 是一种技能分数。它的计算方式如下:

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

其中 y null y_{\text{null}} ynull 是仅包含截距的模型的最佳预测(例如 Tweedie 情况下的 y_true 的均值,绝对误差的中位数,以及 pinball 损失的 alpha 分位数)。

与 R² 一样,最佳分数为 1.0,可能为负(因为模型可能任意糟糕)。一个始终预测 y null y_{\text{null}} ynull 的常数模型,不考虑输入特征,D² 分数为 0.0。

D² Tweedie 分数

d2_tweedie_score 函数实现了 D² 的特殊情况,其中 dev ( y , y ^ ) \text{dev}(y, \hat{y}) dev(y,y^) 是 Tweedie 偏差,参见 mean_tweedie_deviance。它也被称为 D² Tweedie,与 McFadden 的似然比指数有关。

参数 power 定义了 Tweedie 功率,与 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)
D² pinball 分数

d2_pinball_score 函数实现了带有 pinball 损失的 D² 的特殊情况,参见 pinball_loss,即:

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

参数 alpha 定义了 pinball 损失的斜率,与 mean_pinball_loss (pinball_loss) 相同。它确定了 pinball 损失和 D² 最优的分位数水平 alpha。请注意,对于 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)
D² 绝对误差分数

d2_absolute_error_score 函数实现了 mean_absolute_error 的特殊情况:

dev ( y , y ^ ) = MAE ( y , y ^ ) . \text{dev}(y, \hat{y}) = \text{MAE}(y, \hat{y}). dev(y,y^)=MAE(y,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

回归模型的可视化评估

在评估回归模型质量的方法中,scikit-learn 提供了 ~sklearn.metrics.PredictionErrorDisplay 类。它允许以两种不同的方式可视化检查模型的预测误差。

Scikit-Learn 1.4使用指南:模型选择和评估 评估预测质量的度量和评分-LMLPHP
请注意,上述内容仅在预测值是给定 X 的 y 的期望值时成立。这通常适用于最小化均方误差目标函数或更一般地说,对于任何 “power” 参数的 mean Tweedie deviance <mean_tweedie_deviance> 的回归模型。

当绘制一个预测给定 X 的 y 的分位数的估计器的预测结果时,例如 ~sklearn.linear_model.QuantileRegressor 或任何其他最小化 pinball loss <pinball_loss> 的模型,一部分点预计会在对角线上方或下方,具体取决于估计的分位数水平。

总的来说,虽然这个图表很直观易读,但它并不能告诉我们如何获得更好的模型。

右侧的图表显示了残差(即实际值与预测值之间的差异)与预测值之间的关系。

这个图表可以更容易地可视化残差是否遵循 同方差性或异方差性 分布。

特别是,如果 y|X 的真实分布是泊松分布或伽马分布,那么预期最佳模型的残差方差将随着 E[y|X] 的预测值的增加而增加(对于泊松分布是线性增加,对于伽马分布是二次增加)。

当拟合线性最小二乘回归模型(参见 ~sklearn.linear_model.LinearRegression~sklearn.linear_model.Ridge)时,我们可以使用这个图表来检查是否满足一些 模型假设,特别是残差应该是不相关的,它们的期望值应该为零,它们的方差应该是恒定的(同方差性)。

如果不满足这些条件,特别是如果残差图显示出一些香蕉形状的结构,这提示模型可能被错误指定,并且非线性特征工程或切换到非线性回归模型可能是有用的。

参考下面的示例,了解如何使用这个显示来进行模型评估。

示例:

  • 有关如何使用 ~sklearn.metrics.PredictionErrorDisplay 来可视化在学习之前转换目标后回归模型的预测质量改进的示例,请参见 sphx_glr_auto_examples_compose_plot_transformed_target.py

聚类度量

sklearn.metrics

sklearn.metrics 模块实现了几个损失、得分和实用函数。有关更多信息,请参见 clustering_evaluation 部分,例如聚类评估,以及 biclustering_evaluation 部分,例如双聚类。

虚拟估计器

sklearn.dummy

在进行监督学习时,一个简单的合理性检查是将自己的估计器与一些简单的经验法则进行比较。DummyClassifier 实现了几种用于分类的简单策略:

  • stratified 通过遵守训练集类别分布生成随机预测。

  • most_frequent 总是预测训练集中最频繁的标签。

  • prior 总是预测使类别先验最大化的类别(类似于 most_frequent),并且 predict_proba 返回类别先验。

  • uniform 以均匀随机的方式生成预测。

  • constant 总是预测用户提供的常量标签。
    这种方法的一个主要动机是 F1 得分,当正类是少数类时。

请注意,使用所有这些策略时,predict 方法完全忽略输入数据!

为了说明 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)

接下来,让我们比较 SVCmost_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 的准确率并没有比虚拟分类器好多少。现在,让我们改变核函数:

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

我们可以看到准确率提高到了接近100%。建议使用交叉验证策略来更好地估计准确率,如果计算成本不太高的话。有关更多信息,请参见 cross_validation 部分。此外,如果要优化参数空间,强烈建议使用适当的方法;有关详细信息,请参见 grid_search 部分。

总的来说,当分类器的准确率接近随机时,这可能意味着出现了一些问题:特征无效,超参数调整不正确,分类器受到类别不平衡的影响等等…

DummyRegressor 也为回归实现了四个简单的经验法则:

  • mean 总是预测训练目标的均值。
  • median 总是预测训练目标的中位数。
  • quantile 总是预测用户提供的训练目标的分位数。
  • constant 总是预测用户提供的常数值。

在所有这些策略中,predict 方法完全忽略输入数据。

02-07 13:38