Multilabel-Klassifizierungsmetriken für Scikit

19

Ich versuche, einen Multi-Label-Klassifikator zu erstellen, um vorhandenen Dokumenten mithilfe von Scikit Themen zuzuweisen

Ich bearbeite meine Dokumente, indem ich sie über TfidfVectorizerdie Etiketten durch die MultiLabelBinarizerund OneVsRestClassifiermit einerSGDClassifier als Schätzer erstellte.

Beim Testen meines Klassifikators erhalte ich jedoch nur Punkte bis zu 0,29 , was nach meiner Lektüre für ähnliche Probleme ziemlich niedrig ist. Ich habe mehrere Optionen auf dem TfidfVectorizer ausprobiert, wie Stoppwörter, Unigramme, Stemming und nichts scheint das Ergebnis so sehr zu verändern.

Habe ich auch benutzt GridSearchCV , um die besten Parameter für meinen Schätzer zu erhalten, und derzeit habe ich keine Ideen, was ich als nächstes versuchen soll.

Gleichzeitig kann ich nach meinem Verständnis nicht verwenden scikit.metrics , mit OneVsRestClassifierwie kann ich einige Metriken erhalten (F1, Präzision, Rückruf usw.), um herauszufinden , was falsch ist?

Könnte es ein Problem mit meinem Datenkorpus sein?

Update: Ich habe auch versucht, sie zu verwenden CountVectorizerund zu HashingVectorizerpipelining, TfidfTransformeraber die Ergebnisse sind ähnlich. Ich vermute also, dass der Bag-of-Word-Ansatz im Bereich der Tokenisierung am besten funktioniert und der Rest dem Klassifikator überlassen bleibt ...

mobius
quelle
1
Was misst 0,29? Richtigkeit? Etwas anderes?
Sycorax sagt Reinstate Monica
@GeneralAbrial Laut Scikit-Dokumentation, die scoreauf dem Klassifikator läuft ,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
Hast du das getan? Aus Ihrer Frage geht überhaupt nicht hervor, dass dies der Fall ist, daher ist es eine durchaus vernünftige Frage.
Sycorax sagt Reinstate Monica
@ GeneralAbrial Ja, das habe ich getan. Entschuldigen Sie die Verwirrung, ich habe versucht, die Frage eher in einem theoretischen als in einem Entwicklungsmodus zu halten.
Möbius
Können Sie bitte Ihren Code hier hinzufügen? Verwenden Sie speziell sample_weight = "balanced" für SGD? Es gibt jedoch möglicherweise andere Dinge zu beachten, sobald wir Ihren Code sehen.
Diego

Antworten:

21

Die Genauigkeit der Teilmenge ist in der Tat eine harte Metrik. Um ein Gefühl dafür zu bekommen, wie gut oder schlecht 0,29 ist, haben wir eine Idee:

  • Sehen Sie sich an, wie viele Etiketten Sie durchschnittlich für jede Probe haben
  • Sehen Sie sich die Vereinbarung zwischen Annotatoren an, falls verfügbar (falls nicht, versuchen Sie selbst zu sehen, welche Genauigkeit der Teilmenge erhalten wird, wenn Sie der Klassifikator sind).
  • Überlege, ob das Thema gut definiert ist
  • Sehen Sie sich an, wie viele Muster Sie für jedes Etikett haben

Sie können auch die Hamming-Punktzahl berechnen, um festzustellen, ob Ihr Klassifikator ahnungslos oder anständig gut ist, aber Probleme bei der korrekten Vorhersage aller Bezeichnungen haben. Siehe unten, um die Hamming-Punktzahl zu berechnen.

Soweit ich weiß, kann ich scikit.metrics nicht mit OneVsRestClassifier verwenden. Wie kann ich also einige Metriken (F1, Präzision, Rückruf usw.) abrufen, um herauszufinden, was nicht stimmt?

Siehe Berechnen der Genauigkeit / des Rückrufs für die Klassifizierung mit mehreren Klassen und mehreren Etiketten. . Ich habe vergessen , ob sklearn es unterstützt, ich erinnere es einige Einschränkungen hatte, zB sklearn nicht Multi-Label für Verwirrung Matrix unterstützt . Das wäre eine gute Idee, um diese Zahlen in der Tat zu sehen.


Hamming-Punktzahl :

In einer Multilabel Klassifizierung Einstellung sklearn.metrics.accuracy_scoreberechnet nur die Teilmenge Genauigkeit (3) : dh die für eine Stichprobe vorhergesagte Menge von Etiketten muss genau mit der entsprechenden Menge von Etiketten in y_true übereinstimmen.

Diese Art der Genauigkeitsberechnung wird manchmal, vielleicht weniger eindeutig, als genaues Übereinstimmungsverhältnis (1) bezeichnet:

Bildbeschreibung hier eingeben

Eine andere typische Methode zur Berechnung der Genauigkeit ist in (1) und (2) definiert und wird weniger eindeutig als Hamming-Punktzahl (4) (da sie in engem Zusammenhang mit dem Hamming-Verlust steht) oder kennzeichnungsbasierte Genauigkeit bezeichnet . Es wird wie folgt berechnet:

Bildbeschreibung hier eingeben

Hier ist eine Python-Methode, um die Hamming-Punktzahl zu berechnen:

# 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))) 

Ausgänge:

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

(1) Sorower, Mohammad S. " Eine Literaturübersicht über Algorithmen für Multi-Label-Lernen. " Oregon State University, Corvallis (2010).

(2) Tsoumakas, Grigorios und Ioannis Katakis. " Multi-Label-Klassifizierung: Ein Überblick. " Fakultät für Informatik, Aristoteles-Universität von Thessaloniki, Griechenland (2006).

(3) Ghamrawi, Nadia und Andrew McCallum. " Collective Multi-Label-Klassifizierung ". Vorträge der 14. internationalen ACM-Konferenz zu Informations- und Wissensmanagement. ACM, 2005.

(4) Godbole, Shantanu und Sunita Sarawagi. " Diskriminierende Methoden für die mehrfach gekennzeichnete Klassifizierung. " Fortschritte bei Knowledge Discovery und Data Mining. Springer Berlin Heidelberg, 2004. 22-30.

Franck Dernoncourt
quelle
Tolle Antwort, es hat mich nur besser gemacht :) Ich werde es gründlicher lesen, Hamming-Partitur ausprobieren und mich bei Ihnen melden!
Möbius
Um ehrlich zu sein, ist mir nicht ganz klar, wie genau die Teilmengengenauigkeit (Exact Match Ratio) ist. Könnten Sie bitte etwas mehr erklären? Es scheint, dass im Fall von Mehrfachklassen dies mit dem Rückruf identisch ist.
Poete Maudit
Die hamming_scoreFunktion Fehler auf Keras: <ipython-input-34-16066d66dfdd> in Hamming_score (y_true, y_pred, normalize, sample_weight) 60 '' '61 acc_list = [] ---> 62 für i in range (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: index zurückgegeben non-int (Typ NoneType )
rjurney
0

Reicht der Wert von 0.29 nicht aus? Wie sieht Ihre Verwirrungsmatrix aus? Gibt es Themen, die sich nicht trennen lassen, wenn man sich nur den Wortinhalt ansieht?

Versuchen Sie andernfalls, Ihr Problem umzukehren: Hypothese, dass die niedrigen Werte tatsächlich das Beste sind, was Ihr Klassifikator für Ihre Daten tun kann. Das würde bedeuten, dass Ihre Dokumente mit diesem Ansatz nicht klassifizierbar sind.

Um diese Hypothese zu testen, benötigen Sie eine Reihe von Testdokumenten mit bekannten Bag-of-Word-Merkmalen (die Sie selbst erstellen). Sie sollten 100% Punkte bekommen.

Wenn Sie dies nicht tun, haben Sie einen Fehler. Andernfalls benötigen Sie einen anderen Ansatz zur Klassifizierung Ihrer Dokumente. Fragen Sie sich: Wie unterscheiden sich die Dokumente aus den verschiedenen Klassen voneinander? Muss ich mir andere Funktionen meiner Dokumente usw. ansehen?

Ytsen de Boer
quelle
Abgesehen von den Zahlen spüre ich, dass 0,29 niedrig ist. Ich verwende das trainierte Modell, um Themen in Dokumenten vorherzusagen, die ich bereits im Training verwendet habe, um den Klassifikator manuell zu testen. Ich konnte nicht mindestens die gleiche Anzahl von Themen erhalten, die der Benutzer manuell in das Dokument eingegeben hat. Normalerweise bekomme ich nur einen Teil davon. Auch in Bezug auf die Frage der Verwirrungsmatrix glaube ich nicht, dass ich mit den scikit.metrics eine Verwirrungsmatrix für den OneVsRestClassifier erhalten kann ... Ich werde es jedoch überprüfen
mobius