如何使用scikit learn计算多类情况下的精确度、召回率、准确率和f1-score?

2024-05-23 17:47:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个情绪分析问题,数据如下:

label instances
    5    1190
    4     838
    3     239
    1     204
    2     127

所以我的数据是不平衡的,因为1190instances被标记为5。使用scikit的SVC对Im进行分类。问题是我不知道如何以正确的方式平衡我的数据,以便准确计算多类情况下的精度、召回率、准确性和f1分数。所以我尝试了以下方法:

首先:

    wclf = SVC(kernel='linear', C= 1, class_weight={1: 10})
    wclf.fit(X, y)
    weighted_prediction = wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, weighted_prediction)
print 'F1 score:', f1_score(y_test, weighted_prediction,average='weighted')
print 'Recall:', recall_score(y_test, weighted_prediction,
                              average='weighted')
print 'Precision:', precision_score(y_test, weighted_prediction,
                                    average='weighted')
print '\n clasification report:\n', classification_report(y_test, weighted_prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, weighted_prediction)

第二:

auto_wclf = SVC(kernel='linear', C= 1, class_weight='auto')
auto_wclf.fit(X, y)
auto_weighted_prediction = auto_wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, auto_weighted_prediction)

print 'F1 score:', f1_score(y_test, auto_weighted_prediction,
                            average='weighted')

print 'Recall:', recall_score(y_test, auto_weighted_prediction,
                              average='weighted')

print 'Precision:', precision_score(y_test, auto_weighted_prediction,
                                    average='weighted')

print '\n clasification report:\n', classification_report(y_test,auto_weighted_prediction)

print '\n confussion matrix:\n',confusion_matrix(y_test, auto_weighted_prediction)

第三:

clf = SVC(kernel='linear', C= 1)
clf.fit(X, y)
prediction = clf.predict(X_test)


from sklearn.metrics import precision_score, \
    recall_score, confusion_matrix, classification_report, \
    accuracy_score, f1_score

print 'Accuracy:', accuracy_score(y_test, prediction)
print 'F1 score:', f1_score(y_test, prediction)
print 'Recall:', recall_score(y_test, prediction)
print 'Precision:', precision_score(y_test, prediction)
print '\n clasification report:\n', classification_report(y_test,prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, prediction)


F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1082: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
 0.930416613529

但是,我收到这样的警告:

/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172:
DeprecationWarning: The default `weighted` averaging is deprecated,
and from version 0.18, use of precision, recall or F-score with 
multiclass or multilabel data or pos_label=None will result in an 
exception. Please set an explicit value for `average`, one of (None, 
'micro', 'macro', 'weighted', 'samples'). In cross validation use, for 
instance, scoring="f1_weighted" instead of scoring="f1"

如何正确处理不平衡的数据,以便以正确的方式计算分类器的度量?


Tags: oroftestautouseprecisionf1score
3条回答

这里有很多非常详细的答案,但我认为你没有回答正确的问题。据我所知,有两个问题:

  1. 我如何解决一个多类问题?
  2. 如何处理不平衡数据?

您可以使用scikit learn中的大多数评分函数来处理多类问题和单类问题。例如:

from sklearn.metrics import precision_recall_fscore_support as score

predicted = [1,2,3,4,5,1,2,1,1,4,5] 
y_test = [1,2,3,4,5,1,2,1,1,4,1]

precision, recall, fscore, support = score(y_test, predicted)

print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))

这样,您就可以得到每个类的有形和可解释的数字。

| Label | Precision | Recall | FScore | Support |
|-------|-----------|--------|--------|---------|
| 1     | 94%       | 83%    | 0.88   | 204     |
| 2     | 71%       | 50%    | 0.54   | 127     |
| ...   | ...       | ...    | ...    | ...     |
| 4     | 80%       | 98%    | 0.89   | 838     |
| 5     | 93%       | 81%    | 0.91   | 1190    |

然后。。。

2

。。。你可以判断不平衡的数据是不是一个问题。如果代表性较低的课程(1级和2级)的得分低于训练样本较多的课程(4级和5级),则您知道不平衡数据实际上是一个问题,您可以相应地采取行动,如本主题中其他一些答案中所述。 然而,如果你想要预测的数据中存在相同的类分布,那么你的不平衡训练数据是数据的一个很好的代表,因此,不平衡是一件好事。

提出的问题

回答“数据不平衡的多类分类应使用什么度量”的问题:宏-F1-measure。 宏精度和宏回调也可以使用,但它们不像二进制分类那样容易解释,它们已经被纳入F-测度,并且多余的度量使方法比较、参数调整等复杂化。

微平均对类不平衡很敏感:例如,如果你的方法对最常见的标签很有效,而对其他标签则完全是一团糟,那么微平均度量会显示出很好的结果。

加权平均法不太适用于不平衡数据,因为它是按标签计数加权的。此外,它很难解释和不受欢迎:例如,在下面非常详细的survey中没有提到这样的平均值,我强烈建议仔细研究:

Sokolova, Marina, and Guy Lapalme. "A systematic analysis of performance measures for classification tasks." Information Processing & Management 45.4 (2009): 427-437.

特定于应用程序的问题

不过,回到你的任务,我将研究两个主题:

  1. 通常用于特定任务的度量-它允许(a)到 把你的方法和别人比较,了解你是否做了什么 错了,而且(b)不要自己去探索这个问题,并且重用某人 其他发现
  2. 不同方法错误的代价 例如,应用程序的用例可能依赖于4星和5星 只有被检阅者-在这种情况下,好的度量应该只计算这2 标签。

常用指标。 通过查阅文献,我可以推断出两个主要的评估指标:

  1. Accuracy,用于,例如

Yu, April, and Daryl Chang. "Multiclass Sentiment Prediction using Yelp Business."

link)-请注意,作者使用的评级分布几乎相同,请参见图5。

Pang, Bo, and Lillian Lee. "Seeing stars: Exploiting class relationships for sentiment categorization with respect to rating scales." Proceedings of the 43rd Annual Meeting on Association for Computational Linguistics. Association for Computational Linguistics, 2005.

link

  1. MSE(或者,更常见的是,平均绝对误差-MAE)-例如,请参见

Lee, Moontae, and R. Grafe. "Multiclass sentiment analysis with restaurant reviews." Final Projects from CS N 224 (2010).

link)-他们探索精度和最小均方误差,认为后者更好

Pappas, Nikolaos, Rue Marconi, and Andrei Popescu-Belis. "Explaining the Stars: Weighted Multiple-Instance Learning for Aspect-Based Sentiment Analysis." Proceedings of the 2014 Conference on Empirical Methods In Natural Language Processing. No. EPFL-CONF-200899. 2014.

link)-他们利用scikit learn进行评估和基线方法,并声明他们的代码是可用的;但是,我找不到它,所以如果您需要它,请写信给作者,这项工作非常新,似乎是用Python编写的。

不同错误的成本 如果你更关心避免重大失误,例如协助1-star到5-star的评论或类似的事情,看看MSE; 如果差异很重要,但不重要,可以试试MAE,因为它不是diff的平方; 否则保持准确。

关于方法,而不是指标

尝试回归方法,例如SVR,因为它们通常优于SVC或OVA-SVM等多类分类器。

我想人们对用什么重量做什么有很多困惑。我不确定我到底知道什么困扰着你,所以我要涵盖不同的主题,忍受我;)。

类权重

来自class_weight参数的权重用于训练分类器。 它们不用于计算您正在使用的任何度量:对于不同的类权重,数字将不同,因为分类器不同。

基本上,在每个scikit学习分类器中,类权重用于告诉模型类有多重要。这意味着,在训练过程中,分类器将付出额外的努力,对具有高权重的类进行适当的分类。
他们是如何做到这一点的是算法的具体情况。如果你想知道它是如何为SVC工作的,而doc对你来说没有意义,请尽管提一下。

指标

一旦你有了一个分类器,你就想知道它的性能如何。 在这里你可以使用你提到的指标:accuracyrecall_scoref1_score。。。

通常当类分布不平衡时,精确性被认为是一个很差的选择,因为它给只预测最频繁类的模型带来了高分。

我不会详细说明所有这些度量,但请注意,除了accuracy,它们自然应用于类级别:正如您在分类报告的print中看到的,它们是为每个类定义的。它们依赖于诸如true positivesfalse negative之类的概念,这些概念要求定义哪个类是正的类。

             precision    recall  f1-score   support

          0       0.65      1.00      0.79        17
          1       0.57      0.75      0.65        16
          2       0.33      0.06      0.10        17
avg / total       0.52      0.60      0.51        50

警告

F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The 
default `weighted` averaging is deprecated, and from version 0.18, 
use of precision, recall or F-score with multiclass or multilabel data  
or pos_label=None will result in an exception. Please set an explicit 
value for `average`, one of (None, 'micro', 'macro', 'weighted', 
'samples'). In cross validation use, for instance, 
scoring="f1_weighted" instead of scoring="f1".

您收到此警告是因为您正在使用f1分数、召回率和精确度,而没有定义应如何计算这些分数、召回率和精确度! 问题可以重新表述:从上述分类报告中,如何为f1分数输出1全局数? 你可以:

  1. 取每个类的f1分数的平均值:这就是上面的avg / total结果。它也被称为平均值。
  2. 使用真阳性/假阴性等的全局计数来计算f1分数(将每个类的真阳性/假阴性数相加)。Akamicro平均值。
  3. 计算f1分数的加权平均值。在scikit learn中使用'weighted'将通过类的支持来衡量f1分数:一个类拥有的元素越多,这个类的f1分数在计算中就越重要。

这是scikit learn中的3个选项,警告是您必须选择其中一个。所以必须为score方法指定一个average参数。

你选择哪一个取决于你想如何衡量分类器的性能:例如宏平均不考虑类不平衡,类1的f1分数和类5的f1分数同样重要。但是如果你使用加权平均法,你会对第五课更重要。

这些度量标准中的整个参数规范在scikit learn中不是非常清楚,根据文档,它在0.18版中会变得更好。他们正在删除一些不明显的标准行为,并发出警告,以便开发人员注意到它。

计算分数

我最不想提的是(如果你知道的话,可以跳过它)分数只有在基于分类器从未见过的数据计算时才有意义。 这一点非常重要,因为在拟合分类器时使用的数据上得到的任何分数都是完全不相关的。

这里有一种使用StratifiedShuffleSplit的方法,它给您一个数据的随机分割(在洗牌之后),以保持标签分布。

from sklearn.datasets import make_classification
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, classification_report, confusion_matrix

# We use a utility to generate artificial classification data.
X, y = make_classification(n_samples=100, n_informative=10, n_classes=3)
sss = StratifiedShuffleSplit(y, n_iter=1, test_size=0.5, random_state=0)
for train_idx, test_idx in sss:
    X_train, X_test, y_train, y_test = X[train_idx], X[test_idx], y[train_idx], y[test_idx]
    svc.fit(X_train, y_train)
    y_pred = svc.predict(X_test)
    print(f1_score(y_test, y_pred, average="macro"))
    print(precision_score(y_test, y_pred, average="macro"))
    print(recall_score(y_test, y_pred, average="macro"))    

希望这有帮助。

相关问题 更多 >