Scikit'te çok etiketli sınıflandırma metrikleri


19

Scikit kullanarak mevcut belgelere konu atamak için çok etiketli bir sınıflandırıcı oluşturmaya çalışıyorum

Belgelerimi TfidfVectorizeretiketlerden geçirerek işliyorum ve tahmincisi olarak MultiLabelBinarizera OneVsRestClassifierile oluşturdum SGDClassifier.

Ancak sınıflandırıcımı test ederken, sadece okuduğumdan benzer problemler için oldukça düşük olan .29'a kadar puan alıyorum. TfidfVectorizer üzerinde stopwords, unigrams, stemming gibi çok sayıda seçenek denedim ve hiçbir şey sonucu bu kadar değiştirecek gibi görünmüyor.

Ayrıca GridSearchCVtahmin edicim için en iyi parametreleri alırdım ve şu anda bir sonraki adımda ne yapacağım konusunda fikirlerim yok.

Aynı zamanda, gelen ben kullanamıyorum anladığımız scikit.metricsile OneVsRestClassifieröylesine nasıl bu kadar hata ne olduğunu rakama gibi bazı ölçümleri (F1, Hassas, vb Recall) alabilirim?

Veri topluluğumla ilgili bir sorun olabilir mi?

Güncelleme: Ben de kullanarak denedim CountVectorizerve HashingVectorizerve bunları borulama özelliğini TfidfTransformerancak sonuçlar benzerdir. Bu yüzden torbalar kelimesi yaklaşımının tokenizasyon alanında en iyisi olduğunu ve geri kalanının sınıflandırıcıya kadar olduğunu tahmin ediyorum ...


1
0.29 Ölçme Nedir? Doğruluk? Başka bir şey?
Sycorax, Reinstate Monica'nın

@GeneralAbrial scikit belgelerine göre çalışan scoresınıflandırıcı üzerinde,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

Yaptığın bu mu? Sorunuzdan durumun bu olduğu açık değil, bu yüzden oldukça makul bir soru.
Sycorax, Reinstate Monica'ya

@GeneralAbrial Evet, bunu yaptım. Karışıklık için özür dilerim, soruyu bir gelişme değil, daha teorik bir modda tutmaya çalışıyordum.
mobius

Kodunuzu buraya ekler misiniz? Özellikle SGD için sample_weight = "balanced" kullanıyor musunuz? Ancak, kodunuzu gördüğümüzde not edilmesi gereken başka şeyler olabilir.
Diego

Yanıtlar:


21

Altküme doğruluğu gerçekten de sert bir metriktir. 0.29'un ne kadar iyi veya kötü olduğunu anlamak için bazı fikirler:

  • her örnek için ortalama kaç etiketinizin olduğuna bakın
  • eğer varsa ek açıklamalar arası sözleşmeye bakın (eğer değilse, sınıflandırıcı olduğunuzda hangi alt kümenin doğruluğunu elde ettiğinizi görün)
  • konunun iyi tanımlanıp tanımlanmadığını düşünün
  • her bir etiket için kaç tane örneğiniz olduğuna bakın

Ayrıca, çekiçleme puanınızı hesaplamak, sınıflandırıcınızın clueless olup olmadığını veya bunun yerine terbiyeli olarak iyi olup olmadığını görmek, ancak tüm etiketleri doğru şekilde tahmin etmekte sorun olup olmadığını görmek isteyebilirsiniz. Hamur puanını hesaplamak için aşağıya bakın.

Aynı zamanda, anladığım kadarıyla, scikit.metrics'i OneVsRestClassifier ile kullanamıyorum, böylece neyin yanlış olduğunu anlamak için bazı metrikleri (F1, Hassasiyet, Geri Çağırma vb.) Nasıl alabilirim?

Bkz . Çok sınıflı çok etiketli sınıflandırma için hassasiyet / geri çağırma nasıl hesaplanır? . Sklearn'ün destekleyip desteklemediğini unuttum, bazı sınırlamaları olduğunu hatırlıyorum, örneğin sklearn, karışıklık matrisi için çoklu etiketi desteklemiyor . Bu sayıları görmek gerçekten iyi bir fikir olabilir.


Hamming puanı :

Çok etiketli bir sınıflandırma ayarında, sklearn.metrics.accuracy_scoreyalnızca alt kümenin doğruluğunu (3) hesaplar : yani bir örnek için tahmin edilen etiket kümesi y_true içindeki karşılık gelen etiket kümesiyle tam olarak eşleşmelidir.

Doğruluğu hesaplamanın bu yolu, belki de daha az belirsiz bir şekilde kesin eşleşme oranı olarak adlandırılır (1):

resim açıklamasını buraya girin

Doğruluğu hesaplamanın bir başka tipik yolu (1) ve (2) 'de tanımlanmıştır ve daha az belirsiz bir şekilde Hamming skoru (4) olarak adlandırılmıştır (Hamming kaybıyla yakından ilişkili olduğu için) veya etiket tabanlı doğruluk ). Aşağıdaki gibi hesaplanır:

resim açıklamasını buraya girin

Hamming puanını hesaplamak için bir python yöntemi:

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

Çıktılar:

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

(1) Sorower, Mohammad S. " Çok etiketli öğrenme algoritmaları üzerine literatür taraması. " Oregon State University, Corvallis (2010).

(2) Tsoumakas, Grigorios ve Ioannis Katakis. " Çok etiketli sınıflandırma: Genel bakış. " Enformatik Bölümü, Selanik Aristo Üniversitesi, Yunanistan (2006).

(3) Ghamrawi, Nadia ve Andrew McCallum. “ Toplu çok etiketli sınıflandırma. ” 14. ACM Uluslararası Bilgi ve Bilgi Yönetimi Konferansı Bildirileri. ACM, 2005.

(4) Godbole, Shantanu ve Sunita Sarawagi. " Çok etiketli sınıflandırma için ayrımcı yöntemler. " Bilgi Keşfi ve Veri Madenciliğinde Gelişmeler. Springer Berlin Heidelberg, 2004. 22-30.


harika cevap, sadece beni daha iyi yaptı :) Daha iyice okuyacağım, Hamming skorunu deneyin ve size geri döneceğim!
mobius

Dürüst olmak gerekirse, alt kümenin doğruluğunun (Tam Eşleşme Oranı) tam olarak ne olduğu tam olarak açık değil. Biraz daha açıklayabilir misiniz? Çok sınıflı olması durumunda bu hatırlamakla aynı görünüyor.
Poete Maudit

hamming_scoreKeras üzerinde işlev hataları: <ipython girişli 34-16066d66dfdd> hamming_score içinde (y_true, y_pred, normalize, sample_weight), 60 '' 61 acc_list = [] ---> aralığında i 62 (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: dizin döndürülmedi int (tip NoneType )
rjurney

0

0.29 puanı yeterli değil mi? Karışıklık matrisiniz neye benziyor? Belki sadece kelime içeriğine bakarak ayrılamayan bazı konular var mı?

Aksi takdirde, sorununuzu tersine çevirmeye çalışın: Düşük puanların aslında sınıflandırıcınızın verilerinizde yapabileceği en iyi şey olduğunu varsayın. Bu, belgelerinizin bu yaklaşım kullanılarak sınıflandırılamayacağı anlamına gelir.

Bu hipotezi test etmek için, bilinen kelime çantası özelliklerine (kendi oluşturduğunuz) sahip bir dizi test belgesine ihtiyacınız vardır. % 100 puan almalısınız.

Eğer yapmazsanız, o zaman bir hata var. Aksi takdirde, belgelerinizi sınıflandırmak için farklı bir yaklaşıma ihtiyacınız vardır. Kendinize sorun: Farklı sınıflardaki belgeler birbirinden nasıl farklı? Belgelerimin diğer özelliklerine vb. Bakmam gerekiyor mu?


Sayıların dışında 0.29'un düşük olduğunu düşünüyorum. Sınıflandırıcıyı manuel olarak test etmek için eğitimde daha önce kullandığım belgelerdeki konuları tahmin etmek için eğitimli modeli kullanıyorum. Kullanıcının belgeye manuel olarak girdiği en az aynı sayıda konuyu alamadım. Genellikle sadece bir altkümesi alıyorum. Ayrıca karışıklık matris sorusu açısından, ben scikit.metrics kullanarak OneVsRestClassifier bir karışıklık matrisi alabilirsiniz sanmıyorum ... Ben gerçi bunu kontrol edecek
Mobius
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.