Metrik klasifikasi multilabel pada scikit

19

Saya mencoba membangun multi-label classifier untuk menetapkan topik ke dokumen yang ada menggunakan scikit

Saya sedang memproses dokumen saya melewati mereka melalui TfidfVectorizerlabel melalui MultiLabelBinarizerdan membuat OneVsRestClassifierdengan SGDClassifiersebagai penaksir.

Namun ketika menguji classifier saya, saya hanya mendapatkan skor hingga 0,29 yang dari apa yang saya baca cukup rendah untuk masalah yang sama. Saya mencoba beberapa opsi pada TfidfVectorizer seperti stopwords, unigrams, stemming dan sepertinya tidak ada yang mengubah hasil sebanyak itu.

Saya juga terbiasa GridSearchCVmendapatkan parameter terbaik untuk estimator saya dan saat ini saya kehabisan ide tentang apa yang harus dicoba selanjutnya.

Pada saat yang sama, dari apa yang saya pahami saya tidak dapat gunakan scikit.metricsdengan OneVsRestClassifierjadi bagaimana saya bisa mendapatkan beberapa metrik (F1, Precision, Recall dll) sehingga untuk mencari tahu apa yang salah?

Mungkinkah ada masalah dengan korpus data saya?

Update: Saya juga mencoba menggunakan CountVectorizerdan HashingVectorizerdan pipelining mereka untuk TfidfTransformertetapi hasilnya sama. Jadi saya menduga bahwa pendekatan kata-kata melakukan yang terbaik dalam domain tokenisasi dan sisanya terserah pada pengklasifikasi ...

Mobius
sumber
1
Apa yang dimaksud dengan 0,29? Ketepatan? Sesuatu yang lain
Sycorax berkata Reinstate Monica
@GeneralAbrial Menurut dokumentasi scikit berjalan scorepada classifier,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
Itukah yang kamu lakukan? Sama sekali tidak jelas dari pertanyaan Anda bahwa inilah masalahnya, jadi ini adalah pertanyaan yang masuk akal.
Sycorax mengatakan Reinstate Monica
@GeneralAbrial Ya ini yang saya lakukan. Maaf atas kebingungannya, saya mencoba menyimpan pertanyaan dalam mode yang lebih teoretis daripada yang dikembangkan.
mobius
Bisakah Anda menambahkan kode Anda di sini? Khususnya apakah Anda menggunakan sample_weight = "seimbang" untuk SGD? Tetapi mungkin ada hal-hal lain yang perlu diperhatikan setelah kami melihat kode Anda.
Diego

Jawaban:

21

Akurasi himpunan bagian memang metrik yang keras. Untuk memahami seberapa baik atau buruknya 0,29, beberapa ide:

  • lihat berapa banyak label yang Anda miliki rata-rata untuk setiap sampel
  • lihat perjanjian antar-annotator, jika tersedia (jika tidak, coba sendiri untuk melihat keakuratan subset apa yang diperoleh saat Anda menjadi pengklasifikasi)
  • pikirkan apakah topiknya didefinisikan dengan baik
  • lihat berapa banyak sampel yang Anda miliki untuk setiap label

Anda juga mungkin ingin menghitung skor hamming, untuk melihat apakah classifier Anda tidak mengerti, atau malah bagus tetapi memiliki masalah dalam memprediksi semua label dengan benar. Lihat di bawah untuk menghitung skor hamming.

Pada saat yang sama, dari apa yang saya pahami saya tidak bisa menggunakan scikit.metrics dengan OneVsRestClassifier jadi bagaimana saya bisa mendapatkan beberapa metrik (F1, Precision, Recall dll) untuk mengetahui apa yang salah?

Lihat Bagaimana cara menghitung presisi / recall untuk klasifikasi multiclass-multilabel? . Saya lupa apakah sklearn mendukungnya, saya ingat itu memiliki beberapa keterbatasan, mis. Sklearn tidak mendukung multi-label untuk matriks kebingungan . Itu akan menjadi ide yang bagus untuk melihat angka-angka ini.


Skor Hamming :

Dalam pengaturan klasifikasi multilabel , sklearn.metrics.accuracy_scorehanya menghitung akurasi subset (3): yaitu himpunan label yang diprediksi untuk sampel harus sama persis dengan himpunan label yang sesuai di y_true.

Cara penghitungan akurasi ini kadang-kadang dinamai, mungkin kurang ambigu, rasio kecocokan yang tepat (1):

masukkan deskripsi gambar di sini

Cara khas lain untuk menghitung akurasi didefinisikan dalam (1) dan (2), dan kurang ambigu disebut sebagai skor Hamming (4) (karena terkait erat dengan hilangnya Hamming), atau akurasi berbasis label . Itu dihitung sebagai berikut:

masukkan deskripsi gambar di sini

Berikut adalah metode python untuk menghitung skor Hamming:

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

Output:

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

(1) Sorower, Mohammad S. " Sebuah survei literatur tentang algoritma untuk pembelajaran multi-label. " Oregon State University, Corvallis (2010).

(2) Tsoumakas, Grigorios, dan Ioannis Katakis. " Klasifikasi multi-label: Tinjauan. " Departemen Informatika, Aristoteles University of Thessaloniki, Yunani (2006).

(3) Ghamrawi, Nadia, dan Andrew McCallum. " Klasifikasi multi-label kolektif. " Prosiding konferensi internasional ACM ke-14 tentang Informasi dan manajemen pengetahuan. ACM, 2005.

(4) Godbole, Shantanu, dan Sunita Sarawagi. " Metode diskriminatif untuk klasifikasi multi-label. " Kemajuan dalam Penemuan Pengetahuan dan Penambangan Data. Springer Berlin Heidelberg, 2004. 22-30.

Franck Dernoncourt
sumber
jawaban yang bagus, itu hanya membuat saya lebih baik :) Saya akan membacanya lebih menyeluruh, coba skor Hamming dan kembali kepada Anda!
mobius
Sejujurnya, tidak sepenuhnya jelas bagi saya apa sebenarnya akurasi subset (Rasio Pencocokan Tepat). Bisakah Anda jelaskan sedikit lebih banyak? Tampaknya dalam kasus multiclass ini identik dengan recall.
Poete Maudit
The hamming_scorekesalahan fungsi pada Keras: <-ipython input-34-16066d66dfdd> di hamming_score (y_true, y_pred, menormalkan, sample_weight) 60 ''' 61 acc_list = [] ---> 62 untuk i dalam rentang (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 dikembalikan non-int (tipe NoneType )
rjurney
0

Apakah skor 0,29 tidak cukup? Seperti apa matriks kebingungan Anda? Apakah ada beberapa topik yang tidak dapat dipisahkan mungkin hanya dengan melihat isi kata?

Jika tidak, cobalah untuk mengubah masalah Anda: Hipotesis bahwa skor yang rendah sebenarnya adalah yang terbaik yang dapat dilakukan oleh penggolong Anda pada data Anda. Itu berarti bahwa dokumen Anda tidak dapat diklasifikasikan menggunakan pendekatan ini.

Untuk menguji hipotesis ini, Anda memerlukan seperangkat dokumen uji dengan karakteristik kata-kata yang diketahui (yang Anda buat sendiri). Anda harus mendapatkan skor 100%.

Jika tidak, maka Anda memiliki bug. Jika tidak, Anda memerlukan pendekatan berbeda untuk mengklasifikasikan dokumen Anda. Tanyakan kepada diri Anda: bagaimana perbedaan dokumen dari kelas yang berbeda satu sama lain? Apakah saya perlu melihat fitur lain dari dokumen saya, dll.

Ytsen de Boer
sumber
Terlepas dari angka-angka saya merasakan bahwa 0,29 rendah. Saya menggunakan model yang terlatih untuk memprediksi topik pada dokumen yang sudah saya gunakan dalam pelatihan untuk menguji secara manual classifier. Saya belum bisa mendapatkan setidaknya sejumlah topik yang sama dengan yang dimasukkan pengguna secara manual pada dokumen. Saya biasanya hanya mendapatkan sebagian dari mereka. Juga sehubungan dengan pertanyaan matriks kebingungan, saya tidak berpikir saya bisa mendapatkan matriks kebingungan pada OneVsRestClassifier menggunakan scikit.metrics ... Saya akan memeriksanya meskipun
mobius