Scikit ile çok sınıflı durum için hassasiyet, geri çağırma, doğruluk ve f1-skoru nasıl hesaplanır?


109

Bir duyarlılık analizi problemi üzerinde çalışıyorum, veriler şöyle görünüyor:

label instances
    5    1190
    4     838
    3     239
    1     204
    2     127

Yani verilerim 1190 instancesile etiketlendiğinden beri dengesiz 5. Sınıflandırma için Im scikit en kullanarak SVC . Sorun şu ki, çok sınıflı durum için kesinlik, geri çağırma, doğruluk ve f1 puanını doğru bir şekilde hesaplamak için verilerimi doğru şekilde nasıl dengeleyeceğimi bilmiyorum. Bu yüzden aşağıdaki yaklaşımları denedim:

İlk:

    wclf = SVC(kernel='linear', C= 1, class_weight={1: 10})
    wclf.fit(X, y)
    weighted_prediction = wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, weighted_prediction)
print 'F1 score:', f1_score(y_test, weighted_prediction,average='weighted')
print 'Recall:', recall_score(y_test, weighted_prediction,
                              average='weighted')
print 'Precision:', precision_score(y_test, weighted_prediction,
                                    average='weighted')
print '\n clasification report:\n', classification_report(y_test, weighted_prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, weighted_prediction)

İkinci:

auto_wclf = SVC(kernel='linear', C= 1, class_weight='auto')
auto_wclf.fit(X, y)
auto_weighted_prediction = auto_wclf.predict(X_test)

print 'Accuracy:', accuracy_score(y_test, auto_weighted_prediction)

print 'F1 score:', f1_score(y_test, auto_weighted_prediction,
                            average='weighted')

print 'Recall:', recall_score(y_test, auto_weighted_prediction,
                              average='weighted')

print 'Precision:', precision_score(y_test, auto_weighted_prediction,
                                    average='weighted')

print '\n clasification report:\n', classification_report(y_test,auto_weighted_prediction)

print '\n confussion matrix:\n',confusion_matrix(y_test, auto_weighted_prediction)

Üçüncü:

clf = SVC(kernel='linear', C= 1)
clf.fit(X, y)
prediction = clf.predict(X_test)


from sklearn.metrics import precision_score, \
    recall_score, confusion_matrix, classification_report, \
    accuracy_score, f1_score

print 'Accuracy:', accuracy_score(y_test, prediction)
print 'F1 score:', f1_score(y_test, prediction)
print 'Recall:', recall_score(y_test, prediction)
print 'Precision:', precision_score(y_test, prediction)
print '\n clasification report:\n', classification_report(y_test,prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, prediction)


F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1082: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
  sample_weight=sample_weight)
 0.930416613529

Ancak şu şekilde uyarılar alıyorum:

/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172:
DeprecationWarning: The default `weighted` averaging is deprecated,
and from version 0.18, use of precision, recall or F-score with 
multiclass or multilabel data or pos_label=None will result in an 
exception. Please set an explicit value for `average`, one of (None, 
'micro', 'macro', 'weighted', 'samples'). In cross validation use, for 
instance, scoring="f1_weighted" instead of scoring="f1"

Sınıflandırıcının ölçümlerini doğru şekilde hesaplamak için dengesiz verilerimle nasıl doğru bir şekilde başa çıkabilirim?


Öyleyse neden averageüçüncü durumda parametre eklemiyorsunuz?
yangjie

1
@yangjie bilmiyorum. Sadece dokümantasyonu kontrol ediyorum ama dengesiz veriler için ölçümleri doğru şekilde nasıl kullanacağımı anlamıyorum. Daha geniş bir açıklama ve bir örnek verebilir misiniz? Teşekkürler!
new_with_python

Yanıtlar:


164

Bence hangi ağırlıkların ne için kullanıldığı konusunda çok fazla kafa karışıklığı var. Sizi neyin rahatsız ettiğini tam olarak bildiğimden emin değilim, bu yüzden farklı konuları ele alacağım, bana katlanın;).

Sınıf ağırlıkları

class_weightParametreden alınan ağırlıklar sınıflandırıcıyı eğitmek için kullanılır . Kullandığınız ölçümlerin hiçbirinin hesaplanmasında kullanılmazlar : farklı sınıf ağırlıklarında, sınıflandırıcı farklı olduğu için sayılar farklı olacaktır.

Temel olarak her scikit-learn sınıflandırıcısında, sınıf ağırlıkları modelinize bir sınıfın ne kadar önemli olduğunu anlatmak için kullanılır. Bu, eğitim sırasında sınıflandırıcının yüksek ağırlıklara sahip sınıfları uygun şekilde sınıflandırmak için ekstra çaba göstereceği anlamına gelir.
Bunu nasıl yaptıkları algoritmaya özgüdür. SVC için nasıl çalıştığı hakkında ayrıntılar istiyorsanız ve belge size mantıklı gelmiyorsa, bundan bahsetmekten çekinmeyin.

Ölçümler

Bir sınıflandırıcıya sahip olduğunuzda, ne kadar iyi performans gösterdiğini bilmek istersiniz. Burada sözü edilen metrik kullanabilirsiniz: accuracy, recall_score, f1_score...

Genellikle sınıf dağılımı dengesiz olduğunda, yalnızca en sık kullanılan sınıfı tahmin eden modellere yüksek puanlar verdiği için doğruluk zayıf bir seçim olarak kabul edilir.

Tüm bu ölçütleri detaylandırmayacağım, ancak accuracysınıf düzeyinde doğal olarak uygulandıklarına dikkat edin : printbir sınıflandırma raporunda da görebileceğiniz gibi, bunlar her sınıf için tanımlanmıştır. Hangi sınıfın olumlu olduğunu tanımlamayı gerektiren true positivesveya gibi kavramlara güvenirler .false negative

             precision    recall  f1-score   support

          0       0.65      1.00      0.79        17
          1       0.57      0.75      0.65        16
          2       0.33      0.06      0.10        17
avg / total       0.52      0.60      0.51        50

Uyarı

F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The 
default `weighted` averaging is deprecated, and from version 0.18, 
use of precision, recall or F-score with multiclass or multilabel data  
or pos_label=None will result in an exception. Please set an explicit 
value for `average`, one of (None, 'micro', 'macro', 'weighted', 
'samples'). In cross validation use, for instance, 
scoring="f1_weighted" instead of scoring="f1".

Bu uyarıyı alırsınız çünkü f1 skorunu, hatırlamayı ve hassasiyeti nasıl hesaplanacaklarını tanımlamadan kullanıyorsunuz! Soru yeniden ifade edilebilir: Yukarıdaki sınıflandırma raporundan, f1-skoru için bir genel sayıyı nasıl çıkarırsınız? Yapabilirdiniz:

  1. Her sınıf için f1 puanının ortalamasını alın: avg / totalyukarıdaki sonuç budur. Makro ortalama olarak da adlandırılır .
  2. Gerçek pozitif / yanlış negatiflerin genel sayımını kullanarak f1-skorunu hesaplayın (her sınıf için gerçek pozitif / yanlış negatiflerin sayısını toplarsınız). Aka mikro ortalama.
  3. F1 puanının ağırlıklı ortalamasını hesaplayın. 'weighted'Scikit-learn'de kullanmak , f1 puanını sınıfın desteğiyle tartacaktır: Bir sınıf ne kadar çok öğeye sahipse, hesaplamada bu sınıf için f1 puanı o kadar önemlidir.

Bunlar scikit-learn'deki seçeneklerden 3'ü, bir tane seçmeniz gerektiğini belirten uyarı var . Bu nedenle average, puan yöntemi için bir bağımsız değişken belirlemeniz gerekir .

Hangisini seçeceğiniz, sınıflandırıcının performansını nasıl ölçmek istediğinize bağlıdır: örneğin, makro ortalama, sınıf dengesizliğini hesaba katmaz ve 1. sınıfın f1 puanı, sınıfın f1 puanı kadar önemli olacaktır. 5. Ancak ağırlıklı ortalama kullanırsanız, 5. sınıf için daha fazla önem kazanırsınız.

Bu metriklerdeki tüm argüman özellikleri şu anda scikit-learn'de süper net değil, belgelere göre 0.18 sürümünde daha iyi olacak. Bazı bariz olmayan standart davranışları kaldırıyorlar ve geliştiricilerin bunu fark etmesi için uyarılar yayınlıyorlar.

Hesaplama puanları

Bahsetmek istediğim son şey (farkındaysanız atlamaktan çekinmeyin), puanların yalnızca sınıflandırıcının hiç görmediği veriler üzerinden hesaplandıklarında anlamlı olduğudur. . Sınıflandırıcıyı yerleştirmede kullanılan verilerden aldığınız herhangi bir puan tamamen alakasız olduğundan bu son derece önemlidir.

İşte bunu kullanarak yapmanın bir yolu StratifiedShuffleSplit, bu size etiket dağılımını koruyan (karıştırmadan sonra) verilerinizin rastgele bölünmesini sağlar.

from sklearn.datasets import make_classification
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, classification_report, confusion_matrix

# We use a utility to generate artificial classification data.
X, y = make_classification(n_samples=100, n_informative=10, n_classes=3)
sss = StratifiedShuffleSplit(y, n_iter=1, test_size=0.5, random_state=0)
for train_idx, test_idx in sss:
    X_train, X_test, y_train, y_test = X[train_idx], X[test_idx], y[train_idx], y[test_idx]
    svc.fit(X_train, y_train)
    y_pred = svc.predict(X_test)
    print(f1_score(y_test, y_pred, average="macro"))
    print(precision_score(y_test, y_pred, average="macro"))
    print(recall_score(y_test, y_pred, average="macro"))    

Bu yardımcı olur umarım.


Çok sınıflı bir sınıf için, bir sınıf ağırlığını nasıl belirlersiniz? Örneğin, class_weight={1:10}3 sınıfa sahip veriler için ne anlama gelir?
Aziz Javed

Etiket açısından doğruluk puanları almanın bir yolu var mı?
Ankur Sinha

Mikro'nun nasıl çalıştığını daha net açıklayabilir misiniz? Ayrıca ikili program hakkında hiçbir şeyden bahsetmiyorsunuz
mütevazi

Benim için katmanlı karıştırma sorunları yaratıyordu, bu yüzden gösterdiği gibi eğitim-test ayrımına geri döndüm ValueError: The least populated class in y has only 1 member, which is too few. The minimum number of labels for any class cannot be less than 2.. Tren testi bölümüyle iyi çalışıyor, ancak herhangi biri bana neden SSS ile bu hatayı alıyorum bana yardımcı olabilir mi? Teşekkürler.
Akash Kandpal

HI kodunuzu test ettim ancak şu hata mesajını aldım: C: \ Users \\ Anaconda3 \ lib \ site-packages \ sklearn \ metrics \ classroom.py: 976: DeprecationWarning: Sürüm 0.18'den itibaren, ikili giriş kullanılırken özel olarak ele alınmayacaktır ortalama hassasiyet / geri çağırma / F skoru. Yalnızca pozitif sınıf performansını bildirmek için lütfen ortalama = 'ikili' kullanın. 'pozitif sınıf performansı.',
DeprecationWarning

73

Burada çok detaylı cevaplar var ama doğru soruları cevapladığınızı sanmıyorum. Soruyu anladığım kadarıyla iki sorun var:

  1. Çok sınıflı bir problemi nasıl puanlarım?
  2. Dengesiz verilerle nasıl başa çıkırım?

1.

Scikit-learn'deki puanlama işlevlerinin çoğunu hem çok sınıflı problemlerde hem de tek sınıflı problemlerde kullanabilirsiniz. Ör .:

from sklearn.metrics import precision_recall_fscore_support as score

predicted = [1,2,3,4,5,1,2,1,1,4,5] 
y_test = [1,2,3,4,5,1,2,1,1,4,1]

precision, recall, fscore, support = score(y_test, predicted)

print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))

Bu şekilde, her sınıf için somut ve yorumlanabilir sayılar elde edersiniz.

| Label | Precision | Recall | FScore | Support |
|-------|-----------|--------|--------|---------|
| 1     | 94%       | 83%    | 0.88   | 204     |
| 2     | 71%       | 50%    | 0.54   | 127     |
| ...   | ...       | ...    | ...    | ...     |
| 4     | 80%       | 98%    | 0.89   | 838     |
| 5     | 93%       | 81%    | 0.91   | 1190    |

Sonra...

2.

... dengesiz verilerin bir sorun olup olmadığını anlayabilirsiniz. Daha az temsil edilen sınıfların (sınıf 1 ve 2) puanlaması, daha fazla eğitim örneği olan sınıflardan (sınıf 4 ve 5) daha düşükse, o zaman dengesiz verilerin aslında bir sorun olduğunu bilirsiniz ve buna göre hareket edebilirsiniz. bu konudaki diğer cevapların bazılarında açıklanmıştır. Bununla birlikte, tahmin etmek istediğiniz verilerde aynı sınıf dağılımı mevcutsa, dengesiz eğitim verileriniz verilerin iyi bir temsilcisidir ve bu nedenle dengesizlik iyi bir şeydir.


1
Harika gönderi ve iyi söylendi. Teşekkürler
Alvis

1
Hey sadece takip sorusu: etiketleri kullanarak nasıl yazdırdınız? precision_recall_fscore_support ? Etiketler sipariş üzerine mi yazdırılıyor?
BigD

@BigD Evet, en alttaki scikit-learn.org/stable/modules/generated/… bakın . Ayarlamakaverage=NoneEtiketleri ve tanımlayın, ardından belirttiğiniz etiketlerden her biri için aradığınız ölçüyü elde edersiniz.
wonderkid2

Etiket açısından doğruluk puanları almanın bir yolu var mı?
Ankur Sinha

@trollster Ne demek istediğinden emin değilim? Cevap etiketsel doğruluk puanlarında gösterdiğim şey değil mi?
wonderkid2

16

Sorulan soru

'Dengesiz verilerle çok sınıflı sınıflandırma için hangi ölçüt kullanılmalıdır' sorusuna yanıt vermek: Makro-F1 ölçüsü. Makro Hassasiyet ve Makro Geri Çağırma da kullanılabilir, ancak bunlar ikili sınıflandırma için olduğu kadar kolay yorumlanamazlar, zaten F ölçüsüne dahil edilmişlerdir ve fazla ölçüler yöntem karşılaştırmasını, parametre ayarlamasını vb. Karmaşıklaştırır.

Mikro ortalama, sınıf dengesizliğine duyarlıdır: Örneğin, yönteminiz en yaygın etiketler için iyi çalışıyorsa ve diğerlerini tamamen karıştırıyorsa, mikro ortalamalı ölçümler iyi sonuçlar verir.

Ağırlık ortalaması, dengesiz veriler için pek uygun değildir, çünkü etiket sayısına göre ağırlık verir. Dahası, çok zor yorumlanabilir ve popüler değildir: örneğin, aşağıdaki çok detaylı ankette böyle bir ortalamadan bahsedilmemektedir, kesinlikle incelemenizi tavsiye ederim:

Sokolova, Marina ve Guy Lapalme. "Sınıflandırma görevleri için performans ölçütlerinin sistematik bir analizi." Bilgi İşleme ve Yönetimi 45.4 (2009): 427-437.

Uygulamaya özel soru

Ancak, görevinize dönersek, 2 konu araştırırım:

  1. Özel göreviniz için yaygın olarak kullanılan ölçütler - (a) yönteminizi başkalarıyla karşılaştırmanıza ve yanlış bir şey yapıp yapmadığınızı anlamanıza ve (b) bunu kendi başınıza keşfetmemenize ve başka birinin bulgularını yeniden kullanmanıza olanak tanır;
  2. Yöntemlerinizin farklı hatalarının maliyeti - örneğin, uygulamanızın kullanım durumu yalnızca 4 ve 5 yıldızlı incelemelere dayanabilir - bu durumda, iyi bir metrik yalnızca bu 2 etiketi saymalıdır.

Yaygın olarak kullanılan metrikler. Literatüre baktıktan sonra çıkarabileceğim gibi, 2 ana değerlendirme ölçütü var:

  1. Kullanılan doğruluk , örneğin

Yu, April ve Daryl Chang. "Yelp Business'ı Kullanarak Çok Sınıflı Duygu Tahmini."

( bağlantı ) - yazarların neredeyse aynı derecelendirme dağılımıyla çalıştığını unutmayın, bkz. Şekil 5.

Pang, Bo ve Lillian Lee. "Yıldızları görmek: Derecelendirme ölçeklerine göre duyarlılık sınıflandırması için sınıf ilişkilerini kullanmak." Hesaplamalı Dilbilim Derneği 43. Yıllık Toplantısı Bildirileri. Hesaplamalı Dilbilim Derneği, 2005.

( bağlantı )

  1. MSE (veya daha az sıklıkla Ortalama Mutlak Hata - MAE ) - örneğin bkz.

Lee, Moontae ve R. Grafe. "Restoran incelemeleri ile çok sınıflı duyarlılık analizi." CS N 224'ten (2010) Nihai Projeler.

( bağlantı ) - ikincisinin daha iyi olduğunu düşünerek hem doğruluğu hem de MSE'yi keşfederler

Pappas, Nikolaos, Rue Marconi ve Andrei Popescu-Belis. "Yıldızları Açıklamak: Boyut Tabanlı Duygu Analizi için Ağırlıklı Çoklu Örnek Öğrenme." 2014 Doğal Dil İşlemede Ampirik Yöntemler Konferansı Bildirileri. No. EPFL-CONF-200899. 2014.

( bağlantı ) - değerlendirme ve temel yaklaşımlar için scikit-learn'ü kullanırlar ve kodlarının mevcut olduğunu belirtirler; ancak bulamıyorum, bu yüzden ihtiyacınız olursa yazarlara bir mektup yazın, çalışma oldukça yeni ve Python ile yazılmış gibi görünüyor.

Farklı hataların maliyeti . Büyük hatalardan kaçınmayı daha çok önemsiyorsanız, örneğin 1 yıldızdan 5 yıldıza kadar olan incelemeleri veya bunun gibi bir şeyi varsayıyorsanız, MSE'ye bakın; fark önemliyse, ancak çok önemli değilse, MAE'yi deneyin, çünkü farkın karesini alamaz; aksi takdirde Doğruluk ile kalın.

Metrikler değil, yaklaşımlar hakkında

Genellikle SVC veya OVA SVM gibi Çok Sınıflı sınıflandırıcılardan daha iyi performans gösterdiklerinden, regresyon yaklaşımlarını deneyin, örneğin SVR .


13

Her şeyden önce, verilerinizin dengesiz olup olmadığını anlamak için sadece sayma analizini kullanmak biraz daha zordur. Örneğin: 1000 pozitif gözlemden 1'i sadece bir gürültü mü, hata mı yoksa bilimde bir atılım mı? Asla bilemezsin.
Bu nedenle, mevcut tüm bilgilerinizi kullanmak ve durumunu tüm bilge bir şekilde seçmek her zaman daha iyidir.

Tamam, ya gerçekten dengesizse?
Bir kez daha - verilerinize bakın. Bazen bir veya iki gözlemin yüz katı ile çarpıldığını görebilirsiniz. Bazen bu sahte tek sınıf gözlemleri oluşturmak faydalı olabilir.
Tüm veriler temizse, sonraki adım tahmin modelinde sınıf ağırlıklarını kullanmaktır.

Peki ya çok sınıflı metrikler?
Tecrübelerime göre genellikle ölçümlerinizden hiçbiri kullanılmıyor. İki ana neden var.
Birincisi: Olasılıklarla çalışmak, sağlam tahminden daha iyidir (çünkü modelleri, her ikisi de size aynı sınıfı veriyorsa, 0.9 ve 0.6 tahminle başka nasıl ayırabilirsiniz?)
Ve ikincisi: tahmin modellerinizi karşılaştırmak ve yenilerini oluşturmak çok daha kolay tek bir iyi ölçüme bağlı olanlar.
Benim deneyim tavsiye verebilecek logloss veya MSE (ya da sadece ortalama karesel hata).

Sklearn uyarıları nasıl düzeltilir?
Sadece (yangjie'nin fark ettiği gibi) averageşu değerlerden biriyle parametrenin üzerine yazın : 'micro'(küresel olarak ölçütleri hesaplayın), 'macro'(her etiket için ölçütleri hesaplayın) veya 'weighted'( makroyla aynı, ancak otomatik ağırlıklarla).

f1_score(y_test, prediction, average='weighted')

Tüm Uyarılarınız , çok sınıflı tahmin için uygun olmayan varsayılan averagedeğere 'binary'sahip metrik işlevlerini çağırdıktan sonra geldi .
İyi şanslar ve makine öğreniminde iyi eğlenceler!

Düzenle:
Kabul edemediğim regresyon yaklaşımlarına (örneğin SVR) geçmek için başka bir yanıtlayıcı önerisi buldum. Hatırladığım kadarıyla çok sınıflı regresyon diye bir şey bile yok. Evet, çok farklı olan çok etiketli regresyon vardır ve evet bazı durumlarda regresyon ve sınıflandırma arasında geçiş yapmak mümkündür (eğer sınıflar bir şekilde sıralanırsa), ancak oldukça nadirdir.

Tavsiye ettiğim şey (scikit-learn kapsamında) başka çok güçlü sınıflandırma araçlarını denemektir: gradyan artırma , rastgele orman (benim favorim), KNeighbors ve daha fazlası.

Bundan sonra, tahminler arasındaki aritmetik veya geometrik ortalamayı hesaplayabilirsiniz ve çoğu zaman daha da iyi sonuçlar alırsınız.

final_prediction = (KNNprediction * RFprediction) ** 0.5

1
> "regresyon ve sınıflandırma arasında geçiş yapın (eğer sınıflar bir şekilde sıralanırsa) ama oldukça nadirdir" Durum şu: 5> 4> 3> 2> 1. Bu görev için kağıtlara bir göz atmanızı öneririm - var görev için birçok regresyon ve sınıflandırma yaklaşımı (bazen aynı çalışmada).
Nikita Astrakhantsev

O zaman bu çok sınıflı bir sınıflandırma değil, basit bir gerileme.
Vlad Mironov

Evet, dahili olarak veya makine öğrenimi açısından, bu bir gerilemedir, ancak son adımda regresyon sonuçlarını etiketlere dönüştürüyoruz, bu nedenle kullanıcı veya uygulama açısından çok sınıflı bir sınıflandırmadır.
Nikita Astrakhantsev
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.