【Python机器学习】模型评估与改进——二分类指标

news2025/2/28 17:30:48

目录

1、错误类型

2、不平衡数据集

3、混淆矩阵

与精度的关系。

准确率、召回率与f-分数

分类报告

4、考虑不确定性

5、准确率-召回率曲线

6、受试者工作特征(ROC)与AUC


二分类可能是实践中最常见的机器学习应用,也是概念最简单的应用。但是即使是评估这个简单的任务也仍有一些注意事项。对于二分类问题,我们通常会说正类反类,而正类使我们要寻找的类。

1、错误类型

通常来说,精度并不能很好的度量预测性能,因为我们所犯错误的数量并不包含我们感兴趣的所有信息。想象一个应用,利用自动化测试来筛查癌症的早期发现。如果测试结果为阴性,那么认为患者是健康的,如果测试结果为阳性,那么患者则需要接收额外的筛查。这里我们将阳性结果称为正类,阴性测试称为反类。我们不能假设模型永远是完美的,它也会犯错。对于任何应用而言,我们都需要问问自己,这些错误在现实世界中可能有什么后果。

一种可能的错误是健康的患者被诊断为阳性,导致需要进行额外的测试。这会给患者带来一些额外的支出和不便。错误的阳性预测被称为假正例。另一种可能的错误是患病的人被诊断为阴性,因而不会接受进一步的检查,可能导致严重的健康问题,这种错误的类型被叫做假反例,也叫做第二类错误

2、不平衡数据集

如果在两个类别中,一个类别的出现次数比另一个多得多,那么错误类型将发挥重要作用,这在实践中非常常见。一个很好的例子是点击预测,其中每个数据点表示一个印象,即向用户展示的一个物项。这个物项可能是广告、故事,或者在社媒上关注的用户。目标是预测用户是否会点击看到的某个特定物项。用户对互联网上显示的大多数内容都不会点击。你可能向用户展示100个广告,用户才点击一次,这样就会得到一个数据集,其中每99个“未点击”的数据点才有一个“已点击”的数据点。换句话说,00%的样本属于“未点击”类别,这种一个类别比另一个类别出现的次数多很多的数据集,通常叫做不平衡数据集或者具有不平衡类别的数据集。在实际中,不平衡数据才是常态。

如果在上述的数据集上构造一个点击预测任务重精度达到99%的分类器,只要预测“未点击”,就可以达到99%的精度,但这样的精度无法帮助我们区分不变的“未点击”模型与潜在的优秀模型。

为了便于说明,我们将digits数据集中的数字9与其他九个类别加以区分,从而创建一个9:1的不平衡数据集,并使用DummyClassifier来始终预测多数类,以查看精度提供的信息量有多么少:

from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.dummy import DummyClassifier
import numpy as np

disits=load_digits()
y=disits.target==9

X_train,X_test,y_train,y_test=train_test_split(disits.data,y,random_state=0)
dummy_majority=DummyClassifier(strategy='most_frequent').fit(X_train,y_train)
pred_most_frequent=dummy_majority.predict(X_test)
print('标签:{}'.format(np.unique(pred_most_frequent)))
print('测试集精度:{:.2f}'.format(dummy_majority.score(X_test,y_test)))

我们得到了接近90%的精度,却没有学到任何内容。这个结果可能看起来相当好,但根据具体问题,也可能是仅预测了一个类别,我们将这个结果与使用一个真实分类器的结果进行对比:

tree=DecisionTreeClassifier(max_depth=2).fit(X_train,y_train)
pred_tree=tree.predict(X_test)
print('测试集精度:{:.2f}'.format(tree.score(X_test,y_test)))

从精度上来看,DecisionTreeClassifier仅比常数预测稍微好一点,这可能表示我们使用DecisionTreeClassifier的方法有误,也可能是因为精度实际上在这里不是一个很好的变量。

为了便于对比,我们再评估两个分类器,LogisticRegression与默认的DummyClassifier,其中后者进行随机预测,但预测类别的臂力与训练集中的比例相同:

dummy=DummyClassifier().fit(X_train,y_train)
pred_dummy=dummy.predict(X_test)
print('DummyClassifier测试集精度:{:.2f}'.format(dummy.score(X_test,y_test)))

logreg=LogisticRegression().fit(X_train,y_train)
pred_logreg=logreg.predict(X_test)
print('LogisticRegression测试集精度:{:.2f}'.format(logreg.score(X_test,y_test)))

可以看到,产生随机输出的虚拟分类器是所有分类器中最差的,而LogisticRegression则给出了相当好的结果。但是,即使是随机分类器也得到了超过90%的精度。这样很难判断哪些结果是真正有帮助的。这里的问题在于,要想对这种不平衡数据的预测性能进行量化,精度并不是一种合适的度量。

我们希望有一个指标告诉我们,一个模型比最常见预测或随机预测要好多少。如果用一个指标来评估模型,那么这个指标应该能够淘汰这些无意义的预测。

3、混淆矩阵

对于二分类问题的评估结果,一种最全面的表示方法是使用混淆矩阵。我们利用confusion_matrix函数来检查上面的LogisticRegression的预测结果:

from sklearn.metrics import confusion_matrix
confusion=confusion_matrix(y_test,pred_logreg)
print('混淆矩阵:\n{}'.format(confusion))

confusion_matrix输出的是一个2*2数组,其中行对应真实的类别,列对应预测的类别。数组中每个元素给出属于该行对应类别(这里是“9”和“非9”)的样本被分类到该列对应类别中的数量。

如图说明:

mglearn.plots.plot_confusion_matrix_illustration()
plt.show()

如果我们将‘9’作为正类,那么就可以将混淆矩阵的元素与前面介绍过的假正例和假反例两个术语联系起来,为了使图像更完整,我们将正类中正确分类的样本称为真正例,将反类中正确分类的样本称为真反例。这些属于通常缩写为FP(假正例)、FN(假反例)、TP(真正例)、TN(真反例),这样就得到下图对混淆矩阵的解释:

下面用混淆矩阵来比较前面拟合过的模型(两个虚拟模型、决策树、Logistic回归)

print('始终预测多数类的混淆矩阵:\n{}\n'.format(confusion_matrix(y_test,pred_most_frequent)))
print('DummyClassifier混淆矩阵:\n{}\n'.format(confusion_matrix(y_test,pred_dummy)))
print('决策树的混淆矩阵:\n{}\n'.format(confusion_matrix(y_test,pred_tree)))
print('Logistic回归的混淆矩阵:\n{}\n'.format(confusion_matrix(y_test,pred_logreg)))

可以看到,很明显的多数类预测和pred_dummy很有问题,他们总是预测同一个类别。

Logistic回归在各方面都比较好:它的真正例和真反例的数量更多,而假正例和假反例的数量更少。从这个对比中明显看出,只有决策树和Logistic回归给出了合理的结果,并且Logistic回归的效果全面好于决策树。但是,检查整个混淆矩阵有点麻烦,虽然我们通过观察矩阵的各个方面得到了很多深入见解,但这个过程是人工完成的,也是非常定性的。

有几种方法可以总结混淆矩阵中包含的信息,之后展示。

与精度的关系。

这是一种总结混淆矩阵的方法——计算精度,其公式表达:Accuracy=(TP+TN)/(TP+TN+FP+FN),换句话说,精度是正确预测的数量(TP和TN)除以所有样本的数量(混淆矩阵中所有元素的和)

准确率、召回率与f-分数

总结混淆矩阵还有几种方法,其中最常见的就是准确率召回率

准确率度量的是被预测为正例的样本中有多少是真正的正例:Precision=TP/(TP+FP)

如果目标是限制假正例的数量,那么可以使用准确率作为性能指标。准确率也被称为阳性预测值。

另一方面,召回率度量的是正类样本中有多少样本中被预测为正例:Recall=TP/(TP+FN)

如果我们需要找出所有的正类样本,即避免假反例是很重要的情况下,那么可以使用召回率作为性能指标。召回率的其他名称有灵敏度命中率、和真正例率

在优化召回率与优化准确率之间需要折中。如果预测所有样本都属于正类,那么可以轻松得到完美的召回率(没有假反例),也没有真反例。但是,将所有样本都预测为正类,会得到许多假正例,因此准确率会很低。与之相反,如果你的模型只将一个最确定的数据点预测为正类,其他点都预测为反类,那么准确率会很完美,但是召回率会很差。

虽然准确率和召回率是非常重要的度量,但是仅查看二者之一无法提供完整的图景。将两种度量进行汇总的一种方法是f-分数,或f-度量,它是准确率与召回率的调和平均:F=2*(Precision*Recall)/(Precision+Recall)。这一特定变体也被称为f_{1}分数。由于同时考虑了准确率和召回率,所以它对于不平衡的二分类数据集来说是一种比精度更好的度量。

print('f1 score most frequent:{:.2f}'.format(f1_score(y_test,pred_most_frequent)))
print('f1 score dummy:{:.2f}'.format(f1_score(y_test,pred_dummy)))
print('f1 score 决策树:{:.2f}'.format(f1_score(y_test,pred_tree)))
print('f1 score Logistic回归:{:.2f}'.format(f1_score(y_test,pred_logreg)))

这里可以注意到两件事:

1、我们从most_frequent的预测中得到一条错误信息,因为预测的正类数量为0(使得f-分数的分母为0);

2、我们可以看到虚拟预测与决策树预测之间有很大的区别,而仅观察精度时二者区别并不明显。

利用f-分数进行评估,我们再次用一个数字总结了预测性能。打码机f-分数似乎比精度更加符合我们对好模型的直觉,但是f-分数的一个缺点是比精度更难理解。

分类报告

如果我们想要对准确率、召回率和f_{1}分数做一个更全面的总结,可以使用classification_report这个很方便的函数,它可以同时计算这三个值,并以美观的格式打印出来:

print(classification_report(y_test,pred_most_frequent,target_names=['非9','9']))

classification_report函数为每个类(这里是True和False)生成一行,并给出以该类别作为正类的准确率、召回率、f-分数。前面我们假设较少的“9”类为正类。如果将正类改为“非9”,我们可以从classification_report的输出结果中看出,利用most_frequent模型得到的f-分数为0.94。此外,对于“非9”类别,召回率是1,因为我们将所有样本都分类为“非9”。f-分数旁边的最后一列给出了每个类别的支持率(support),它表示的是这个类别中真实样本的数量。

分类报告的最后一行显示的是对应指标的加权平均。下面的两个报告,分别是虚拟分类器和Logistic回归的:

print('虚拟分类器',classification_report(y_test,pred_dummy,target_names=['非9','9']))
print('Logistic回归',classification_report(y_test,pred_logreg,target_names=['非9','9']))

在查看报告时可以看到,虚拟模型与好模型之间的区别不再那么明显。选择哪个类作为正类对指标有很大影响。虽然以“9”类作为正类时虚拟分类的f-分数是0.1(对比Logistic回归的0.89),而以“非9”类作为正类的f-分数分别是0.91和0.99,两个结果看起来都很合理。不过同时查看所有数字可以给出非常准确的图像,我们可以清楚的看到Logistic回归模型的优势。

4、考虑不确定性

混淆矩阵和分类报告为一组特定的预测提供了非常详细的分析。但是,预测本身已经丢弃了模型汇总包含的大量信息。大多数分类器都提供了一个decision_function或predict_proba方法来评估预测的不确定度。预测可以被看做是以某个固定点作为decision_function或predict_proba输出的阈值——在二分类问题中,我们使用0作为决策函数的阈值,0.5作为predict_proba的阈值。

下面是一个不平衡二分类任务的示例,反类有400个点,而正类只有50个点。训练数据如下图左侧。我们在这个数据上训练一个核SVM模型,训练数据右侧的图像将决策函数值绘制为热图。我们可以子啊图像偏上的位置看到一个黑色圆圈,表示decision_function的阈值刚好问为0.在这个圆圈内的点将被划为正类,圆圈外的点将被划为反类:

import mglearn.plots
from sklearn.datasets import load_digits,make_blobs
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.svm import SVC


plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

X,y=make_blobs(n_samples=(400,50),cluster_std=[7.0,2],random_state=22)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
svc=SVC(gamma=0.05).fit(X_train,y_train)

mglearn.plots.plot_decision_threshold()
plt.show()

我们可以使用classification_report函数来评估两个类别的准确率与召回率:

print(classification_report(y_test,svc.predict(X_test)))

对于类别1,我们得到了一个相当低的准确率,而召回率则令人糊涂。由于类别0要大得多,所以分类器将重点放在类别0分类正确,而不是较小的类别1。

假设在我们的应用中,类别1具有高召回率更加重要,这意味着我们愿意冒险有更多的假正例,以换取更多的真正例。svc.predict生成的预测无法满足这个要求,但我们可以通过改变决策阈值不等于0来将预测重点放在使类别1的召回率更高。默认情况下,decision_function值大于0的点将被划分为1。我们希望将更多的点划分为1,所以需要减小阈值。

y_pred_lower_threshold=svc.decision_function(X_test)>-.8
print(classification_report(y_test,y_pred_lower_threshold))

正如所料,类别1 的召回率增大,准确率减小。现在我们将更大的空间区域划分为类别1,正如上图右上图所示,如果认为准确率比召回率更重要,或者反过来,或者数据严重不平衡,那么改变决策阈值是得到更好结果的最简单方法。由于decision_function的取值可能在任意范围,所以很难提供关于如何选取阈值的经验法则。

对于实现了predict_proba方法的模型来说,选择阈值可能更简单,因为predict_proba的输出固定在0到1的范围内,表示的是概率。默认情况下,0.5的阈值表示,如果模型以超过50%的概率“确信”一个点属于正类,那么就将其划为正类。增大这个阈值意味着模型需要更加确信才能做出正类的判断。虽然使用概率可能比使用任意阈值更加直观,但并非所有模型都提供了不确定性的实际模型。这与校准的概念相关:校准模型是指能够为其不确定性提供准确度量的模型。

5、准确率-召回率曲线

之前说过,改变模型汇总用于分类决策的阈值,是一种调节给定分类器的准确率和召回率之间折中的方法。你可能希望仅遗漏不到10%的正类样本,即希望召回率能够达到90%。这一决策取决于应用,应该是由商业目标驱动的。一旦设定了一个具体目标,就可以适当地设定一个阈值,总是可以设置一个阈值来满足特定的目标,比如90%的召回率。难点在于开发一个模型,在满足这个阈值的同时仍具有合理的准确率——如果你将所有样本都划为正类,那么将会得到100%的召回率,但这个模型毫无用处。

对分类器设置要求(比如90%的召回率)通常被称为设置工作点。在业务中固定工作点通常有助于为客户或组织内的其他小组提供性能保证。

在开发新模型时,通常并不完全清楚工作点在哪里。因此,为了更好地理解模型问题,很有启发性的做法是,同时查看所有可能的阈值或准确率和召回率的所有可能折中。利用一种叫做准确率—召回率曲线的工具可以做到这一点。我们可以在scikit-learn模块中找到计算准确率—召回率曲线的函数。这个函数需要真实标签与预测的不确定度,后者由decision_function或predict_proba给出:

from sklearn.metrics import precision_recall_curve
precision,recall,thresholds=precision_recall_curve(y_test,svc.decision_function(X_test))

precision_recall_curve函数返回一个列表,包含按顺序排序的所有可能阈值(在决策函数中出现的所有值)对应的准确率和召回率,这样我们就可以绘制一条曲线:

from sklearn.datasets import load_digits,make_blobs
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.metrics import precision_recall_curve
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

X,y=make_blobs(n_samples=(4000,500),cluster_std=[7.0,2],random_state=22)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
svc=SVC(gamma=0.05).fit(X_train,y_train)

precision,recall,thresholds=precision_recall_curve(y_test,svc.decision_function(X_test))
close_zero=np.argmin(np.abs(thresholds))
plt.plot(precision[close_zero],recall[close_zero],'o',markersize=10,label='阈值 0',fillstyle='none',mew=2)
plt.plot(precision,recall,label='精确率-召回率曲线')
plt.xlabel('准确率')
plt.ylabel('召回率')
plt.show()

上图中曲线上的每一个点都对应decision_function的一个可能阈值。例如,我们可以看到,在准确率约为0.75的时候,召回率为0.4.黑色圆圈表示的是阈值为0的点,0是decision_function的默认阈值,这个点是在调用predict方法时所选择的折中点。

曲线越靠近右上角,则分类器越好。右上角的点表示对于同一个阈值,准确率和召回率都很高。曲线从左上角开始,这里对应于非常低的阈值,将所有样本都化为正类。提高阈值可以让曲线向准确率更高的方向移动,但同时召回率降低。继续增大阈值,大多数被划为正类的点都是真正例,此时准确率很高,但召回率更低,随着准确率的升高,模型越能够保持较好的召回率,则模型越好。

进一步观察曲线,可以发现,利用这个模型可以得到约0.5的准确率,同时保持很高的召回率。如果我们想要更高的准确率,那么就必须牺牲很多召回率。换句话说,曲线左侧相对平坦,说明在准确率提高的同时召回率没有下降很多。当准确率大于0.5之后准确率每增加一点就会导致召回率下降很多。

不同的分类器可能在曲线上不同的位置(即在不同的工作点)表现很好,我们来比较一下再同一数据集上训练的SVM与随机森林。RandomForestClassifier没有decision_function,只有predict_proba。precision_recall_curve函数的第二个参数应该是正类的确定性度量,所以我们传入样本属于类别1的概率。二分类问题的predict_proba的默认阈值为0.5,所以我们在曲线上标出这个点:

import mglearn.plots
from sklearn.datasets import load_digits,make_blobs
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.svm import SVC
from sklearn.metrics import precision_recall_curve
import numpy as np
from sklearn.ensemble import RandomForestClassifier
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

X,y=make_blobs(n_samples=(4000,500),cluster_std=[7.0,2],random_state=22)
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)
svc=SVC(gamma=0.05).fit(X_train,y_train)
rf=RandomForestClassifier(n_estimators=100,random_state=0,max_features=2)
rf.fit(X_train,y_train)

precision,recall,thresholds=precision_recall_curve(y_test,svc.decision_function(X_test))
close_zero=np.argmin(np.abs(thresholds))
precision_rf,recall_rf,thresholds_rf=precision_recall_curve(y_test,rf.predict_proba(X_test)[:,1])
plt.plot(precision,recall,label='svc')
plt.plot(precision[close_zero],recall[close_zero],'o',markersize=10,label='阈值 0(SVC)',fillstyle='none',mew=2)
plt.plot(precision_rf,recall_rf,label='rf')
close_default_rf=np.argmin(np.abs(thresholds_rf-0.5))
plt.plot(precision_rf[close_default_rf],recall_rf[close_default_rf],'^',c='k',markersize=10,label='阈值 0.5 rf',fillstyle='none',mew=2)
plt.xlabel('准确率')
plt.ylabel('召回率')
plt.legend(loc='best')
plt.show()

从这张对比图可以看出,随机森林在极值处(要求很高的召回率或很高的准确率)的表现更好。在中间位置(准确率约为0.7)SVM的表现更好。如果我们只查看f_{1}-分数来比较二者的总体性能,那么可能会遗漏这些细节。f_{1}-分数只反映了准确率-召回率曲线上的一个点,即默认阈值对应的那个点。

print('随机森林f1-分数:{:.3f}'.format(f1_score(y_test,rf.predict(X_test))))
print('SVC f1-分数:{:.3f}'.format(f1_score(y_test,svc.predict(X_test))))

对比这两条准确率-召回率曲线,可以为我们提供大量详细的洞见,但这是一个相当麻烦的过程。对于自动化模型对比,我们可能希望总结曲线中包含的信息,而不限于某个特定的阈值或工作点。总结准确率-召回率曲线的一种方法是计算该曲线下的积分或面积,也叫做平均准确率。你可以使用average_precision_score函数来计算平均准确率。因为我们要计算准确率-召回率曲线并考虑多个阈值,所以需要向average_precision_score传入decision_function或predict_proba的结果,而不是predict的结果:

ap_rf=average_precision_score(y_test,rf.predict_proba(X_test)[:,1])
ap_svc=average_precision_score(y_test,svc.decision_function(X_test))
print('平均准确率(随机森林):{:.3f}'.format(ap_rf))
print('平均准确率(svc):{:.3f}'.format(ap_svc))

在对所有可能的阈值进行平均时,我们看到随机森林和SVC的表现差不多好。随机森林稍微领先。这与前面从f1_score中得到的结果大卫不同。因为平均准确率是从0到1的曲线下的面积,所以平均准确率总是返回一个在0(最差)到1(最好)之间的值。随机分配decision_function的分类器的平均准确率是数据集中正例样本所占的比例。

6、受试者工作特征(ROC)与AUC

还有一种常用的工具可以分析不同阈值的分类器行为:受试者工作特征曲线,简称为ROC曲线。,与准确率-召回率曲线类似,ROC曲线考虑了给定分类器的所有可能的阈值,但它显示的是假正例率(FPR)真正例率(TPR),而不是报告准确率和召回率(真正例率只是召回率的另一个名称,而假正例率则是假正例占所有反类样本的比例)。

FPR=FP/(FP+TN)

可以用roc_curve函数来计算ROC曲线:

fpr,tpr,thresholds=roc_curve(y_test,svc.decision_function(X_test))

plt.plot(fpr,tpr,label='ROC曲线')
plt.xlabel('FPR')
plt.ylabel('TPR(recall)')
close_zero=np.argmin(np.abs(thresholds))
plt.plot(fpr[close_zero],tpr[close_zero],'o',markersize=10,label='阈值0',fillstyle='none',c='k',mew=2)
plt.legend(loc=4)
plt.show()

对于ROC曲线,理想的曲线要靠近左上角:我们希望分类器的召回率很高,同时保证假正例率很低。从曲线中可以看出,与默认阈值0相比,我们可以得到明显更高的召回率(约为0.9),而FPR仅稍有增加。最接近左上角的点可能是比默认选择更好的工作点。同样要注意,不应该在测试集上选择阈值,而是应该在单独的验证集上选择。

下图给出了随机森林和SVM的ROC曲线对比:

fpr,tpr,thresholds=roc_curve(y_test,svc.decision_function(X_test))
close_zero=np.argmin(np.abs(thresholds))
fpr_rf,tpr_rf,thresholds_rf=roc_curve(y_test,rf.predict_proba(X_test)[:,1])

plt.plot(fpr,tpr,label='ROC曲线(SVC)')
plt.plot(fpr_rf,tpr_rf,label='ROC曲线(随机森林)')
plt.xlabel('FPR')
plt.ylabel('TPR(recall)')
plt.plot(fpr[close_zero],tpr[close_zero],'o',markersize=10,label='SVC 阈值0',fillstyle='none',c='k',mew=2)
close_default_rf=np.argmin(np.abs(thresholds_rf-0.5))
plt.plot(fpr_rf[close_default_rf],tpr_rf[close_default_rf],'^',markersize=10,label='随机森林 阈值0.5',fillstyle='none',c='k',mew=2)
plt.legend(loc=4)
plt.show()

与准确率-召回率曲线一样,我们通常希望使用一个数字来总结ROC曲线,即曲线下的面积(通常被称为AUC,这里的曲线指的就是ROC曲线)。我们可以利用roc_auc_score函数来计算ROC曲线下的面积:

rf_auc=roc_auc_score(y_test,rf.predict_proba(X_test)[:,1])
svc_auc=roc_auc_score(y_test,svc.decision_function(X_test))
print('AUC(随机森林):{:.3f}'.format(rf_auc))
print('AUC(SVC):{:.3f}'.format(svc_auc))

利用AUC分数来比较随机森林和SVM,我们发现随机森林的表现比SVM要略好一些。由于平均准确率是从0到1的曲线下的面积,所以平均准确率总是返回一个0到1之间的值。随机预测得到的AUC总是等于0.5,无论数据集中的类别多么不平衡。对于不平衡的分类问题来说,AUC是一个比精度好得多的指标。AUC可以被解释为评估整理样本的排名。它等价于从正类样本中随机挑选一个点,由分类器废除的分数比从反类样本中随机挑选一个点的分数更高的概率。因此,AUC最高为1,这说明所有正类点的分数高于所有反类点。对于不平衡类别的分类问题,使用AUC进行模型选择通常比使用精度更有意义。

我们使用SVM对之前(9&非9)数据集进行分类,分别使用三种不同的内核宽度(gamma)设置:

from sklearn.datasets import load_digits,make_blobs
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.svm import SVC
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
from sklearn.metrics import roc_curve,roc_auc_score

digits=load_digits()
y=digits.target==9
X_train,X_test,y_train,y_test=train_test_split(digits.data,y,random_state=0)
plt.figure()

for gamma in [1,0.1,0.01]:
    svc=SVC(gamma=gamma).fit(X_train,y_train)
    accuracy=svc.score(X_test,y_test)
    auc = roc_auc_score(y_test, svc.decision_function(X_test))
    fpr, tpr, _ = roc_curve(y_test, svc.decision_function(X_test))
    print('gamma={:.2f} accuracy={:.2f} AUC={:.2f}'.format(gamma,accuracy,auc))
    plt.plot(fpr,tpr,label='gamma={:.3f}'.format(gamma))

plt.xlabel('FPR')
plt.ylabel('TPR')
plt.xlim(-0.01,1)
plt.ylim(0,1.02)
plt.legend(loc='best')
plt.show()

 

对于3中不同的gamma设置,其精度是相同的,都等于0.9,这可能与随机森林的性能相同,也可能不同。但是观察AUC以及对应的曲线,我们可以看到三个模型之间有明显区别。对于gamma=1.0,AUC实际上处于随机水平,即decision_function的输出与随机结果一样好。对于gamma=0.1,性能大幅提升至AUC等于0.96。最后,对于gamma=0.01,我们得到了等于1 的完美AUC,这意味着根据决策函数,所有正类点的排名要高于所有反类点。换句话说,利用正确的阈值,这个模型可以对所有数据进行完美分类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1888841.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第206题反转链表

题目: 题解: # Definition for singly-linked list. # class ListNode: # def __init__(self, val0, nextNone): # self.val val # self.next next class Solution:def reverseList(self, head: Optional[ListNode]) -> Optio…

开源之夏|祝贺MatrixOne开源社区项目中选同学!

在本届「开源之夏 2024」活动中,MatrixOne开源社区共计上线3个项目任务,最终有 3位同学成功突围。接下来让我们看看每个项目的详细中选情况: 中选学生公示 项目名称:基于大语言模型的操作系统任务自动识别,拆解&#…

Seal^_^【送书活动第8期】——《ChatGLM3大模型本地化部署、应用开发与微调》

Seal^_^【送书活动第8期】——《ChatGLM3大模型本地化部署、应用开发与微调》 一、参与方式二、本期推荐图书2.1 作者建语2.2 编辑推建2.3 图书简介2.4 前 言2.5 目 录 三、正版购买 大模型领域 既是繁星点点的未知宇宙,也是蕴含无数可能的广阔天地, 正…

【Linux】—Hadoop运行环境搭建(完全分布式)

文章目录 前言一、模板虚拟机环境准备二、克隆虚拟机(以hadoop102为例)三、修改克隆机的IP四、安装JDK五、安装Hadoop(完全分布式)六、集群常用命令七、配置集群八、群起并测试集群九、配置历史服务器十、配置日志的聚集十一、集群…

华为DCN之:SDN和NFV

1. SDN概述 1.1 SDN的起源 SDN(Software Defined Network)即软件定义网络。是由斯坦福大学Clean Slate研究组提出的一种新型网络创新架构。其核心理念通过将网络设备控制平面与数据平面分离,从而实现了网络控制平面的集中控制,为…

电脑配置怎么看?3个方法轻松get,这些指标一看便知

无论是购买新电脑、升级现有配置,还是解决电脑运行问题,了解电脑的配置信息都显得尤为重要。那么,电脑配置怎么看?本文将为你介绍3个简单易行的方法,让你轻松获取电脑配置的关键指标,帮助你更好地了解和管理…

3.(vue3.x+vite)el-tree组件(数组结构数据转树结构数据)

1:效果预览 2:编写代码 (1)主页面 <template><el-tree ref="componentInfoTreeRef" :data="treeData

AOP基本概念

AOP&#xff08;Aspect-Oriented Programming&#xff0c;面向切面编程&#xff09;是一种编程范式&#xff0c;用于将横切关注点&#xff08;如日志记录、安全检查、事务管理等&#xff09;从业务逻辑中分离出来&#xff0c;以提高代码的模块化程度和可维护性。以下是AOP的核心…

参数污染漏洞(HPP)挖掘技巧及实战案例全汇总

目录 概念: 漏洞原理: 实战案例总结: 1. 逻辑漏洞(IDOR) 2. 绕过检测(WAF) 挖掘技巧: 修复方案: 概念: HTTP参数污染,也叫HPP(HTTP Parameter Pollution)。简单地讲就是给一个参数赋上两个或两个以上的值,由于现行的HTTP标准没有提及在遇到多个输入值给相…

2.2.3 C#中显示控件BDPictureBox 的实现----控件实现

2.2.3 C#中显示控件BDPictureBox 的实现----控件实现 1 界面控件布局 2图片内存Mat类说明 原始图片&#xff1a;m_raw_mat ,Display_Mat()调用时更新或者InitDisplay_Mat时更新局部放大显示图片&#xff1a;m_extract_zoom_mat&#xff0c;更新scale和scroll信息后更新overla…

第四届数字安全大会:AI时代数据安全策略与天空卫士创新实践

2024年6月22日&#xff0c;以 “新质•真能力”为主题的第四届数字安全大会在北京隆重召开。这场由数世咨询和CIO时代联合主办的行业盛会&#xff0c;集中探讨了大模型、数据治理与流通、以及安全运营等当前最前沿的议题。大会吸引了来自不同行业的首席信息官&#xff08;CIO&a…

JavaScript之深入对象,详细讲讲构造函数与常见内置构造函数

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是前端菜鸟的自我修养&#xff01;今天给大家详细讲讲构造函数与常见内置构造函数&#xff0c;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;原创不易&#xff0c;如果能帮助到带大家&#xff0c;欢迎…

【C++知识点总结全系列 (06)】:STL六大组件详细总结与分析- 配置器、容器、迭代器、适配器、算法和仿函数

STL六大组件目录 前言1、配置器(1)What(2)Why(3)HowA.调用new和delete实现内存分配与销毁B.STL Allocator (4)allocator类A.WhatB.HowC.allocator的算法 2、容器(1)What(2)Which&#xff08;有哪些容器&#xff09;(3)序列容器&#xff08;顺序容器&#xff09;A.WhichB.array&…

世界智能产业博览会开幕 - 天空卫士汽车行业方案入选优秀案例

6月20日&#xff0c;以“智行天下、能动未来”为主题的2024世界智能产业博览会在国家会展中心&#xff08;天津&#xff09;开幕。主席向博览会致贺信并指出&#xff1a;中国高度重视人工智能发展&#xff0c;积极推动互联网、大数据、人工智能和实体经济深度融合&#xff0c;培…

网页设计入门:必备学习技巧和方法总结

网页设计是一个创造性和具有挑战性的设计领域。学习网页设计不仅需要审美能力&#xff0c;还需要设计师有扎实的专业知识来完成各种类型的网页设计项目。要想在网页设计领域脱颖而出&#xff0c;需要不断学习相关知识&#xff0c;提高专业技能。本文将分享网页设计的学习技巧和…

【原理】随机森林模型是怎么训练的

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 目录 一、随机森林简介二、随机森林训练原理2.1. 随机森林的训练流程2.2. 随机森林训练的核心代码 用过随机森林的朋友都知道&#xff0c;随机森林是集成决策的一个经典代表&#xff0c;它通过训练多棵决策树&#xf…

未公开 GeoServer开源服务器wfs远程命令执行漏洞 已复现(CVE-2024-36401)

0x01 阅读须知 技术文章仅供参考&#xff0c;此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成…

【面试系列】UI设计师高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

bootloader原理介绍

bootloader解析 bootloader的引出 不知道你有没有想过这样一个问题&#xff0c;当你按下电源开关的那一瞬间&#xff0c;第一行代码是如何在芯片上运行起来的呢&#xff1f;我们都知道嵌入式软件代码&#xff0c;是需要通过一定的方式&#xff0c;烧录在硬件芯片中&#xff0c…

ubuntu安装搜狗\谷歌输入法

目录 1 安装搜狗输入法 1.1 安装Fcitx输入框架 1.2 下载搜狗输入法安装包 1.3 安装搜狗输入法 1.4 打开配置 1.5 选择fcitx 1.6 重启系统 1.7 配置输入法 1.8 添加搜狗输入法 1.9 使用 2 安装谷歌输入法 2.1 下载fcitx-googlepinyin 2.2 选择fcitx 2.3 重启系统 …