面对ValueError:目标是多类的,但average ='binary'

Int*_*777 5 python scikit-learn

我是python和机器学习的新手。根据我的要求,我正在尝试对数据集使用朴素贝叶斯算法。

我能够找出准确度,但尝试找出准确度并回想一下。但是,它引发以下错误:

   "choose another average setting." % y_type)
ValueError: Target is multiclass but average='binary'. Please choose another average setting.
Run Code Online (Sandbox Code Playgroud)

谁能建议我如何进行。我曾尝试在平均值和召回率分数中使用average ='micro'。它的工作原理没有任何错误,但在准确性,准确性和召回率上却给出了相同的分数。

我的数据集:

train_data.csv:

review,label
Colors & clarity is superb,positive
Sadly the picture is not nearly as clear or bright as my 40 inch Samsung,negative
Run Code Online (Sandbox Code Playgroud)

test_data.csv:

review,label
The picture is clear and beautiful,positive
Picture is not clear,negative
Run Code Online (Sandbox Code Playgroud)

我的代码:

from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import BernoulliNB
from sklearn.metrics import confusion_matrix
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score


def load_data(filename):
    reviews = list()
    labels = list()
    with open(filename) as file:
        file.readline()
        for line in file:
            line = line.strip().split(',')
            labels.append(line[1])
            reviews.append(line[0])

    return reviews, labels

X_train, y_train = load_data('/Users/abc/Sep_10/train_data.csv')
X_test, y_test = load_data('/Users/abc/Sep_10/test_data.csv')

vec = CountVectorizer() 

X_train_transformed =  vec.fit_transform(X_train) 

X_test_transformed = vec.transform(X_test)

clf= MultinomialNB()
clf.fit(X_train_transformed, y_train)

score = clf.score(X_test_transformed, y_test)
print("score of Naive Bayes algo is :" , score)

y_pred = clf.predict(X_test_transformed)
print(confusion_matrix(y_test,y_pred))

print("Precision Score : ",precision_score(y_test,y_pred,pos_label='positive'))
print("Recall Score :" , recall_score(y_test, y_pred, pos_label='positive') )
Run Code Online (Sandbox Code Playgroud)

Viv*_*mar 6

您需要添加'average'参数。根据文档

平均值:字符串,[无,“二进制”(默认),“微”,“宏”,“样本”,“加权”]

This parameter is required for multiclass/multilabel targets. If None, the 
scores for each class are returned. Otherwise, this
determines the type of averaging performed on the data:
Run Code Online (Sandbox Code Playgroud)

做这个:

print("Precision Score : ",precision_score(y_test, y_pred, 
                                           pos_label='positive'
                                           average='micro'))
print("Precision Score : ",recall_score(y_test, y_pred, 
                                           pos_label='positive'
                                           average='micro'))
Run Code Online (Sandbox Code Playgroud)

替换'micro'为以上任一选项'binary'。同样,在多类设置中,不需要提供,'pos_label'因为无论如何它将被忽略。

更新评论:

是的,它们可以相等。它在用户指南中给出:

请注意,对于包含所有标签的多类设置中的“微”平均,将产生相等的精度,召回率和F,而“加权”平均可能会产生不在精度和召回率之间的F分数。

  • 我在准确率和召回率分数中添加了 average ='micro',但在准确率、准确率和召回率方面我得到了相同的分数。是否有可能对上述所有三个参数获得相同的分数? (4认同)

cot*_*ail 5

这个错误是不言自明的。也就是说,对于超过 2 个类别的问题,需要某种平均规则。有效的规则是:'micro''macro'和(文档列出了'weighted',但它不适用于多类目标)。None'samples'

如果我们查看其源代码,在精度和召回分数计算方面,多类问题会被视为多标签问题,因为使用的底层混淆矩阵 ( multilabel_confusion_matrix) 是相同的。1此混淆矩阵创建一个 3D 数组,其中每个“子矩阵”都是 2x2 混淆矩阵,其中正值是标签之一。

每个平均规则之间有什么区别?

  • 使用average=None,返回每个类别的精确度/召回率分数(不进行任何平均),因此我们得到一个长度等于类别数量的分数数组。2

  • 使用 时average='macro',会计算每个类别的精度/召回率,然后取平均值。其公式如下:

    宏

  • 有了average='micro',所有类别的贡献就被相加来计算平均精度/召回率。其公式如下:

    微

  • average='weighted'实际上是加权宏观平均值,其中权重是实际的正类。其公式如下:

    加权


让我们考虑一个例子。

import numpy as np
from sklearn import metrics
y_true, y_pred = np.random.default_rng(0).choice(list('abc'), size=(2,100), p=[.8,.1,.1])
mcm = metrics.multilabel_confusion_matrix(y_true, y_pred)
Run Code Online (Sandbox Code Playgroud)

上面计算的多标签混淆矩阵如下所示。

混淆矩阵

各自的准确率/召回率分数如下:

  • average='macro'准确率/召回率是:

    recall_macro = (57 / (57 + 16) + 1 / (1 + 10) + 6 / (6 + 10)) / 3
    precision_macro = (57 / (57 + 15) + 1 / (1 + 13) + 6 / (6 + 8)) / 3
    
    # verify using sklearn.metrics.precision_score and sklearn.metrics.recall_score
    recall_macro == metrics.recall_score(y_true, y_pred, average='macro')        # True
    precision_macro == metrics.precision_score(y_true, y_pred, average='macro')  # True
    
    Run Code Online (Sandbox Code Playgroud)
  • average='micro'准确率/召回率是:

    recall_micro = (57 + 1 + 6) / (57 + 16 + 1 + 10 + 6 + 10)
    precision_micro = (57 + 1 + 6) / (57 + 15 + 1 + 13 + 6 + 8)
    
    # verify using sklearn.metrics.precision_score and sklearn.metrics.recall_score
    recall_micro == metrics.recall_score(y_true, y_pred, average='micro')        # True
    precision_micro == metrics.precision_score(y_true, y_pred, average='micro')  # True
    
    Run Code Online (Sandbox Code Playgroud)
  • average='weighted'准确率/召回率是:

    recall_weighted = (57 / (57 + 16) * (57 + 16) + 1 / (1 + 10) * (1 + 10) + 6 / (6 + 10) * (6 + 10)) / (57 + 16 + 1 + 10 + 6 + 10)
    precision_weighted = (57 / (57 + 15) * (57 + 16) + 1 / (1 + 13) * (1 + 10) + 6 / (6 + 8) * (6 + 10)) / (57 + 16 + 1 + 10 + 6 + 10)
    
    # verify using sklearn.metrics.precision_score and sklearn.metrics.recall_score
    recall_weighted == metrics.recall_score(y_true, y_pred, average='weighted')        # True
    precision_weighted == metrics.precision_score(y_true, y_pred, average='weighted')  # True
    
    Run Code Online (Sandbox Code Playgroud)

正如您所看到的,这里的示例是不平衡的(类的a频率为 80%,而bc各为 10%)。平均规则之间的主要区别在于,'macro'平均不考虑类别不平衡,但'micro''weighted'考虑类别不平衡。因此'macro'对类别不平衡很敏感,并且可能会根据不平衡情况导致“人为”高分或低分。

另外,从公式中很容易看出,回忆分数'micro''weighted'是相等的。

为什么准确率 == 召回率 == 精度 == f1-score average='micro'

从视觉上看可能更容易理解。

如果我们看一下上面构建的多标签混淆矩阵,每个子矩阵对应一个 One vs Rest 分类问题;即在子矩阵的每个列/行中,考虑其他两个标签。

例如,对于第一个子矩阵,有

  • 57 个真实阳性 ( a)
  • 16 个假阴性(或者bc
  • 15 个误报(或者bc
  • 12 个真阴性

对于精度/召回率的计算,只有 TP、FN 和 FP 重要。如上所述,FN 和 FP 计数可以是bc;由于它是二进制的,因此该子矩阵本身无法说明每个子矩阵的预测数量;但是,我们可以通过简单地调用该方法来计算多类混淆矩阵,从而准确确定其中有多少个被正确分类confusion_matrix()

mccm = metrics.confusion_matrix(y_true, y_pred)
Run Code Online (Sandbox Code Playgroud)

下图mccm使用不同的背景颜色绘制了相同的混淆矩阵 ( )(黄色背景对应于 TP,红色背景对应于第一个子矩阵中的假阴性,橙色对应于第三个子矩阵中的假阳性等)。所以这些实际上是多标签混淆矩阵中的 TP、FN 和 FP,它们被“扩展”以准确解释负类。左图的配色方案与多标签混淆矩阵中 TP 和 FN 计数的颜色(用于确定召回率)相匹配,右图的配色方案与 TP 和 FP 的颜色(用于确定精度)相匹配。

混淆矩阵

其中average='micro',黄色背景数字与左图中所有数字的比率决定召回率,黄色背景数字与右图中所有数字的比率决定精确率。如果我们仔细观察,相同的比率也决定了准确性。此外,由于f1-score是精度召回率的调和平均值,并且假设它们相等,因此我们有关系recall == precision == accuracy == f1-score