scikit上的多标签分类指标


19

我正在尝试构建多标签分类器,以便使用scikit将主题分配给现有文档

我正在处理我的文档,将它们通过传递给TfidfVectorizer标签,MultiLabelBinarizerOneVsRestClassifierSGDClassifier作为估算器创建了。

但是,当测试我的分类器时,我只能得到0.29的分数,对于类似的问题,从我的阅读中得出的分数非常低。我在TfidfVectorizer上尝试了多个选项,例如停用词,单字组,词干,似乎没有什么改变结果。

我还习惯于GridSearchCV为估算器获取最佳参数,目前我对下一步的想法一无所知。

同时,根据我的理解,我无法使用它scikit.metricsOneVsRestClassifier那么我如何获得一些指标(F1,Precision,Recall等)以找出问题所在?

我的数据语料库可能有问题吗?

更新:我也尝试使用CountVectorizerHashingVectorizer管道化它们,TfidfTransformer但结果相似。所以我猜想词袋方法在标记化领域中表现最好,其余的取决于分类器...


1
什么是0.29测量?准确性?还有吗
Sycorax说恢复莫妮卡

@GeneralAbrial根据score分类器上运行的scikit文档,Returns the mean accuracy on the given test data and labels. In multi-label classification, this is the subset accuracy which is a harsh metric since you require for each sample that each label set be correctly predicted.
mobius

那是你做的吗?从您的问题根本不清楚是这种情况,所以这是一个完全合理的问题。
Sycorax说恢复莫妮卡

@GeneralAbrial是的,这就是我所做的。很抱歉让我感到困惑,我试图将问题保持在一种理论上的模式,而不是一种发展的模式。
mobius

您能在这里添加您的代码吗?具体来说,您是否将sample_weight =“ balanced”用于SGD?但是,一旦我们看到您的代码,可能还会有其他事情要注意。
迭戈

Answers:


21

子集精度确实是一个苛刻的指标。为了了解0.29的好坏,一些想法:

  • 看一下每个样本平均有多少个标签
  • 查看注释者之间的协议(如果可用)(如果不可行,请尝试一下,看看您是分类器时获得了什么子集准确性)
  • 考虑主题是否定义明确
  • 看看每个标签有多少样本

您可能还需要计算汉明分数,以查看分类器是否无能为力,还是不错,但在正确预测所有标签方面存在问题。参见下文以计算汉明得分。

同时,据我了解,我无法将scikit.metrics与OneVsRestClassifier一起使用,因此如何获取一些指标(F1,Precision,Recall等)以找出问题所在?

请参阅如何为多类-多标签分类计算精度/召回率?。我忘了sklearn是否支持它,我记得它有一些局限性,例如sklearn不支持混淆矩阵的多标签。确实看到这些数字将是一个好主意。


海明得分

标签分类设置中,sklearn.metrics.accuracy_score仅计算子集准确性(3):即,为样本预测的标签集必须与y_true中的相应标签集完全匹配。

这种计算准确性的方法有时被称为精确匹配率(1),可能不太明确:

在此处输入图片说明

计算精度的另一种典型方法是在(1)和(2)中定义,并且不太明确地称为汉明得分(4)(因为它与汉明损耗密切相关)或基于标签的精度。计算如下:

在此处输入图片说明

这是一个计算汉明分数的python方法:

# Code by /programming//users/1953100/william
# Source: /programming//a/32239764/395857
# License: cc by-sa 3.0 with attribution required

import numpy as np

y_true = np.array([[0,1,0],
                   [0,1,1],
                   [1,0,1],
                   [0,0,1]])

y_pred = np.array([[0,1,1],
                   [0,1,1],
                   [0,1,0],
                   [0,0,0]])

def hamming_score(y_true, y_pred, normalize=True, sample_weight=None):
    '''
    Compute the Hamming score (a.k.a. label-based accuracy) for the multi-label case
    /programming//q/32239577/395857
    '''
    acc_list = []
    for i in range(y_true.shape[0]):
        set_true = set( np.where(y_true[i])[0] )
        set_pred = set( np.where(y_pred[i])[0] )
        #print('\nset_true: {0}'.format(set_true))
        #print('set_pred: {0}'.format(set_pred))
        tmp_a = None
        if len(set_true) == 0 and len(set_pred) == 0:
            tmp_a = 1
        else:
            tmp_a = len(set_true.intersection(set_pred))/\
                    float( len(set_true.union(set_pred)) )
        #print('tmp_a: {0}'.format(tmp_a))
        acc_list.append(tmp_a)
    return np.mean(acc_list)

if __name__ == "__main__":
    print('Hamming score: {0}'.format(hamming_score(y_true, y_pred))) # 0.375 (= (0.5+1+0+0)/4)

    # For comparison sake:
    import sklearn.metrics

    # Subset accuracy
    # 0.25 (= 0+1+0+0 / 4) --> 1 if the prediction for one sample fully matches the gold. 0 otherwise.
    print('Subset accuracy: {0}'.format(sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)))

    # Hamming loss (smaller is better)
    # $$ \text{HammingLoss}(x_i, y_i) = \frac{1}{|D|} \sum_{i=1}^{|D|} \frac{xor(x_i, y_i)}{|L|}, $$
    # where
    #  - \\(|D|\\) is the number of samples  
    #  - \\(|L|\\) is the number of labels  
    #  - \\(y_i\\) is the ground truth  
    #  - \\(x_i\\)  is the prediction.  
    # 0.416666666667 (= (1+0+3+1) / (3*4) )
    print('Hamming loss: {0}'.format(sklearn.metrics.hamming_loss(y_true, y_pred))) 

输出:

Hamming score: 0.375
Subset accuracy: 0.25
Hamming loss: 0.416666666667

(1)Sorower,Mohammad S.“ 关于多标签学习算法的文献调查。 ”俄勒冈州立大学,科瓦利斯(2010)。

(2)Tsoumakas,Grigorios和Ioannis Katakis。“ 多标签分类:概述。 ”希腊塞萨洛尼基亚里斯多德大学信息学系(2006年)。

(3)Ghamrawi,Nadia和Andrew McCallum。“ 集体多标签分类。 ”第14届ACM信息和知识管理国际会议论文集。ACM,2005年。

(4)Godbole,Shantanu和Sunita Sarawagi。“ 多标签分类的判别方法。 ”知识发现和数据挖掘的进展。Springer Berlin Heidelberg,2004年。22-30。


很好的答案,它使我变得更好:)我将更仔细地阅读它,尝试汉明分数并回复您!
mobius

老实说,我不清楚这是什么子集的准确度(精确匹配率)。您能再解释一下吗?在多类的情况下,这似乎与召回相同。
诗人莫迪

hamming_score函数的错误列于Keras:<IPython的输入-34-16066d66dfdd>在hamming_score(y_true,y_pred,正常化,sample_weight)60 ''” 61 acc_list = [] ---> 62为i的范围(y_true.shape [ 0]):63 set_true = set(np.where(y_true [i])[0])64 set_pred = set(np.where(y_pred [i])[0])TypeError:索引返回了非int类型(类型NoneType )
rjurney

0

0.29得分还不够吗?您的混淆矩阵是什么样的?是否有些仅通过查看单词内容就无法将其分离出来的主题?

否则,请尝试解决您的问题:假设低分实际上是分类器可以对数据进行的最佳处理。这意味着使用这种方法无法对您的文档进行分类。

要测试这个假设,您需要一组具有已知单词袋特征(由您自己创建)的测试文档。您应该获得100%的分数。

如果不这样做,那么您就有一个错误。否则,您需要使用其他方法对文档进行分类。问自己:不同类别的文档之间有何不同?我是否需要查看文档的其他功能,等等。


除了数字,我还感觉到0.29很低。我使用经过训练的模型来预测我已经在训练中用于手动测试分类器的文档上的主题。我无法获得至少与用户在文档上手动输入的主题数量相同的主题。我通常只是得到其中的一部分。此外,关于混淆矩阵问题,我认为我无法使用scikit.metrics在OneVsRestClassifier上获得混淆矩阵...不过,我会检查一下
mobius
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.