3.3 指标和评分:量化预测的质量¶
3个不同的API可供评估模型预测质量:
评估器评分方法:评估器有一个score方法,它给计划解决的问题提供一个初始评估标准。这部分内容不在这里讨论,但会出现在每一个评估器的文件中。 评分参数:使用交叉验证(cross-validation)的模型评估方法(例如:[model_selection.cross_val_score和model_selection.GridSearchCV)基于一个内部评分策略。这部分内容将会在评分参数:定义模型评估规则。 指标函数:metrics模块执行的功能是评估特定目的的误差。这些指标在分类指标, 多标签排序指标, 回归指标和聚类指标部分会详细介绍。
最后,Dummy评估器(Dummy 评估器)可用于获取随机预测的这些指标基准值。
还可参见:对于“成对”指标,样本之间而不是评估器或者预测值之间,详见成对度量、亲和力和核函数部分。
3.3.1 评分参数:定义模型评估准则
模型选择和评估使用的工具,如model_selection, GridSearchCV和model_selection.cross_val_score,使用scoring参数控制对评估器的估计量应用的指标。
3.3.1.1 常见场景:预定义值
在最常见的例子中,可以给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. ])
>>> model = svm.SVC()
>>> cross_val_score(model, X, y, cv=5, scoring='wrong_choice')
Traceback (most recent call last):
ValueError: 'wrong_choice' is not a valid scoring value. Use sorted(sklearn.metrics.SCORERS.keys()) to get va
注意: ValueError列出的异常值对应于以下各节中说明的测量预测准确性函数。这些函数中的评分对象以字典形式存储在sklearn.metrics.SCORES中。
3.3.1.2 根据metric函数定义评分策略
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(), param_grid={'C': [1, 10]},
... scoring=ftwo_scorer, cv=5)
第二个例子是在简单python函数中使用make_scorer,以构建完全自定义评分对像,它可以接受几个参数:
可以使用的python函数(下例中使用my_custom_loss_func) 是否python函数返回一个分数(初始值为greater_is_better=True)或者一个损失(分数)(greater_is_better=False)。如果一个损失函数,python函数的返回值是负值的评分对象,符合交叉验证的传统,评分越高,模型越好。 仅对于分类的指标:是否python函数要求提供连续决定确定性(needs_threshold=True)。初始值是False。 任何其它参数,如f1_score中的beta或labels。
如下示例展示构建传统评分器,使用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(clf.predict(X), y)
0.69...
>>> score(clf, X, y)
-0.69...
3.3.1.3 执行自定义评分对象
无需使用make_scorer “制造厂”,就可以通过从头构建自定义评分对象,生成更加灵活的模型评分器。对于一个可调用的评分器,需要满足如下两个规定协议:
可以调用参数(estimator, X, y),estimator是需要被评估的模型,X是验证数据,y是X标签(应用于有监督的案例中)的真实值或者None(应用于非监督的案例中)。 它返回一个浮点型数值,该数值量化estimator对X关于y的预测质量。再强调一遍,越高的得分模型越好,所以如果得分是损失函数的返回值,那么该值应为负。
注意:当n_jobs>1时,函数中对传统评分器的使用
虽然在调用函数的旁边定义自定义评分函数应使用默认joblib backend(loky),但从另一个模块中导入时将会是更健壮的方法,并且独立于joblib backend(loky)。
例如,下例中将n_jobs设置为大于1,custom_scoring_function保存在user_created模块(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']
以字典形式将评分器名称映射给评分函数::
>>> 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
>>> # A sample toy binary classification dataset
>>> X, y = datasets.make_classification(n_classes=2, random_state=0)
>>> svm = LinearSVC(random_state=0)
>>> def tn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 0]
>>> def fp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 1]
>>> def fn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 0]
>>> def tp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 1]
>>> scoring = {'tp': make_scorer(tp), 'tn': make_scorer(tn),
... 'fp': make_scorer(fp), 'fn': make_scorer(fn)}
>>> cv_results = cross_validate(svm.fit(X, y), X, y, cv=5, scoring=scoring)
>>> # 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模块执行各种损失函数,评分,及调用函数测量分类模型的表现。一些指标可能要求正类别的可能性(probability)估计,置信度值,或者二分类决策值。大多数执行允许计算每一个样本对评分的权重贡献,通过sample_weight参数实现。
其中一些只适用于二分类的案例中:
参数 | 说明 |
---|---|
precision_recall_curve(y_true, probs_pred, *) | 根据不同的可能性阈值计算精确率-召回率 |
roc_curv(y_true, y_score, *[, pos_label, ...]) | 计算Receiver operating characteristic(ROC) |
其它也可用于多分类的参数例子:
参数 | 说明 |
---|---|
balanced_accuracy_score(y_true, y_pred, *) | 计算balanced准确率 |
cohen_kappa_score(y1, y2, *[, labels, ...]) | Cohen's kappa:衡量注一致程度的统计 |
confusion_matrix(y_true, y_pred, *[, ...]) | 计算混淆矩阵来评估分类模型的准确率 |
hinge_loss(y_true, pred_decision, *[, ...]) | 平均hinge损失(非正规 non-regularized) |
matthews_corrcoef(y_true, y_pred, *[, ...]) | 计算曼哈顿相关系数(MCC) |
roc_auc_score(y_true, y_score, *[, ...] | 从预测分数中,计算ROC曲线的面积(ROC AUC) |
一些也可以用于多分类例子中的参数:
参数 | 说明 |
---|---|
accuracy_score(y_true, y_pred, *[, ...]) | 分类模型的准确率得分 |
classification_report(y_true, y_pred, *[, ...]) | 主要分类模型指标的文本报告 |
f1_score(y_true, y_pred, *[, labels, ...]) | 计算F1评分,也被称为balanced F-score或者F-measure |
fbeta_score(y_true, y_pred, *, beta[, ...]) | 计算F-beta评分 |
hamming_loss(y_true, y_pred, *[, sample_weight]) | 计算平均Hamming损失 |
jaccard_score(y_true, y_pred, *[, labels, ...]) | Jaccard相似性系数得分 |
log_loss(y_true, y_pred, *[, eps, ...]) | 对数损失,aka logistic损失或者交叉熵损失 |
multilabel_confusion_matrix(y_true, y_pred, *) | 为每一个类或样本计算混淆矩阵 |
precision_recall_fscore_support(y_true, ...) | 计算精确率,召回率,F-measure并且支持每一个类 |
precision_score(y_true, y_pred, *[, ...]) | 计算精确率 |
recall_score(y_true, y_pred, *[, labels, ...]) | 计算召回率 |
roc_auc_score(y_true, y_score, *[, ...]) | 从预测分数中计算ROC曲线的面积 |
zero_one_loss(y_true, y_pred, *[, ...]) | 0-1分类损失 |
可以处理二分类和多标签(不是多分类)的问题:
参数 | 说明 |
---|---|
average_precision_score(y_true, y_score, *) | 从预测评分中计算平均精确率(AP) |
在随后的各子部分中,将会描述每一个上述函数,使用常用的API和指数定义。
3.3.2.1 从二分类到多分类和多标签
一些指标本质上是定义给二分类模型的(例如:f1_score)。在这些例子中,模型的默认值是只有正标签会被评估,假设正样本类的标签为1是初始值(尽管标签可以通过pos_label参数进行修改)。
由二分类指标延伸到多类或者多标签问题,数据被当作是二分类问题的集合,每个类都有一个。有一系列的方法可用于计算类集合的平均二分类指标,每个二分类指标可以应用于某些领域中。如果需要,可以使用average参数进行定义。
"weighted" (权重)处理类的不均衡问题。按其在真实数据中的加权计算每个类的分数,并计算各二分类指标的平均值。 "micro" (微)对于所有二分类指标(除非已分配样本权重)指定给每个样本类匹配相等的贡献。除了汇总每个类的指标,还要汇总除数和被除数,将每个类的各指标汇总成一个整体商(总被除数/总除数得出评估模型整体水平的商)。 微-平均方法更适合多标签分类中,包括多类别分类问题,但多数类会被忽略。 "samples" (样本)仅应用于多标签问题。它不对子类进行计算,而是计算评估数据中每个样本真实类别和预测类别的指标。 最后返回它们的(sample_weight - weighted)均值。 设置参数 average = None 会返回每个类得分的数组。
当多分类数据作为类标签数组提供给指标时,如二分类标签,多标签数据就会被指定为一个指标矩阵。 如元素(一个列表形式)[i, j],如果样本i被标记为j,则其值为1,否则为0。
3.3.2.2 准确率评分
accuracy_score函数计算accuracy(准确率),或者是个分数(初始值)或者是正确预测个数的计数(normalize=False)。
在多标签分类中,函数返回各子集的准确率。如果整个集合中每一个样本的预测标签严格匹配集合中的标签真实值,子集的准确率是1.0;否则是0.0。
如果是第i个样本的预测值与真实值相一致,对个样本正确预测的分数值是:
其中*l(x)*是指标函数(indicator function)。
>>> 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
在带有二分类标签指标的多标签例子中:
>>> accuracy_score(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
0.5
例如:
详见 用排列检验分类分数的显著性 是一个排序数据集的准确率评分。
3.3.2.3 平衡的准确率评分(Balanced accuracy score)
balanced_accuracy_score函数计算balanced accuracy,避免了对不平衡数据集进行夸大的性能估计。每个类别召回率的宏平均,或者等同于每个样本根据真实类别的比率(inverse prevalence)的权重,而计算的原始准确率。因此,对于平衡样本,平衡的准确率评分(Balanced accuracy score)与准确率相同。
在二分类的例子中,平衡的准确率与灵敏度(sensitivity)相同(真正率)和特异性(specificity)(真负率),或者ROC曲线的面积(二分类预测值而不是分数):
如果分类器在每个类的表现都很好,则该函数会退化为传统的准确率(例如:正确预测的个数除以总预测样本数)。
与之相对比,如果传统的准确率高于样本比例,仅因为分类器利用的是不均衡测试集,而对于平衡的准确率,会下降为。
分数范围为0-1,或者当参数adjusted=True时,范围变为到1,包括边界的,随机得分表现为0。
如果是第i个样本的真实值,是对应的样本权重,从而调整的样本权重为:
其中,l(x)是指标函数。根据样本i的预测值,平衡的准确率被定义如下:
设置adjusted=True,平衡的准确率报告的是比相对高的值。在二分类的例子中,也被称为*Youden's J statistic*或者informedness。
**注意:**多分类的定义看起来是用于二分类指标的合理延伸,尽管在文献中未达成共识。
我们的定义:[Mosley2013], [Kelleher2015]和[Guyon2015], 其中[Guyon2015]适合调整的版本,以确保随机预测值为0,好的预测值为1.. 类的均衡准确率在[Mosley2013]中描述:每个类别中精确率和召回率的最小值会被计算。将计算出的这些值进行平均,从而得到均衡的准确率。 均衡的准确率在[Urbanowicz2015]中被描述:每一个类别的灵敏度和特异性的均值会被计算,随后计算总的均值。
参考:
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.
Urbanowicz2015Urbanowicz R.J., Moore, J.H. ExSTraCS 2.0: description and evaluation of a scalable learning classifier system, Evol. Intel. (2015) 8: 89.
3.3.2.4 Cohen's kappa
cohen_kappa_score函数计算Cohen's kappa统计值。此度量旨在比较不同标注的标签,而分类器和真实数据的比较。
Kappa score(参见文档字符串)是一个数值,介于-1和1之间。分数大于0.8会被认为是好的协议;小于0说明没有协议(等同于随机标签)。
Kappa score可被用于计算二分类或者多分类的问题,但不适用于多标签的问题(除手动计算每一个标签分数)和多于两个以上注释器的问题。
>>> 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.5 混淆矩阵
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]])
plot_confusion_matrix可被用于展示混淆矩阵的可视化,在混淆矩阵的例子中,如下图所示:
参数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)
例如:
详见混淆矩阵,是一个用混淆矩阵评估分类器产出质量的例子。 详见识别手写数字,是一个使用混淆矩阵区分手写数字的例子。 详见基于稀疏特征的文本文档分类, 是一个使用混淆矩阵区分文本文档的例子。
3.3.2.6 分类模型报告
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.7 Hamming损失函数
Hamming_loss 计算平均的Hamming loss或者Hamming distance在两个样本的集合中。
如果是某个样本第j个标签的预测值,是其对应的真实值,是类别或者标签个是,Hamming损失函数介于两个样本之间:
其中,*l(x)*是指标函数(indicator function)。
>>> 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的Hamming损失函数与Hamming距离相一致,Hamming损失函数与零一损失函数(Zero one loss)相类似。但是零-一损失函数惩罚预测集合,预测集不与真实值集直接匹配,Hamming损失函数惩罚单个标签。因次,Hamming损失函数的上限是零一损失函数,它介于零和一之间,包括边界;预测真实标签合适的子集或者超子集会使Hamming损失函数界于零和一之间,不包括边界。
3.3.2.8 精确率,召回率和F-measures
直观地说,精确率(precision)是模型区分的能力,而不是将样本为负的标签标记为正,而召回率(recall)是找到正样本的能力。
F-measure(和测量)可被解释为精确率和召回率的权重调和平均数。测量值最高为1,最差为0。当时,和是相等的,并且召回率和精确率是同等重要的。
precision_recall_curve从真实标签和评分(不同阈值设定下,分类器的评分)计算一个精确率-召回率曲线.
average_precision_score函数从预测分数中计算平均精确率(average precision(AP))。该值介于0和1之间,且越高越好。AP的定义如下:
其中,和是在第n个阈值下的精确率和召回率,AP是正样本的分数。
参考[Manning2008]和[Everingham2010]展现AP的替代变体,它差值计算精确率-召回率曲线。 目前,average_precision_score并不能执行各种差值的变体。参考[Davis2006]和[Flach2015]描述了为何精确率-召回率曲线上点的线性插值产生的结果是过于乐观的分类器表现测量。线性插值被用于计算带有梯形法则的ROC曲线面积,即auc。
以下函数提供对精确率,召回率和F-measure评分的解释:
参数 | 解释 |
---|---|
average_precision_score(y_true, y_score,*) | 从预测评分中计算平均精确率 |
f1_score(y_true, y_pred, *[labels, ...]) | 计算F1评分,也被称为均衡的F-score或F-measure |
fbeta_score(y_true, y_pred, *, beta[, ...]) | 计算F-beta评分 |
precision_recall_curve(y_true, probas_pred, *) | 计算在不同的阈值下精确率-召回率组合 |
precision_recall_fscore_support(y_true, ...) | 计算精确率,召回率,F-measure,且支持对每一类的计算 |
precision_score(y_true, y_pred, *[, ...]) | 计算精确率 |
recall_score(y_true, y_pred, *[, labels, ...]) | 计算召回率 |
需要注意的是:precision_recall_curve函数只能用于二分类的例子中。average_precision_score函数可以用于二分类的分类模型和多标签形式。plot_precision_recall_curve函数画出精确率召回率关系图,如下所示。
例如:
参见 基于稀疏特征的文本文档分类,使用f1_score对文本文档的分类进行评估。 参见 使用带有交叉验证的网格搜索进行参数估计,使用内置交叉验证的网格搜索估计参数,用precision_score和recall_score评估。 参见 精确度-召回曲线用来评估分类质量。
参考:
[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.
3.3.2.8.1 二分类分类模型
在二分类分类模型中,分类预测中的“正”和“负”,“真”和“假”指的是预测值是否与外部评判(也作“观测值”)相一致。基于这些定义,可以总结一下表格:
实际类别(观测值) | 实际类别(观测值) | |
---|---|---|
预测类别(期望) | tp(真正)正确的结果 | fp(假正)意料外的结果 |
预测类别(期望) | fn(假负)错误的结果 | tn(真负)正确未出现的结果 |
基于上文,可以定义精确率,召回率和F-measure的概念:
如下是二分类分类模型代码示例:
>>> 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.66..., 0.5 , 1. , 1. ])
>>> recall
array([1. , 0.5, 0.5, 0. ])
>>> threshold
array([0.35, 0.4 , 0.8 ])
>>> average_precision_score(y_true, y_scores)
0.83...
3.3.2.8.2 多分类和多标签分类模型
在多分类和多标签分类任务中,精确率,召回率,和F-measures的定义可以应用于每一个独立的标签。有很多方法可以将各标签的结果进行组合,可用average参数分别在average_precision_score(仅用于多标签),f1_score,fbeta_score,precision_recall_support,precision_score和recall_score函数中传递,已在以上描述(above)。需要注意的是:如果所有的标签啊都包括在内,那么“micro”-averaging(“微”-平均)在多分类中的设置将产生精确率,召回率和F与准确率的结果相等。也要注意"权重"平均可能产生不介于精确率和召回率之间的F-score。
为了更清晰的了解,请考虑如下概念:
y是预测值(样本,标签)组合的集合 是真实值(样本,标签)组合的集合 L是标签的集合 S是样本的集合 是y的样本s 的子集,例如: 是y的标签l的子集 同样地,和均是的子集 (在处理B=\emptyset时,公约有所不同;这个执行使用R(A, B): = 0,并且与P类似 )
各指标定义如下:
average | Precision | Recall | F_beta |
---|---|---|---|
"micro" | |||
"samples" | |||
"macro" | |||
"weighted" | |||
None |
>>> 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
同样地,一些未在样本中出现的标签,可以考虑使用宏-平均(macro-averaging)。
>>> metrics.precision_score(y_true, y_pred, labels=[0, 1, 2, 3], average='macro')
0.166...
3.3.2.9 Jaccard相似性系数评分
jacquard_score函数计算Jaccard similarity coefficients(Jaccard相似性系数)的均值,也被称为Jaccard指数,在标签对的集合中。
第i个样本的Jaccard相似性系数,与真实标签和预测标签的定义如下:
jaccard_score与precision_recall_fscore_support的作用类似,应用于二分类标签,并且通过使用参数average可以扩展到多标签和多分类(详见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...
用二分类标签指标的多标签例子:
>>> 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_phred, 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.10 Hinge loss
hinge_loss函数指通过使用hinge loss方法计算模型和数据之间的平均距离,它是一个单边指数,即仅考虑预测误差。(Hinge loss被用于最大化边际分类器,如支持向量机。)
如果标签被编码为+1和-1,y:是真实值,w是预测决策,是decision_function的产出值,hinge loss被定义如下:
如果多于两个标签,根据Crammer & Singer,hinge_loss使用多分类变体。详见论文链接。
如果是真实样本的预测决策,是所有样本预测决策的最大值,预测决策是预测函数的返回值,多分类hinge loss的定义如下:
如下是用带有hinge_loss函数的支持向量机分类器解决的二分类问题的小例子:
>>> from sklearn import svm
>>> from sklearn.metrics import hinge_loss
>>> X = [[0], [1]]
>>> y = [-1, 1]
>>> est = svm.LinearSVC(random_state=0)
>>> est.fit(X, y)
LinearSVC(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函数的支持向量机分类器解决多分类问题的小例子:
>>> X = np.array([[0], [1], [2], [3]])
>>> Y = np.array([0, 1, 2, 3])
>>> labels = np.array([0, 1, 2, 3])
>>> est = svm.LinearSVC()
>>> est.fit(X, Y)
LinearSVC()
>>> pred_decision = est.decision_function([[-1], [2], [3]])
>>> y_true = [0, 2, 3]
>>> hinge_loss(y_true, pred_decision, labels)
0.56...
3.3.2.11 对数损失函数(Log loss)
对数损失函数,也被称作逻辑回归损失函数或者交叉熵损失函数,是基于可能性的估计值。它被广泛应用于(多项式)逻辑回归和神经网络模型中,以及一些计算期望最大化的变种模型,并且被用于评估一个分类器而不是离散预测值的可能性产出(predict_proba)。
对于带有真实标签二分类分类模型和一个可能性估计,每个样本的对数损失函数是给定真实标签分类器的负对数似然值:
它延伸到多分类的例子如下所示。样本中的真实标签可以被编码为1-of-K 二分类指标矩阵 Y,例如:如果样本i的标签k是从标签集合K中提取的。通过,让P成为可能性估计矩阵。对数损失函数的集合就是:
如想详细了解上述二分类对数损失函数是如何生成的,需要注意在二分类的例子中,和,所以给出二分类对数损失函数,需要扩展的内部和。
提供真实标签值的列表和可能性矩阵,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...
y_pred参数列表[.9, .1]中的第一个值表示第一个样本被标记为0的可能性为90%。对数损失函数是非负的。
3.3.2.12 马修斯相关系数
对于二分类,matters_corrcoef函数计算的是Matthew's correlation coefficient (MCC)。 下面引用自维基百科:
“马修斯相关系数被用于机器学习是作为测量二分类(两类)分类模型质量的评估。它考虑真正,假正,真负和假负,并且被认为是一个平衡值,可被用于类大小不均衡的数据。马修斯相关系数(MCC)本质上是一个介于-1和+1之间的相关系数值。如果系数值为+1,则表示预测非常好,0表示一个平均随机的预测,-1表示预测相反。在统计学中也被称作phi系数。”
在二分类(两类)的例子中,tp,tn,fp和fn分别是真正,真负,假正和假负的数量,MCC被定义如下:
在多分类的例子中,马修斯相关系数被定义为可以根据K个分类计算混淆矩阵C。为了简化定义,考虑如下的中间变量:
是类别k真实发生的次数, 是类别k预测的次数, 是正确预测的总样本个数, 是总样本的个数。
多分类MCC被定义为:
当多于两个标签时,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.13 多标签混合矩阵
multilabel_confusion_matrix函数计算class-wise(初始值)或者sample-wise(sample wise = True)多标签混淆矩阵来评估分类模型的准确率。如果是多标签,多标签混淆矩阵(multilabel_confusion_matrix)也被认为是多分类数据。这种转变被普遍用于使用二分类分类模型指标(例如精确率,召回率等。)评估多分类问题。
当计算class-wise多标签混淆矩阵C,类别i的真负个数是,假负是,真正是,和假正是。
如下示例解释带有多标签指标矩阵(多标签指标矩阵)投入的multilabel_confusion_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]],
<BLANKLINE>
[[1, 1],
[0, 1]]])
如下例子解释了带有multiclass(多分类)投入的multilabel_confusion_matrix的使用:
>>> 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函数计算多标签指标矩阵投入的,每一个类别的召回率(或者灵敏度),特异度,fall out(假正率)和 miss rate(假负率)。
计算每一个类的recall(召回率)(也被称作真正率和灵敏度):
>>> 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(特异度)(也被称作真负率)
>>> tn / (tn + fp)
array([1. , 0. , 0.5])
计算每个类的fall out(也被称作假正率):
>>> fp / (fp + tn)
array([0. , 1. , 0.5])
计算每一个类的miss rate(也被称作假负率):
>>> fn / (fn + tp)
array([0. , 0.5, 1. ])
3.3.2.14 Receiver operating characteristic (ROC)
roc_curve函数计算receiver operating characteristic curve, or ROC curve。引用维基百科:
“receiver operating characteristic (ROC),或简称ROC 曲线, 是一个图,它解释二分类分类器系统随着不同阈值变化的表现。用来绘制在各种阈值的设置中,真正数占总正样本的比率(TPR = 真正率(true positive rate))与假正数占总负样本的比率(FPR = 假正率(false positive rate))之间的关系。TPR也被认为是敏感度,和FPR(1-敏感度或者真负率)。”
这个函数要求真二分类值和目标分数,它或者是正类别的可能性估计,置信度值,或者是二分类决策值。如下是使用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([1.8 , 0.8 , 0.4 , 0.35, 0.1 ])
下图是上例ROC曲线:
roc_auc_score函数计算ROC曲线的面积,被称为AUC或者AUROC。通过计算ROC曲线的面积,整个曲线的信息被总结为一个数字。详见Wikipedia article on AUC。
>>> import numpy as np
>>> from sklearn.metrics import roc_auc_score
>>> y_true = np.array([0, 0, 1, 1])
>>> y_scores = np.array([0.1, 0.4, 0.35, 0.8])
>>> roc_auc_score(y_true, y_scores)
0.75
在多标签分类模型中,roc_auc_curve函数可以通过在标签上进行平均来扩展,如上例子。
诸如子集准确率,Hamming损失函数,或者F1分数相比,ROC不能给每一个标签提供最佳的阈值。 roc_auc_score函数可以用于多类别分类模型。当前有两个平均策略可以使用:one-vs-one算法计算ROC AUC评分的均值;one-vs-rest算法计算每一个类ROC AUC评分的均值,而不是总均值。在上面两个例子中,预测标签以数组形式提供,值的范围是0到n_classes,评分与属于某类样本的可能性估计值相一致。OvO和OvR算法支持均匀加权(average = "macro")和prevalence(average = "weighted")。
One-vs-one Algorithm: 计算所有可能类组合的AUC的均值。[HT2001]定义一个多类别AUC指标均匀权重:
其中c是类的个数,AUC(j|k)是类别j作为正类和类别k作为负类的AUC值。总而言之,在多分类的例子中。这个算法是用"ovo"给参数multiclass赋值和"macro"给"average"赋值。
[HT2001]多分类AUC指标可以延伸到用prevalence进行加权:
其中c是类别数。该算法是用“ovo”给参数multiclass赋值,和用“weighted”给参数average赋值。“weighted”选项返回一个prevalence-weighted均值,详见如下描述[FC2009]。
**One-vs-rest Algorithm: **计算每个类别的AUC而不是剩余的[PD2000]。该算法在功能上与多标签的例子相同。通过设置"ovr"给参数multiclass来使用该算法。正如OvO, OvR支持两种均值策略:“macro”[F2006]和"weighted"[F2001]。
在那些高(false positive rate)不被容忍的情况下,roc_auc_score函数的参数max_fpr可被用来把ROC曲线累加到一个给定的限制。

例子:
参见 ROC曲线 使用ROC去评估一个分类器产出的质量。 参见 带交叉验证的ROC曲线 使用ROC评估模型分类质量,使用交叉验证。 参见 物种分布模型 使用ROC建模分类分布。
参考:
HT2001(1,2) Hand, D.J. and Till, R.J., (2001). A simple generalisation of the area under the ROC curve for multiple class classification problems. Machine learning, 45(2), pp.171-186.
[FC2009]Ferri, Cèsar & Hernandez-Orallo, Jose & Modroiu, R. (2009). An Experimental Comparison of Performance Measures for Classification. Pattern Recognition Letters. 30. 27-38.
[PD2000]Provost, F., Domingos, P. (2000). Well-trained PETs: Improving probability estimation trees (Section 6.2), CeDER Working Paper #IS-00-04, Stern School of Business, New York University.
[F2006]Fawcett, T., 2006. An introduction to ROC analysis. Pattern Recognition Letters, 27(8), pp. 861-874.
[F2001]Fawcett, T., 2001. Using rule sets to maximize ROC performance In Data Mining, 2001. Proceedings IEEE International Conference, pp. 131-138.
3.3.2.15 Zeor one loss
zero_one_loss函数是通过来计算0-1分类模型的损失函数()的求和或者均值。初始情况下,函数会将整个数据标准化。为了得到的求和,设置normalize=False。
在多标签分类模型中,zero_one_loss给子集打分,严格按照标签和预测值的对应关系,如果有任何错误,都评为0分。初始情况下,函数返回未能较好预测的子集比例。如果想得到这样的子集计数,设置normalize = False。
如果是第i个样本的预测值, 是与值对应的真实值,那么0-1损失函数就被如下定义:
其中*l(x)*是指标函数(indicator function)。
>>> 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, 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
例如:
参见 brier_score_loss 函数计算二分类的Brier score。引用自维基百科:
“Brier score是一个合适的评分函数,它测量概率预测的准确率。它适用于预测必须将该率分配给一组相互排斥的离散结果的任务。”
该函数返回一个实际结果与预测的可能结果的可能性之间的均方差的评分。实际结果应是1或者0(真或假),尽管实际结果的预测可能性是一个介于0和1之间的数。
brier分数损失也是一个介于0和1之间的数,评分越低(均方差很小),预测越准确。它被看作是测量一个可能性预测集合的“标尺”。
其中:N是总预测值,是实际结果的预测可能性。
以下是使用该函数的小例子:
>>> 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
例子:
参见 Probability calibration of classifiers 是一个使用Brier score损失来校准分类器的可能性。
参考:
G. Brier, Verification of forecasts expressed in terms of probability, Monthly weather review 78.1 (1950)
3.3.3 多标签排序指标
在多标签的机器学习中,每个样本可以有很多与之相关联的真实标签。目标是提供高的评分和较好的真实值排名。
3.3.3.1 覆盖误差
coverage_error函数计算必须包含在最中预测的标签的平均数量,以预测所有真实的标签。如果想知道高分数标签的个数,需要可以预测不缺少任何真实标签的平均值。因此,该指标的最佳值是真实标签的平均值。
**注意:**这里实现的得分比在Tsoumakas et al., 2010文献中提供的计算方式大1.这个延伸是为了解决一些例子中不包含真实标签的退化现象。
在形式上,提供真实标签的二分类指标矩阵,以及与每一个标签相联合的得分