ROC görbe alatti terület

A mai bejegyzésben megismerkedünk egy módszerrel, amivel két osztályos klasszifikáció modellek teljesítményét tudjuk mérni és optimalizálni. Ez a módszer a “ROC görbe alatti terület” (angolul: “Area under the ROC curve”).


Klasszikus teljesítménymérés

Bár a blogon nem volt téma eddig, de gondolom a legtöbbeknek ismerős az “igazságmátrix” ( angolul: “Confusion_matrix”) fogalma. Annak, akiknek mégsem lenne, nagy vonalakban ismertetem. Az igazságmátrix egy nagyon egyszerű táblázat, aminek egyik oldalán a tesztadatunk valós osztályai, míg a másik oldalán a modellünk által előre jelzett osztályok szerepelnek. Általános szokás szerint a sorokban vannak az igazi osztályok, és az oszlopokban a becsültek. A szemléltetés végett nézzünk egy szintetikus teszt adatsort:

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# mintavétel 
X, y = make_classification(n_samples=1000, n_classes=2, random_state=1)
# tanuló és treszt adatokra vágás
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.5, random_state=2)

Most illesszünk rá egy logisztikus regressziós modellt (később lesz róla szó miért pont ezt a választottam):

from sklearn.linear_model import LogisticRegression
# model illesztése
model = LogisticRegression()
model.fit(train_X, train_y)
probs_y = model.predict_proba(test_X)
# csak a +  osztály értékeit hagyuk meg
probs_y = probs_y[:, 1] 

És az igazságmátrix:

import seaborn as sn
import pandas as pd
cutoff = 0.5
probs_y_binary = [ 0 if x < cutoff else 1 for x in probs_y ]

data = {'y_Actual':    test_y,
        'y_Predicted': probs_y_binary
        }

df = pd.DataFrame(data, columns=['y_Actual','y_Predicted'])
confusion_matrix = pd.crosstab(df['y_Actual'], df['y_Predicted'], rownames=['Valóság'], colnames=['Model eredménye'])

sn.heatmap(confusion_matrix, annot=True,  fmt="d")
plt.show()
Igazságmátrix

Egy modell teljesítményét legnyilvánvalóbban a “pontosság” (angolul: Accuracy) értékkel mérhetjük. Ez annak a valószínűsége, hogy egy megfigyelést helyes osztályba sorol a modell. A fenti példánál maradva, a modell pontossága:

\frac{197+220}{197+220+40+43} =  0,834

Ez egy jó mérőszám addig, amíg a tévedések egyformán fontosak. De ez nem mindig van így. Néha arra törekszünk, hogy vagy az álpozitív vagy az álnegatív értékeket jobban minimalizáljuk. Mi történik akkor például, ha a modellünk rákos daganatokat keres CT felvételeken? Értelemszerűen ilyenkor a célunk az álnegatív értékek csökkentése, még akkor is ha ezzel egyidőben az álpozitív értékek jobban növekednek, és a modell pontossága csökken. Miért? Etikai okokból az sokkal kisebb probléma, ha egy egészséges embert további kivizsgálásokra küldünk, mintha egy beteg esetén elmulasztjuk a kezelést. Ezekben az esetekben lesz segítségünkre a ROC. Mi is ez?

ROC

A ROC (Receiver Operating characteristic) egy vizuális ábrázolása az álpozitív és álnegatív értékeknek kétosztályos klasszifikációnál. A ROC két értéket használ az ábrázolásra: az Valós pozitív arányt (angolul: True positive rate, magyarul nevezik még szenzitivitás-nak is) és az Álnegativ arányt (angolul: True negativ rate). Ezek tulajdonképpen az igazságmátrix sorai. Az Álpozitív arány: 43/(43+197)=0,18, az Valós pozitív arány pedig: 220/(40+220)=0,85. Ha a fenti példa igazságmátrix értékeit kiszámoljuk és ábrázoljuk akkor a következőt fogjuk kapni:

Igazságmátrix ROC ábrázolása

Mire jó ez? Ez eddig nem sokra. Amit fontos tudatosítani, hogy használható ROC ábra nem készíthető minden modellhez. Vannak modellek, amik kimenete egyszerű 1 vagy 0. Ezek ROC ábrája ábrája a fentiekhez hasonló lesz: egyetlen egy pontot fog tartalmazni. Ekkor a ROC semmi használható extra információt nem nyújt számunkra az igazságmátrixszal összevetve.

Vannak modellek amik ezzel szemben valószínűséget rendelnek az osztályokhoz. Neurális hálózatok tipikusan ide sorolhatók, vagy a logisztikus regresszió is például. Ezek eredménye nem egyértelmű 0 vagy 1, hanem annak a valószínűsége, hogy a megfigyelés az egyik vagy másik osztályba tartozik. Pl: 0,25 és 0,75. Ami azt fogja jelenteni, hogy a megfigyelés 25% valószínűséggel negatív és 75%-os valószínűséggel pozitív. Értelemszerűen ilyen esetekben felmerül a kérdés, hogy mi legyen az a határérték ami felett a megfigyelést egyik vagy másik osztályhoz rendeljük. Az 50% egy természetes értéknek tűnik ilyen esetekben, fentebb ezt is alkalmaztuk az igazságmátrixunkhoz. De fontos tudatosítani, hogy ez nincs kőbe vésve. Amikor az Álnegatív és Álpozitív nem egyformán fontos számunkra kifejezetten jó ötletnek tűnik más értéket választani. De mi legyen ez az érték ilyen esetben?

Értelemszerűen minden egyes határérték esetén más-más lesz az igazságmátrix. Megtehetnénk, hogy elkezdünk kísérletezni és elkészítünk egy rakás igazságmátrixot, amíg olyat nem találunk ami megfelel számunkra. Ez azért elég időigényes. A ROC ábra ezt a folyamatot egyszerűsíti le: egyetlen egy ábrában foglalja össze a különböző igazságmátrixok eredményét. Minden igazságmátrix egy pont a ROC ábrán. Paul van der Laken-nek van egy jó ábrája ennek szemléltetésére:

Készítsünk mi is egy ROC-ot a modellünkhöz:

# ROC számítása
fpr, tpr, cutoff = roc_curve(test_y, probs_y)

# Alapvonal
plt.plot( np.linspace(0,1,100), np.linspace(0,1,100), linestyle='--', label='Alapvonal')
# logistic regresion model
plt.plot(fpr, tpr, marker='.', label='Logistic model')
# tengelyek címkézése
plt.xlabel('Álpozitiv arány')
plt.ylabel('Valós pozitiv arány')
plt.legend()
plt.show()
ROC ábra

Miben segít ez nekünk? A daganatos betegek példájánál maradva, azt szeretnénk, ha a Valós pozitív arány maximális lenne, és ezért hajlandók vagyunk elfogadni nagyobb álpozitív értéket. Jelen példánál ez:

# megkeressük a legkisebb álpozitív értékű pontot ahol a Valós pozitív == 1 
index = np.where(tpr == 1)[0][0]
cutoff_alneg = cutoff[index]
# igazságmátrix
probs_y_binary = [ 0 if x < cutoff_alneg else 1 for x in probs_y ]

data = {'y_Actual':    test_y,
        'y_Predicted': probs_y_binary
        }

df = pd.DataFrame(data, columns=['y_Actual','y_Predicted'])
confusion_matrix = pd.crosstab(df['y_Actual'], df['y_Predicted'], rownames=['Valóság'], colnames=['Model eredménye'])

sn.heatmap(confusion_matrix, annot=True,  fmt="d")
plt.title(f"Ideállis model Álnegatív minimalizálásra")
plt.show()

Mint fentebb látható, tényleg minimumra csökkentettük az Álnegatív értéket, viszont ennek az ára az volt, hogy sok Álpozitív értékünk lett. A modell Pontossága 0,588-ra csökkent a korábbi 0,834-ről, de ebben az esetben mégis ezt a modellt támogatjuk.

Hasonló módon megtalálhatjuk a legjobb pontosságú modellt:

index = np.where(tpr-fpr == np.max(tpr-fpr))
cutoff_pont = cutoff[index][0]
print("Ideállis pontosság", cutoff_pont)

Ami jelen esetben a 0,49-nél lesz, a modell pontosság pedig ekkor 0,84.

Ami talán nem egyből egyértelmű, hogy a ROC-ot modellek összehasonlítására is lehet használni. Egy jó modell meredeken emelkedik az elejétől fogva és távolabb helyezkedik el az Alapvonaltól. Ezt számszerűsíteni is lehet. Ez lesz az AOC, ami a modell alatti terület aránya a teljes 1×1-es tartományhoz. Értelemszerűen az Alapvonal AOC-ja 0,5-lesz mivel felezi a lehetséges tartományt. Nézzük meg a fenti modell AOC-ját:

auc = roc_auc_score(test_y, probs_y)
print('AUC: %.3f' % auc)

Ez 0,903 lesz, ez elég jó. Paul van der Laken-nek van arra nézve is egy jó ábrája, hogy alakul az AOC ahogy a modellünk egyre jobb:

A fenti ábrán szépen látszik, hogy minél jobban elkülönülnek egymástól az osztályok, az AOC értéke annál jobban növekszik.

ROC korlátai

A ROC egyik nagy problémája, hogy nem tudja kezelni ha az osztályok nem egyforma nagyságúak. Paul van der Laken ezt is jól szemlélteti:

Mint a fenti ábrán észrevehető a ROC érdemben nem változik, annak ellenére, hogy egyértelmű, hogy a modellek nem egyforma pontóságúak. Ilyen esetekre a Pontosság–Valós pozitív arány (angolul: Precision-Recall) lehet segítségünkre.

Irodalom

Hírdetés

ROC görbe alatti terület” bejegyzéshez egy hozzászólás

Vélemény, hozzászólás?

Adatok megadása vagy bejelentkezés valamelyik ikonnal:

WordPress.com Logo

Hozzászólhat a WordPress.com felhasználói fiók használatával. Kilépés /  Módosítás )

Facebook kép

Hozzászólhat a Facebook felhasználói fiók használatával. Kilépés /  Módosítás )

Kapcsolódás: %s