Wielopłaszczyznowe wskaźniki klasyfikacji w programie scikit

19

Usiłuję zbudować klasyfikator z wieloma etykietami, aby przypisywać tematy do istniejących dokumentów za pomocą programu scikit

Ja przetwarzanie moich dokumentów przepuszczanie ich przez TfidfVectorizeretykiet poprzez podjęcie działań MultiLabelBinarizeri stworzył OneVsRestClassifierze związkiem SGDClassifierjako estymatora.

Jednak podczas testowania mojego klasyfikatora otrzymuję tylko wyniki do 0,29, które z tego, co przeczytałem, są dość niskie w przypadku podobnych problemów. Wypróbowałem wiele opcji w TfidfVectorizer, takich jak stopery, unigramy, wywodzenie i nic nie wydaje się tak bardzo zmieniać wyniku.

Kiedyś GridSearchCVuzyskiwałem najlepsze parametry mojego estymatora i obecnie nie mam pomysłów, co dalej.

Jednocześnie, z tego co rozumiem, nie mogę korzystać scikit.metricsz OneVsRestClassifiertak jak mogę dostać jakieś metryki (F1, precyzja, Recall etc), tak aby dowiedzieć się, co jest nie tak?

Czy to może być problem z moim korpusem danych?

Aktualizacja: Ja również spróbował wykorzystać CountVectorizeri HashingVectorizeri szybkiego odbierania im TfidfTransformer, ale wyniki są podobne. Zgaduję więc, że metoda work-of-words robi najlepiej w dziedzinie tokenizacji, a reszta należy do klasyfikatora ...

mobius
źródło
1
Co mierzy 0,29? Precyzja? Coś innego?
Sycorax mówi Przywróć Monikę
@GeneralAbrial Według dokumentacji scikit działającej scorena klasyfikatorze,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
Czy to właśnie zrobiłeś? Z twojego pytania wcale nie jest jasne, więc jest to całkowicie rozsądne pytanie.
Sycorax mówi Przywróć Monikę
@GeneralAbrial Tak, właśnie to zrobiłem. Przepraszam za zamieszanie, starałem się utrzymać to pytanie w bardziej teoretycznym trybie niż w trybie rozwojowym.
mobius
Czy możesz tutaj dodać swój kod? W szczególności, czy używasz sample_weight = "balance" dla SGD? Ale kiedy zobaczymy Twój kod, możesz zauważyć inne rzeczy.
Diego,

Odpowiedzi:

21

Dokładność podzestawu jest rzeczywiście trudną miarą. Aby zorientować się, jak dobry lub zły jest 0,29, jakiś pomysł:

  • sprawdź, ile masz etykiet dla każdej próbki
  • spójrz na umowę między adnotatorami, jeśli jest dostępna (jeśli nie, spróbuj się przekonać, jaka dokładność podzbioru została uzyskana, gdy jesteś klasyfikatorem)
  • zastanów się, czy temat jest dobrze zdefiniowany
  • sprawdź, ile masz próbek dla każdej etykiety

Możesz także obliczyć wynik Hamminga, aby sprawdzić, czy twój klasyfikator nie ma pojęcia, czy jest całkiem dobry, ale ma problem z przewidywaniem wszystkich etykiet poprawnie. Zobacz poniżej, aby obliczyć wynik Hamminga.

Jednocześnie z tego, co rozumiem, nie mogę używać scikit.metrics z OneVsRestClassifier, więc w jaki sposób mogę uzyskać niektóre metryki (F1, Precision, Recall itp.), Aby dowiedzieć się, co jest nie tak?

Zobacz Jak obliczyć precyzję / przywołanie dla klasyfikacji wieloklasowej-wielowarstwowej? . Zapomniałem, czy sklearn je obsługuje, pamiętam, że miał pewne ograniczenia, np. Sklearn nie obsługuje wielu etykiet dla macierzy pomieszania . Byłoby dobrym pomysłem, aby zobaczyć te liczby.


Wynik Hamminga :

W ustawieniach klasyfikacji wielowarstwowejsklearn.metrics.accuracy_score oblicza tylko dokładność podzestawu (3): tj. Zestaw etykiet przewidziany dla próbki musi dokładnie odpowiadać odpowiadającemu zestawowi etykiet w y_true.

Ten sposób obliczania dokładności nazywa się czasem, być może mniej jednoznacznie, dokładnym współczynnikiem dopasowania (1):

wprowadź opis zdjęcia tutaj

Innym typowym sposobem obliczenia dokładności jest zdefiniowany w (1) i (2), a mniej jednoznacznie określany jako wynik Hamminga (4) (ponieważ jest ściśle związany ze stratą Hamminga) lub dokładnością opartą na etykietach ). Oblicza się go w następujący sposób:

wprowadź opis zdjęcia tutaj

Oto metoda pythonowa do obliczenia wyniku Hamminga:

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

Wyjścia:

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

(1) Sorower, Mohammad S. „ Badanie literatury na temat algorytmów uczenia się wielu marek. ” Oregon State University, Corvallis (2010).

(2) Tsoumakas, Grigorios i Ioannis Katakis. „ Klasyfikacja wielu marek: przegląd. ” Departament Informatyki, Aristotle University of Thessaloniki, Grecja (2006).

(3) Ghamrawi, Nadia i Andrew McCallum. „ Zbiorowa klasyfikacja wielu marek. ” Materiały z 14. międzynarodowej konferencji ACM na temat zarządzania informacjami i wiedzą. ACM, 2005.

(4) Godbole, Shantanu i Sunita Sarawagi. „ Dyskryminacyjne metody klasyfikacji wielu marek. Postępy w odkrywaniu wiedzy i eksploracji danych. Springer Berlin Heidelberg, 2004. 22-30.

Franck Dernoncourt
źródło
świetna odpowiedź, po prostu mnie poprawiła :) Przeczytam ją dokładniej, wypróbuj partyturę Hamminga i wróć do ciebie!
mobius
Szczerze mówiąc, nie jest dla mnie całkowicie jasne, jaka dokładnie jest dokładność podzbioru (Dokładny współczynnik dopasowania). Czy mógłbyś wyjaśnić coś więcej? Wydaje się, że w przypadku wieloklasowości jest to identyczne z przypomnieniem.
Poete Maudit
Te hamming_scorebłędy funkcyjne odchodzący na Keras <ipython Input 34-16066d66dfdd> w hamming_score (y_true, y_pred, normalizacja, sample_weight) 60 ''”, 61 acc_list = [] ---> 62 do i w zakresie (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: indeks zwrócił non-int (typ NoneType )
rjurney
0

Czy wynik 0,29 to za mało? Jak wygląda twoja macierz dezorientacji? Czy są jakieś tematy, których nie można oddzielić, patrząc tylko na treść słowa?

W przeciwnym razie postaraj się odwrócić problem: postaw hipotezę, że niskie wyniki są najlepszymi wynikami klasyfikatora w danych. Oznaczałoby to, że twoje dokumenty nie podlegają klasyfikacji przy użyciu tego podejścia.

Aby przetestować tę hipotezę, potrzebujesz zestawu dokumentów testowych o znanej charakterystyce work-of-word (które sam tworzysz). Powinieneś uzyskać 100% wyników.

Jeśli nie, to masz błąd. W przeciwnym razie potrzebujesz innego podejścia do klasyfikacji dokumentów. Zadaj sobie pytanie: czym różnią się dokumenty z różnych klas? Czy muszę spojrzeć na inne funkcje moich dokumentów itp.

Ytsen de Boer
źródło
Poza liczbami wyczuwam, że 0,29 jest niski. Używam wyszkolonego modelu do przewidywania tematów dokumentów, które już wykorzystałem w szkoleniu do ręcznego testowania klasyfikatora. Nie udało mi się uzyskać co najmniej takiej samej liczby tematów, którą użytkownik wpisał ręcznie w dokumencie. Zwykle otrzymuję tylko ich podzbiór. Również w odniesieniu do pytania o macierz nieporozumień, nie sądzę, że mogę uzyskać macierz nieporozumień na OneVsRestClassifier za pomocą scikit.metrics ... Sprawdzę to jednak
mobius