Tutorial o tym, jak mierzyć jakość klasyfikatora i dlaczego zwykła dokładność (ang. accuracy) to często za mało. Wyjaśniam intuicję i na przykładach pokazuję o co chodzi w: precision, recall oraz F1
Wpis jest częścią serii o mierzeniu jakości klasyfikacji, dotychczas powstały:
- Precision, recall i F1 – miary oceny klasyfikatora
- Krzywa Precision-Recall jak ją wykreślić i zinterpretować
- Krzywa ROC (todo)
Accuracy – czemu mnie okłamujesz?
Dokładność jest najpowszechniejszą metryką do oceny jakości klasyfikacji. Jest prosta w zrozumieniu i interpretacji. Niestety, w wielu wypadkach niewystarczającą. Gdy rozkład elementów w klasach jest nierównomierny, to posługiwanie się tylko dokładnością zaburza pogląd sytuacji.
W wielu życiowych przykładach nierównomierny rozkład jest na porządku dziennym np. rozpoznawanie chorób (zazwyczaj mamy więcej pacjentów zdrowych), klasyfikacja fraudów, rozpoznawanie błędów, rozpoznawanie named entity (NER) w tekście itp.
Przyjrzyjmy się przykładowi. Załóżmy, iż w klasie „pozytywnej” mamy 990 egzemplarzy a w „negatywnej” tylko 10. Wyobraźmy sobie sytuację (nie taką rzadką), iż nasz klasyfikator wyuczy się tylko rozpoznawania klasy „pozytywnej”. Każdy obiekt będzie przypisywał właśnie do niej. Policzmy dokładność (accuracy):
Dokładność wyniesie: 990/(990+10) = 0,99
990 poprawnie rozpoznanych egzemplarzy (tych „pozytywnych”) do liczby wszystkich elementów w zbiorze. Czyli całkiem nieźle, prawda?
Chyba czujecie, iż jednak nie do końca. Co, o ile te 10 przypadków to małe, słodkie kotki, które są zagrożone wyginięciem i to właśnie je chcemy rozpoznawać i ratować?
Dobrze by było mieć metrykę, która bierze pod uwagę także, w jakim stopniu dane klasy są rozpoznawane oraz jaka jest jakość rozpoznania w obrębie danej klasy.
Jakość rozpoznania w obrębie klasy decyzyjnej
W naszym przykładzie klasa „pozytywna” rozpoznawana jest w 100% ( 990/990). Wszystkie egzemplarze pozytywne zostały rozpoznane jako pozytywne (bo wszystko rozpoznaje jako pozytywne). Jakość rozpoznania klasy pozytywnej wynosi 990/1000=0,99. Rozpoznał 1000 jako „pozytywne” z czego tylko 990 rzeczywiście przynależy do tej klasy. Ogólnie całkiem nieźle.
Sprawa wygląda zupełnie inaczej gdy popatrzymy na klasę „negatywną”. Policzmy na ile jest rozpoznawana: 0/10=0. Żaden element z 10 z klasy „negatywnej” nie został rozpoznany, uuu słabo. To może policzmy jakość rozpoznania 0/0. Klasyfikator nie rozpoznał żadnego elementu z klasy negatywnej (0 w liczniku). Nie przydzielił także żadnego elementu do tej klasy (0 w mianowniku). Jeszcze słabiej
Precission, recall, true positive, false negative i inne niezapadające w pamięć nazwy
Spróbujmy sformalizować powyższe spostrzeżenia i intuicje i na moment skupmy się tylko na klasyfikacji binarnej. W powyższym akapicie wyróżniliśmy dwie cechy dobrego klasyfikatora. Dokładność rozpoznania w obrębie klasy oraz to, w jakim stopniu rozpoznaje („chwyta”) wszystkie elementy klasy.
Przyjmijmy, iż nasz klasyfikator binarny ma do rozpoznania dwie klasy „A” i „B”. I przyjmijmy do interpretacji, iż klasa „A” to klasa pozytywna, a „B” negatywna (jest to tylko kwestia interpretacji i zależna od rzeczywistego przykładu). Dokonując predykcji możliwe są następujące warianty:
- część elementów z klasy A rozpozna jako A – poprawna klasyfikacja,
- część elementów z klasy A rozpozna jako B – błąd klasyfikacji,
- część elementów z klasy B rozpozna jako A – błąd klasyfikacji,
- część elementów z klasy B rozpozna jako B – poprawna klasyfikacja.
Liczbę elementów z powyższego przykładu można ładnie zestawić w tabeli (zwanej Confusion matrix). Statystycy nazwali powyższe sytuacje jako: True positive, False negative, False positive,, True negative. I skoro klasa A u nas jest pozytywna, a B negatywna można to sobie przetłumaczyć następująco: True A (wariant 1) , False B (wariant 2), False A (wariant 3), True B (wariant 4).
Powyższymi pojęciami będziemy się posługiwali definiując precision i recall. Uzupełnijmy tabelę przykładowymi liczbami.
Najlepiej czytać tę tabelę wierszowo. Czyli w sumie 999 elementów zostało zakwalifikowanych do klasy A (predicted as A), a tylko 1 element do klasy B. W tym 990 zostało oznaczonych jako A będąc rzeczywiście w klasie A oraz 9 należących do klasy B. Tylko 1 obiekt z klasy B został rozpoznany jako B i 0 elementów z klasy A zostało rozpoznanych jako B.
Miara precision odpowiada za dokładność rozpoznania klasy A, czyli jaką część stanowią poprawnie przewidziane elementy TP (true positive) do wszystkich oznaczonych jako A przez klasyfikator sumy TP+FP (true positive + False positive)
Miara recall (nazywana także: sensitivity czy true positive rate ) informuje nas ile elementów z danej klasy zostało poprawnie rozpoznanych. Wyrażana jest jako stosunek TP/(TP+FN)
Definicje wzorów – precision i recall
Pierwotnie w statystyce precision i recall odnosiło się do klasy pozytywnej, ale bardzo łatwo je uogólnić na wiele klas. I tak dla klasy A i B wzory wyglądają następująco. Wystarczy zsumować i podzielić odpowiednie komórki dla poszczególnych klas.
Zastanówmy się przez chwilę nad powyższymi wzorami:
- precision dla klasy A, jest to stosunek poprawnie sklasyfikowanych elementów z A (TP) do wszystkich, które nasz klasyfikator oznaczył jako A (TP+FP)
- recall dla klasy A, jest to stosunek poprawnie rozpoznanych elementów z A (TP) do wszystkich, które powinien rozpoznać, czyli do całej klasy A (TP+FN)
Podobnie jest z klasą B
- precision dla klasy B, jest to stosunek poprawnie sklasyfikowanych elementów z B (TN) do wszystkich, które nasz klasyfikator oznaczył jako B (TN+FN)
- recall dla klasy B, jest to stosunek poprawnie rozpoznanych elementów z B (TN) do wszystkich, które powinien rozpoznać, czyli do całej klasy B (TN+FP)
Podstawiająć liczby powinny wam wyjść wartości
Jeżeli chcecie pobawić się liczbami to przygotowałem pomocnego excela, do którego możecie wstawić swoje wartości i podejrzeć formuły: https://docs.google.com/spreadsheets/d/1ufHV2krvbtr7jPF-KBkK1IOHuPI4cxTjtdCuNZCizLo/edit?usp=sharing
One Ring to rule them all – miara F1
Uuu Panie, wszystko super, tylko jak jesteś taki mądry to powiedz jak mam ogarnąć 4 miary zamiast jednej. Jak porównać do siebie dwa klasyfikatory?
Sprawa jest prosta, gdy wszystkie wartości są dla jednego z nich większe, ale co w sytuacji, gdy w jednym większe jest precision dla klasy „A”, a w drugim recall.
Weź głęboki oddech i się uspokój. Zaraz dam Ci rozwiązanie.
Oto magiczne rozwiązanie: uśrednij wyniki!
Ale aby nie było za prosto, nie wystarczy tutaj zwykła średnia arytmetyczna dla precision i recall. Lepiej zastosować średnią harmoniczną.
A dlaczego tak? Szczegółową odpowiedź znajdziesz na stack overflow: Why is the F-Measure a harmonic mean and not an arithmetic mean of the Precision and Recall measures?
Ja tylko przytoczę dwa wykresy funkcji dla średniej arytmetycznej i harmonicznej.
Co z nich wynika? Zauważcie, iż średnia harmoniczna bardziej „karze” gdy jeden z wyników jest zły (bliski zera). Wartość średniej wtedy jest także mała (ciemnoniebieskie obrzeża). Dzięki tej adekwatności możemy gwałtownie zauważyć, iż coś jest nie tak z którąś z wartości (precision bądź recall).
A oto proszę państwa wzór na F1:
W bardziej ogólnym przypadku Fβ, gdy chcemy wskazać co jest dla nas ważniejsze precision czy recall.
Jeżeli obie miary są ważne to podstawiamy za β=1, o ile bardziej zależy nam na precission to Beta powinna być z przedziału [0,1], zaś w przeciwnym przypadku gdy bardziej zależy na Recall to β>1.
Zazwyczaj mamy trzy sytuację:
- β=1 – precision i recall tak samo ważne
- β=0.5 precision ważniejsze
- β=2 recall ważniejszy
Uśredniona miara F1
W poprzedniej sekcji omówiliśmy miarę F1, ale tylko dla jednej klasy. Precision i recall możemy policzyć dla każdej klasy z osobna i otrzymamy dwie wartości F1 (dla klasy A i B). Chcąc mieć tylko jedną liczbę dla naszego klasyfikatora binarnego możemy dokonać uśrednienia dwóch F1. Obliczymy w ten sposób macro average F1.
Dla tych, co chcą wgłębić się w bebechy miary F1 polecam artykuł https://www.mikulskibartosz.name/f1-score-explained/
Problem wieloklasowy
Podobnie jak dla dwóch klas powyższe miary: precision, recall i F1 można policzyć dla wielu klas. W przykładowym arkuszu kalkulacyjnym https://docs.google.com/spreadsheets/d/1ufHV2krvbtr7jPF-KBkK1IOHuPI4cxTjtdCuNZCizLo/edit#gid=372756307
jest zakładka multiclass_classification, w której podaję przykład jak to dokładnie policzyć. Przeanalizujcie sami, sądzę, iż po powyższej lekturze ze zrozumieniem nie będziecie mieli problemu.
Jak policzyć precision, recall i F1 w scikit-learn?
Z wykorzystaniem biblioteki scikit-learn to banalnie proste. Wystarczy przygotować tylko dane wejściowe:
- y_true – czyli rzeczywiste etykiety
- y_pred – etykiety przewidziane przez klasyfikator.
Resztą zajmie się już sklearn! Wykorzystaj metodę classification_report z mudułu sklearn.metrics
Poniższy kod znajdziesz także w projekcie na moim githubie https://github.com/ksopyla/scikit-learn-tutorial/blob/master/metrics/metrics.py
Potrzebujemy dwóch tablic:
- y_true – tablica z rzeczywistymi wartościami klas
- y_pred – tablica z przewidzianymi klasam
Następnie liczymy i wyświetlamy confusion matrix oraz raport klasyfikacji. Zauważcie, iż scikit learn domyślnie za klasę pozytywną bierze wartości „1”. To i wiele innych domyślnych ustawień można łatwo zmienić przekazując do metody dodatkowe parametry. Warto zwrócić uwagę na następujące:
- output_dict=True – zwróci nam słownik z poszczególnymi wartośiami
- target_names=[’klasa A’, 'klasa B’] – możemy podać nazwy dla naszych klas
Podsumowanie
We wpisie przedstawiłem idea oraz intuicję podstawowych miar używanych podczas oceny klasyfikatorów: precision, recall i miarę F1. Zachęcam do „pobawienia” się udostępnionym arkuszem kalkulacyjnym w celu poczucia jak te miary się zmieniają w zależności od wartości: true positive, false positive, false negative i true negative. Warto także poeksperymentować z parametrami do metod w powyższych przykładach. Powodzenia w nauce.
Jeżeli uważasz ten wpis za wartościowy to Zasubskrybuj bloga. Dostaniesz informacje o nowych artykułach.
Zapisz mnie
Ps. Obraz Steve Buissinne z Pixabay