Fundamente de Data Science

4.4 Matricea de confuzie și curbele ROC

Un singur număr (acuratețea) ascunde ce greșește modelul. Matricea de confuzie și curba ROC arată exact unde și cum greșește — și cum poți repara.

Teorie

Construcția matricei de confuzie

Tabel cu clasele reale pe rânduri și cele prezise pe coloane; celula (i, j) numără exemplele din clasa i prezise ca j. Pentru clasificare binară:

Prezis: negativPrezis: pozitiv
Real: negativTNFP (alarmă falsă)
Real: pozitivFN (ratat)TP

Interpretare

Diagonala = corect; restul = erori, defalcate pe tip. La multi-clasă vezi imediat care perechi de clase se confundă (de exemplu cifrele 3 și 8) — informație care îți spune ce feature-uri să adaugi. Din matrice derivă direct precizia și recall-ul fiecărei clase (lecția 4.1).

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay

cm = confusion_matrix(y_val, y_pred)
ConfusionMatrixDisplay(cm, display_labels=model.classes_).plot(cmap="Blues")

Curba ROC și AUC

Clasificatorul dă probabilități; pragul (implicit 0.5) le transformă în clase. Curba ROC arată, pentru toate pragurile posibile, compromisul dintre rata adevărat-pozitivelor (recall) și rata fals-pozitivelor:

TPR = TP/(TP+FN) — cât din pozitivele reale prindem (axa Y)

FPR = FP/(FP+TN) — cât din negativele reale alarmăm din greșeală (axa X)

AUC (aria de sub curbă): 1.0 = separare perfectă, 0.5 = ghicit la întâmplare (diagonala). AUC nu depinde de prag — măsoară cât de bine ordonează modelul exemplele.

Utilizare pentru clasificare — alegerea pragului

from sklearn.metrics import roc_curve, roc_auc_score
import matplotlib.pyplot as plt

proba = model.predict_proba(X_val)[:, 1]
fpr, tpr, praguri = roc_curve(y_val, proba)
print("AUC:", roc_auc_score(y_val, proba))

plt.plot(fpr, tpr); plt.plot([0, 1], [0, 1], "--", c="gray")
plt.xlabel("FPR"); plt.ylabel("TPR"); plt.show()

# prag personalizat: prindem mai multe pozitive, acceptăm mai multe alarme
pred_strict = (proba >= 0.3).astype(int)
Când enunțul punctează cu F1 pe clase dezechilibrate, încearcă praguri diferite pe validare — de multe ori 0.3–0.4 bate pragul implicit 0.5.

Problemă rezolvată: diagnoza completă a unui clasificator medical

Matrice + ROC pe problema diabetului Mediu Rezolvată

Continuăm problema din lecția 2.2: modelul e antrenat, acum îl anatomizăm — matrice de confuzie, curbă ROC, alegerea pragului optim pentru F1.

Rezolvarea completă
import numpy as np
from sklearn.metrics import (confusion_matrix, ConfusionMatrixDisplay,
                             roc_curve, roc_auc_score, f1_score)

proba = model.predict_proba(X_val)[:, 1]

# 1. matricea de confuzie la pragul implicit
cm = confusion_matrix(y_val, proba >= 0.5)
print(cm)          # de ex. [[85  8]
                   #         [17 25]]  → 17 diabetici ratați!

# 2. curba ROC + AUC
print("AUC:", roc_auc_score(y_val, proba).round(3))

# 3. pragul care maximizează F1 pe validare
praguri = np.linspace(0.1, 0.9, 81)
f1s = [f1_score(y_val, proba >= p) for p in praguri]
best = praguri[int(np.argmax(f1s))]
print("Prag optim:", best.round(2), "F1:", max(f1s).round(3))

cm2 = confusion_matrix(y_val, proba >= best)
print(cm2)         # FN scade — mai puțini bolnavi ratați

Concluzia: același model, prag ales inteligent → F1 mai mare și mai puține cazuri ratate. Nimic din model nu s-a schimbat — doar citirea probabilităților.

Probleme propuse

1. Matrice de mână Exercițiu

Din y_real = [A,A,B,B,B,C,C,A,B,C] și y_pred = [A,B,B,B,C,C,C,A,B,A], construiește matricea de confuzie 3×3 pe hârtie. Care clasă are cel mai slab recall?

2. Punct pe curbă Exercițiu

Pentru pragul 0.5, TPR = 0.8 și FPR = 0.1. Marchează punctul pe o schiță de curbă ROC. Ce se întâmplă cu ambele rate când cobori pragul la 0.2?

3. Cifre confundate Exercițiu

Antrenează un clasificator pe digits și afișează matricea de confuzie 10×10. Care două cifre se confundă cel mai des? Afișează câteva imagini greșit clasificate.

4. Praguri la concurs Platformă

Pe o problemă binară punctată cu F1, compară scorul submisiei cu prag 0.5 vs pragul optimizat pe validare locală.