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

目录

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 npdisits=load_digits()
y=disits.target==9X_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 SVCplt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = FalseX,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'] = FalseX,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'] = FalseX,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_scoredigits=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.mzph.cn/news/865224.shtml

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

相关文章

云原生之容器编排实践-OpenEuler23.09在线安装Kubernetes与KubeSphere

背景 前几篇文章中介绍了如何将 ruoyi-cloud 项目部署到 Kubernetes 集群中,包括网关服务、认证服务和系统服务并且对全部服务采用 YAML 文件的方式来进行部署,这虽然有助于理解 K8S 组织管理资源的风格与底层机制,但是对于团队中不太熟悉命…

代码随想录算法训练营第21天|LeetCode 669. 修剪二叉搜索树、108.将有序数组转换为二叉搜索树、538.把二叉搜索树转换为累加树

1.LeetCode 669. 修剪二叉搜索树 题目链接:https://leetcode.cn/problems/trim-a-binary-search-tree/description/ 文章链接:https://programmercarl.com/0669.修剪二叉搜索树.html 视频链接:https://www.bilibili.com/video/BV17P41177ud?…

【网络】网络基础(一)

网络基础(一) 文章目录 一、计算机网络背景1.1网络发展1.2认识“协议” 二、网络协议初识2.1OSI七层模型2.2OSI五层模型 三、网络传输基本流程3.1局域网通信3.2网络传输流程不跨子网的网络传输跨子网的网络传输 3.3网络中的地址管理IP地址MAC地址 一、计…

Kotlin中的数据类型

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

冒泡排序写法

正宗的冒泡排序写法&#xff1a; public class BubbleSort {public static void main(String[] args) {int[] a {4,6,5,24,3,7,1};//初始化一个最大角标变量int n a.length-1;//循环轮次for (int i0;i<n;i){//从后向前开始&#xff0c;相邻元素比较大小&#xff0c;小的元…

Batch Size 不同对evaluation performance的影响

目录 问题描述如果是bugbatch size的设置问题尝试使用GroupNorm解决batchsize不同带来的问题归一化的分类 参考文章 问题描述 深度学习网络训练时&#xff0c;使用较小的batch size训练网络后&#xff0c;如果换用较大的batch size进行evaluation&#xff0c;网络的预测能力会…

Python基础001

Python输出语句 print输出字符串 print("中国四大名著&#xff1a;","西游记|","三国演义|","红楼梦|","水浒传") print(6) print(1 1)Python输入语句 input函数 input() input("我的名字是&#xff1a;") p…

RK3568驱动指南|第十五篇 I2C-第182章 使用Linux中默认的模拟I2C驱动程序

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

线性代数笔记

行列式 求高阶行列式 可以划上三角 上三角 余子式 范德蒙行列式 拉普拉斯公式 行列式行列对换值不变 矩阵 矩阵的运算 同型矩阵加减 对应位置相加减 矩阵的乘法 左边第 i 行 一次 相乘求和 右边 第 j 列 eg 中间相等 两边规模 矩阵的幂运算 解题思路 找规律 数学归纳…

CVE-2024-6387 分析

文章目录 1. 漏洞成因2. 漏洞利用前置知识2.1 相关 SSH 协议报文格式2.2 Glibc 内存分配相关规则 3. POC3.1 堆内存布局3.2 服务端解析数据时间测量3.3 条件竞争3.4 FSOP 4. 相关挑战 原文链接&#xff1a;个人博客 近几天&#xff0c;OpenSSH爆出了一个非常严重的安全漏洞&am…

重生奇迹mu精灵之心怎么搭配

玩家可以通过召唤来召唤多种精灵之心&#xff0c;每种精灵之心增加的属性也不同。精灵之心的作用是为了提升各种各样的属性。我们可以通过召唤获得精灵之心&#xff0c;前面的解锁费用较低&#xff0c;而后面的解锁需要大量的金币来解锁。 召唤精灵之心后&#xff0c;我们可以…

数据结构(JAVA)—代码题

01-数据结构—判断题 02-数据结构—选择题 03 数据结构—多选填空程序填空 ​ 01-顺序表的建立及遍历 import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; import java.util.Scanner;public class Main {public static void main(St…

Hadoop-09-HDFS集群 JavaClient 代码上手实战!详细附代码 安装依赖 上传下载文件 扫描列表 PUT GET 进度条显示

章节内容 上一节完成&#xff1a; HDFS的集群启动HDFS的命令行操作HDFS 上传下载移动重命名等操作 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&#xff0c;但是没…

基于FPGA的DDS信号发生器

前言 此处仅为基于Vivado实现DDS信号发生器的仿真实现&#xff0c;Vivado的安装请看下面的文章&#xff0c;这里我只是安装了一个标准版本&#xff0c;只要能够仿真波形即可。 FPGA开发Vivado安装教程_vivado安装 csdn-CSDN博客 DDS原理 DDS技术是一种通过数字计算生成波形…

Pandas_DataFrame读写详解:案例解析(第24天)

系列文章目录 一、 读写文件数据 二、df查询数据操作 三、df增加列操作 四、df删除行列操作 五、df数据去重操作 六、df数据修改操作 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、 读写文…

Web 基础与 HTTP 协议

Web 基础与 HTTP 协议 一、Web 基础1.1域名和 DNS域名的概念Hosts 文件DNS&#xff08;Domain Name System 域名系统&#xff09;域名注册 1.2网页与 HTML网页概述HTML 概述网站和主页Web1.0 与 Web2.0 1.3静态网页与动态网页静态网页动态网页 二、HTTP 协议1.1HTTP 协议概述1.…

秋招——MySQL补充——MySQL是如何加行级锁

文章目录 引言正文什么SQL语句会加行级锁查询操作增加对应的行级锁事务的写法 update和delete修改操作也会增加行级锁 行级锁有哪些种类记录锁间隙锁Next-Key锁 MySQL是如何加行级锁&#xff1f;唯一索引等值查询查询记录是存在的查询记录是不存在的 唯一索引范围查找针对大于或…

《梦醒蝶飞:释放Excel函数与公式的力量》8.4 COUNTIF函数

8.4 COUNTIF函数 COUNTIF函数是Excel中常用的统计函数之一&#xff0c;用于统计指定条件下的单元格数量。通过COUNTIF函数&#xff0c;我们可以轻松地对数据进行条件筛选和统计分析。下面将从函数简介、语法、基本用法、注意事项、高级应用、实战练习和小节几个方面展开介绍。…

爬虫笔记19——代理IP的使用

访问网站时IP被阻止 有些网站会设置特定规则来限制用户的访问&#xff0c;例如频率限制、单一账户多次登录等。 网站为了保护自身安全和用户体验&#xff0c;会设置防御机制&#xff0c;将涉嫌恶意行为的IP地址加入黑名单并屏蔽访问。如果用户在使用网站时违反了这些规则&…