ROC-kurvor och AUC-ROC
Ni kommer att rita ROC-kurvan genom att variera beslutströskeln, beräkna AUC och tolka det som sannolikheten att ett slumpmässigt positivt exempel rangordnas högre än ett slumpmässigt negativt.
ROC-kurvor och AUC-ROC är en gratis lektion i Machine Learning Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Machine Learning Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.
Begränsningar hos mått med fast tröskel
Precision, recall och F1-poäng beror alla på en fast beslutströskel (vanligtvis 0,5 för binära klassificerare). Men den optimala tröskeln varierar beroende på användningsområde: ett spamfilter kanske använder 0,9 (strikt för att undvika falskt positiva resultat), medan en bedrägeridetektor kanske använder 0,1 (generös för att undvika att missa bedrägerier). Om du utvärderar en modell vid bara en tröskel får du en ofullständig bild av dess förmåga. ROC-kurvan (Receiver Operating Characteristic) löser detta genom att samtidigt visa prestandan vid alla möjliga trösklar, så att du kan förstå hela det spann av avvägningar mellan precision och recall som modellen kan uppnå.
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = LogisticRegression(max_iter=10000)
clf.fit(X_tr, y_tr)
proba = clf.predict_proba(X_te)[:, 1]
for t in [0.1, 0.3, 0.5, 0.7, 0.9]:
y_pred = (proba >= t).astype(int)
print(f'thresh={t}: prec={precision_score(y_te,y_pred,zero_division=0):.3f}, '
f'rec={recall_score(y_te,y_pred,zero_division=0):.3f}')True Positive Rate och False Positive Rate
ROC-kurvan byggs utifrån två mått som beräknas vid varje tröskel: True Positive Rate (TPR) (samma som recall/sensitivitet): TPR = TP / (TP + FN) — hur stor andel av de faktiska positiva fallen fångade vi? False Positive Rate (FPR): FPR = FP / (FP + TN) — hur stor andel av de faktiska negativa fallen flaggade vi felaktigt? När tröskeln sänks ökar både TPR och FPR. ROC-kurvan visar TPR mot FPR när tröskeln varierar från 1 (förutsäg inget som positivt) till 0 (förutsäg allt som positivt). En perfekt klassificerare når (0, 1) — noll falsklarm och alla sanna positiva fall hittade.
import numpy as np
from sklearn.metrics import confusion_matrix
def tpr_fpr(y_true, y_pred):
TN, FP, FN, TP = confusion_matrix(y_true, y_pred).ravel()
tpr = TP / (TP + FN) # Recall = sensitivity
fpr = FP / (FP + TN) # False positive rate = 1 - specificity
return tpr, fpr
# Example predictions at different thresholds
y_true = np.array([1,1,1,0,0,0,0,0,0,0])
for thresh in [0.3, 0.5, 0.7]:
# Simulated probabilities
proba = np.array([0.9, 0.8, 0.4, 0.6, 0.5, 0.3, 0.2, 0.1, 0.05, 0.01])
y_pred = (proba >= thresh).astype(int)
tpr, fpr = tpr_fpr(y_true, y_pred)
print(f'thresh={thresh}: TPR={tpr:.2f}, FPR={fpr:.2f}')Rita ROC-kurvan
Scikit-learns roc_curve() beräknar paren (FPR, TPR) för alla trösklar i ett enda anrop. RocCurveDisplay skapar en figur som är redo för publicering. ROC-kurvan för en slumpmässig klassificerare är den diagonala linjen från (0,0) till (1,1) — den presterar inte bättre än slumpen vid någon tröskel. En bra klassificerare böjer av mot det övre vänstra hörnet och uppnår hög TPR med låg FPR. Ju längre kurvan ligger från diagonalen, desto bättre är klassificeraren. Arean under kurvan (AUC) sammanfattar prestandan i ett enda tal.
from sklearn.metrics import roc_curve, RocCurveDisplay
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = LogisticRegression(max_iter=10000)
clf.fit(X_tr, y_tr)
RocCurveDisplay.from_estimator(clf, X_te, y_te)
plt.plot([0,1],[0,1],'k--', label='Random classifier')
plt.title('ROC Curve')
plt.legend()
plt.show()AUC-ROC: arean under kurvan
AUC-ROC (Area Under the ROC Curve) sammanfattar ROC-kurvan i ett enda tal mellan 0 och 1. AUC = 0.5: inte bättre än slumpen (diagonal linje). AUC = 1.0: perfekt klassificerare (inga falskt positiva resultat vid någon recall-nivå). AUC = 0.0: perfekt omvänd klassificerare — varje förutsägelse är fel (användbart om du vänder på förutsägelserna). En AUC på 0,8 innebär att ett slumpmässigt valt positivt prov 80 % av gångerna får en högre förutsagd sannolikhet än ett slumpmässigt valt negativt prov. AUC är oberoende av tröskeln — det utvärderar kvaliteten på rangordningen av sannolikhetspoängen, inte ett specifikt förutsägelsebeslut.
from sklearn.metrics import roc_auc_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = LogisticRegression(max_iter=10000)
clf.fit(X_tr, y_tr)
proba = clf.predict_proba(X_te)[:, 1]
auc = roc_auc_score(y_te, proba)
print(f'AUC-ROC: {auc:.4f}')
# Interpretation: AUC = P(score(pos) > score(neg))
import numpy as np
pos_scores = proba[y_te == 1]
neg_scores = proba[y_te == 0]
mc_auc = np.mean([p > n for p in pos_scores for n in neg_scores])
print(f'Monte Carlo AUC: {mc_auc:.4f}') # Should match roc_auc_scoreTolka AUC-värden i praktiken
Riktlinjer för tolkning av AUC: 0,5 = slumpmässig klassificerare, oanvändbar; 0,6–0,7 = dålig, men bättre än slumpen; 0,7–0,8 = godtagbar — tillräcklig för vissa användningsområden; 0,8–0,9 = bra — en stabil produktionsmodell; 0,9–1,0 = utmärkt — sannolikt nära den bästa tillgängliga nivån för problemet. Var uppmärksam på uppblåsta AUC-värden: tidsmässigt dataläckage (användning av framtida information), etikettläckage eller mycket obalanserade klasser kan artificiellt höja AUC. Gör alltid en rimlighetskontroll med kalibreringskurvor och genom att granska förutsägelser för specifika exempel.
# AUC interpretation guide
auc_guide = [
(0.50, 0.60, 'Random to poor'),
(0.60, 0.70, 'Poor but predictive'),
(0.70, 0.80, 'Fair'),
(0.80, 0.90, 'Good'),
(0.90, 1.00, 'Excellent'),
]
for low, high, label in auc_guide:
print(f'AUC [{low:.2f}, {high:.2f}): {label}')
# Note: domain matters -- AUC 0.75 might be excellent
# for predicting disease 10 years in advance but poor
# for predicting email spam from clear signalsJämföra flera modeller med ROC-kurvan
Om flera ROC-kurvor visas i samma diagram blir det möjligt att jämföra modellerna direkt. Varje modells kurva och AUC-värde visas tillsammans. En modell är bättre om dess ROC-kurva ligger konsekvent ovanför en annan kurva vid varje FPR. Om kurvorna korsar varandra dominerar ingen av modellerna – den ena är bättre vid låga falskt positiva frekvenser och den andra vid höga falskt positiva frekvenser, och verksamhetens sammanhang avgör vilken som är att föredra. En jämförelse av AUC ger en snabb sammanfattning, men kontrollera alltid kurvorna vid den driftpunkt som Ni faktiskt avser att använda.
from sklearn.metrics import roc_curve, roc_auc_score
from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
models = [
('Logistic Reg', LogisticRegression(max_iter=1000)),
('Decision Tree', DecisionTreeClassifier(max_depth=5)),
('KNN', KNeighborsClassifier(n_neighbors=5)),
]
for name, model in models:
model.fit(StandardScaler().fit_transform(X_tr) if name!='Decision Tree' else X_tr, y_tr)
proba = model.predict_proba(X_te)[:, 1]
fpr, tpr, _ = roc_curve(y_te, proba)
auc = roc_auc_score(y_te, proba)
plt.plot(fpr, tpr, label=f'{name} (AUC={auc:.3f})')
plt.plot([0,1],[0,1],'k--')
plt.legend()
plt.show()Precision–recall-kurvan: bättre för obalanserade data
För kraftigt obalanserade dataset kan ROC-kurvan ge en missvisande positiv bild. När det finns mycket få positiva exempel (till exempel en bedrägerifrekvens på 1 %) får även en modell med många falskt positiva resultat en låg FPR, eftersom nämnaren (TN+FP) är mycket stor. Precision–recall-kurvan visar precision mot recall vid olika tröskelvärden och påverkas inte av klassobalans. Arean under PR-kurvan (Average Precision, AP) är ett bättre sammanfattande mått för obalanserade problem. Använd ROC för balanserade klasser och precision–recall-kurvan för obalanserade klasser.
from sklearn.metrics import PrecisionRecallDisplay, average_precision_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
X, y = load_breast_cancer(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = LogisticRegression(max_iter=10000)
clf.fit(X_tr, y_tr)
proba = clf.predict_proba(X_te)[:, 1]
ap = average_precision_score(y_te, proba)
print(f'Average Precision (AP): {ap:.4f}')
PrecisionRecallDisplay.from_estimator(clf, X_te, y_te)
plt.title(f'Precision-Recall Curve (AP={ap:.3f})')
plt.show()AUC vid korsvalidering
Om Ni vill få en tillförlitlig AUC-uppskattning som inte påverkas av en enda uppdelning i tränings- och testdata kan Ni använda cross_val_score med scoring='roc_auc'. Detta beräknar AUC på valideringsmängden i varje fold och returnerar poängen för alla foldar. Medelvärdet är den bästa uppskattningen, medan standardavvikelsen visar stabiliteten. Högt medelvärde för AUC och låg standardavvikelse tyder på en robust modell. Hög AUC tillsammans med hög standardavvikelse tyder på att modellen är känslig för vilka observationer som hamnar i respektive fold – överväg om datan har naturliga grupperingar (till exempel flera observationer per patient) som bör hållas samman i foldarna.
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
X, y = load_breast_cancer(return_X_y=True)
pipe = Pipeline([
('sc', StandardScaler()),
('clf', LogisticRegression(max_iter=1000))
])
aucs = cross_val_score(pipe, X, y, cv=10, scoring='roc_auc')
print(f'AUC per fold: {aucs.round(3)}')
print(f'Mean AUC: {aucs.mean():.4f}')
print(f'Std AUC: {aucs.std():.4f}')Fastställa en driftpunkt på ROC-kurvan
När Ni har utvärderat en modell med ROC-kurvan måste Ni välja en specifik driftpunkt (ett tröskelvärde) för användning i produktion. Tre strategier: (1) Youdens J-statistik: välj det tröskelvärde som maximerar (TPR - FPR) – den punkt som ligger längst ovanför diagonalen. (2) Verksamhetsbegränsning: ange en högsta tillåten FPR (till exempel att högst 5 % av legitima transaktioner får flaggas som bedrägerier) och hitta motsvarande tröskelvärde. (3) Kostnadsoptimering: om Ni känner till kostnaden för FP och FN väljer Ni det tröskelvärde som minimerar den totala kostnaden. Dokumentera det valda tröskelvärdet tillsammans med modellen för att möjliggöra reproducerbar driftsättning.
from sklearn.metrics import roc_curve
import numpy as np
fpr, tpr, thresholds = roc_curve(y_te, proba)
# Strategy 1: Youden's J (max TPR - FPR)
youden_j = tpr - fpr
best_idx = np.argmax(youden_j)
best_threshold = thresholds[best_idx]
print(f'Youden threshold: {best_threshold:.3f}')
print(f'TPR={tpr[best_idx]:.3f}, FPR={fpr[best_idx]:.3f}')
# Strategy 2: Max TPR with FPR <= 0.05
allowed_fpr = 0.05
mask = fpr <= allowed_fpr
idx = np.where(mask)[0][-1] # Highest TPR satisfying FPR constraint
print(f'\nAt FPR<={allowed_fpr}: TPR={tpr[idx]:.3f}, threshold={thresholds[idx]:.3f}')ROC-AUC för flerk lassklassificering
För klassificering med flera klasser utökas ROC-AUC genom att AUC beräknas för varje klass i en One-vs-Rest-konfiguration (OvR): behandla klass k som positiv och alla andra som negativa, beräkna AUC och ta sedan medelvärdet över klasserna. Scikit-learn's roc_auc_score stöder detta med multi_class='ovr' och average='macro' eller average='weighted'. Detta kräver sannolikhetsuppskattningar från predict_proba(), så klassificeraren måste stödja sannolikhetsutdata. Macro AUC behandlar alla klasser lika, medan viktad AUC tar hänsyn till klassernas frekvens.
from sklearn.metrics import roc_auc_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, random_state=42)
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_tr, y_tr)
proba_all = clf.predict_proba(X_te) # Shape: (n_samples, n_classes)
auc_macro = roc_auc_score(y_te, proba_all, multi_class='ovr', average='macro')
auc_weighted = roc_auc_score(y_te, proba_all, multi_class='ovr', average='weighted')
print(f'Macro AUC (OvR): {auc_macro:.4f}')
print(f'Weighted AUC (OvR): {auc_weighted:.4f}')AUC för obalanserade dataset: en varning
AUC-ROC kan ge en missvisande positiv bild för kraftigt obalanserade dataset. När endast 0,1 % av transaktionerna är bedrägerier kan även en modell som upptäcker 80 % av bedrägerifallen och flaggar 5 % av de legitima transaktionerna uppnå en AUC nära 0,9 – men i absoluta tal innebär flaggning av 5 % av miljontals legitima transaktioner en enorm driftskostnad. I sådana fall är AUC-PR (arean under precision–recall-kurvan) mer informativ, eftersom måttet enbart fokuserar på resultatet för den positiva klassen och inte blåses upp av det stora antalet sant negativa resultat. Vid extrem obalans (<1 % positiva exempel) ska Ni alltid rapportera AUC-PR tillsammans med AUC-ROC.
from sklearn.metrics import roc_auc_score, average_precision_score
from sklearn.linear_model import LogisticRegression
import numpy as np
np.random.seed(42)
# Extremely imbalanced: 1% positive rate
n_neg, n_pos = 9900, 100
X = np.vstack([np.random.randn(n_neg, 5),
np.random.randn(n_pos, 5) + 1.5])
y = np.array([0]*n_neg + [1]*n_pos)
clf = LogisticRegression(class_weight='balanced', max_iter=1000)
clf.fit(X, y)
proba = clf.predict_proba(X)[:, 1]
auc_roc = roc_auc_score(y, proba)
auc_pr = average_precision_score(y, proba)
print(f'AUC-ROC: {auc_roc:.4f} (looks great!)')
print(f'AUC-PR: {auc_pr:.4f} (more honest about minority class)')Snabbtest
Testa Era kunskaper om begrepp inom Machine Learning med Python från den här lektionen.
Sammanfattning av lektionen
I den här lektionen har Ni lärt Er att ROC-kurvan visar TPR mot FPR över alla tröskelvärden och hela intervallet av avvägningar mellan precision och recall, att AUC-ROC sammanfattar rangordningskvaliteten i ett enda tal där 0,5 = slumpmässigt och 1,0 = perfekt, samt att Ni för obalanserade klasser bör använda precision–recall-kurvan och Average Precision i stället. Nästa avsnitt handlar om regressionsmått, däribland MAE, MSE, RMSE och R-squared.
Lär dig Python med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 30
- Lektioner
- 120
Vanliga frågor
Är lektionen ”ROC-kurvor och AUC-ROC” gratis?
Ja – hela texten till ”ROC-kurvor och AUC-ROC” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Machine Learning Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Machine Learning Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”ROC-kurvor och AUC-ROC”?
Ni kommer att rita ROC-kurvan genom att variera beslutströskeln, beräkna AUC och tolka det som sannolikheten att ett slumpmässigt positivt exempel rangordnas högre än ett slumpmässigt negativt. Ni övar på Machine Learning Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Machine Learning Academy?
Du behöver inga förkunskaper. Utbildningen i Machine Learning Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.
Hur lång tid tar lektionen ”ROC-kurvor och AUC-ROC”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Machine Learning Academy-lektionen?
Ja. Varje Machine Learning Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Klassificeringsmått: accuracy, precision, recall och F1
- ROC-kurvor och AUC-ROC
- Regressionsmått: MAE, MSE, RMSE och R-kvadrat
- Välj rätt mått för ert affärsproblem