Scikit-learn 和 Yellowbrick 给出不同的分数

Posted

技术标签:

【中文标题】Scikit-learn 和 Yellowbrick 给出不同的分数【英文标题】:Scikit-learn and Yellowbrick giving different scores 【发布时间】:2021-02-15 03:15:47 【问题描述】:

我正在使用 sklearn 来计算分类器的平均精度和 roc_auc,并使用 Yellowbrick 来绘制 roc_auc 和精度召回曲线。问题是这些包在两个指标中给出的分数不同,我不知道哪个是正确的。

使用的代码:

import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from yellowbrick.classifier import ROCAUC
from yellowbrick.classifier import PrecisionRecallCurve
from sklearn.datasets import make_classification
from sklearn.metrics import roc_auc_score
from sklearn.metrics import average_precision_score

seed = 42

# provides de data
X, y = make_classification(n_samples=1000, n_features=2, n_redundant=0,
                           n_informative=2, random_state=seed)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

clf_lr = LogisticRegression(random_state=seed)
clf_lr.fit(X_train, y_train)

y_pred = clf_lr.predict(X_test)
roc_auc = roc_auc_score(y_test, y_pred)
avg_precision = average_precision_score(y_test, y_pred)
print(f"ROC_AUC: roc_auc")
print(f"Average_precision: avg_precision")
print('='*20)

# visualizations
viz3 = ROCAUC(LogisticRegression(random_state=seed))
viz3.fit(X_train, y_train) 
viz3.score(X_test, y_test)
viz3.show()
viz4 = PrecisionRecallCurve(LogisticRegression(random_state=seed))
viz4.fit(X_train, y_train)
viz4.score(X_test, y_test)
viz4.show()

代码产生以下输出:

如上所示,指标根据包的不同给出不同的值。在打印语句中是由 scikit-learn 计算的值,而在图中显示的是由 Yellowbrick 计算的值。

【问题讨论】:

请用这两个包给出的确切结果更新您的帖子;事实上,它一点也不明显,图表与问题的相关性也不明显(两者似乎都来自黄砖)。 @desertnaut scikit-learn 计算的 auc 分数和平均精度在 print 语句中,而 Yellowbric 计算的值出现在图中的注释中。我编辑帖子以澄清这一点。 【参考方案1】:

由于您使用 scikit-learn 的 predict 方法,您的预测 y_pred 是硬类成员,而不是概率:

np.unique(y_pred)
# array([0, 1])

但是对于 ROC 和 Precision-Recall 计算,情况应该不是;您传递给这些方法的预测应该是概率,而不是硬类。来自average_precision_scoredocs:

y_score:数组,形状 = [n_samples] 或 [n_samples, n_classes]

目标分数,可以是正类的概率估计、置信度值或决策的非阈值度量(如 由某些分类器上的“decision_function”返回)。

non-thresholded 的意思是不是硬类roc_auc_score (docs) 也是如此。

使用以下代码更正此问题,使 scikit-learn 结果与 Yellowbrick 返回的结果相同:

y_pred = clf_lr.predict_proba(X_test)     # get probabilities
y_prob = np.array([x[1] for x in y_pred]) # keep the prob for the positive class 1
roc_auc = roc_auc_score(y_test, y_prob)
avg_precision = average_precision_score(y_test, y_prob)
print(f"ROC_AUC: roc_auc")
print(f"Average_precision: avg_precision")

结果:

ROC_AUC: 0.9545954595459546
Average_precision: 0.9541994473779806

由于 Yellowbrick 会在内部(并且透明地)处理所有这些计算细节,因此它不会受到此处手动 scikit-learn 过程中的错误的影响。


请注意,在二进制情况下(如此处),您可以(并且应该)使用 binary=True 参数使您的图不那么混乱:

viz3 = ROCAUC(LogisticRegression(random_state=seed), binary=True) # similarly for the PrecisionRecall curve

而且,与人们可能直观地期望的相反,至少对于二进制情况,ROCAUCscore 方法将返回 AUC,但精度,如在docs:

viz3.score(X_test, y_test)
# 0.88

# verify this is the accuracy:

from sklearn.metrics import accuracy_score
accuracy_score(y_test, clf_lr.predict(X_test))
# 0.88

【讨论】:

以上是关于Scikit-learn 和 Yellowbrick 给出不同的分数的主要内容,如果未能解决你的问题,请参考以下文章

高斯混合模型:Spark MLlib 和 scikit-learn 之间的区别

LibSVM 和 scikit-learn 的不同精度

nltk 和 scikit-learn 的安装

spaCy 和 scikit-learn 向量化器

“OneVsRestClassifier”(Scikit-learn)和“Binary Relevance”(Scikit-multilearn)有啥区别?

scikit-learn 中的 SVC 和 LinearSVC 在啥参数下是等效的?