Precision, recall og F1-score i praksis
Beregn precision og recall, forstå afvejningen mellem precision og recall, og vælg det rette mål til ubalancerede opgaver fra den virkelige verden.
Precision, recall og F1-score i praksis er en gratis Machine Learning Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Machine Learning Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Rammeværket for precision og recall
Når klasserne er ubalancerede, eller når forskellige fejltyper har forskellige omkostninger, har vi brug for mål, der specifikt fokuserer på, hvordan modellen håndterer den positive klasse. Precision og recall er de to komplementære mål, der udfylder denne rolle.
Tilsammen giver precision og recall et komplet billede af klassifikatorens adfærd for den positive klasse uden at blive forvrænget af et stort antal true negatives. Det er særligt vigtigt inden for svindelregistrering, sygdomsscreening og indholdsmoderation — områder, hvor den positive klasse er sjælden, men kritisk.
Precision: Kvaliteten af positive forudsigelser
Precision besvarer spørgsmålet: Af alle de eksempler, som modellen forudsagde som positive, hvor stor en andel var faktisk positive?
Precision = TP / (TP + FP)
Høj precision betyder få falske alarmer. Et spamfilter med precision 0,99 betyder, at 99 % af de e-mails, der sendes til spam-mappen, faktisk er spam — meget få legitime e-mails klassificeres forkert. Precision siger dog ikke noget om, hvor mange ægte spam-e-mails der blev overset. En model, der kun markerer én e-mail som spam, og hvor denne e-mail faktisk er spam, har precision 1,0, selv hvis den overså tusindvis af spam-e-mails.
from sklearn.metrics import precision_score
from sklearn.metrics import confusion_matrix
import numpy as np
y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0])
y_pred = np.array([1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0])
cm = confusion_matrix(y_true, y_pred)
TN, FP, FN, TP = cm.ravel()
precision_manual = TP / (TP + FP)
precision_sklearn = precision_score(y_true, y_pred)
print(f'TP={TP}, FP={FP}, FN={FN}, TN={TN}')
print(f'Precision (manual): {precision_manual:.3f}')
print(f'Precision (sklearn): {precision_sklearn:.3f}')Recall: Dækning af faktiske positive
Recall (også kaldet sensitivitet eller true positive rate) besvarer spørgsmålet: Af alle de faktisk positive eksempler, hvor stor en andel identificerede modellen korrekt?
Recall = TP / (TP + FN)
Høj recall betyder få oversete positive eksempler. En kræftscreeningstest med recall 0,95 finder 95 % af de patienter, der faktisk har kræft — kun 5 % bliver overset. Recall siger dog ikke noget om, hvor mange raske patienter der fejlagtigt blev markeret. Høj recall er afgørende, når omkostningen ved at overse et positivt tilfælde (False Negative) er meget høj.
from sklearn.metrics import recall_score
import numpy as np
y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0])
y_pred = np.array([1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0])
TP = ((y_pred == 1) & (y_true == 1)).sum()
FN = ((y_pred == 0) & (y_true == 1)).sum()
recall_manual = TP / (TP + FN)
recall_sklearn = recall_score(y_true, y_pred)
print(f'TP={TP}, FN={FN}')
print(f'Recall (manual): {recall_manual:.3f}')
print(f'Recall (sklearn): {recall_sklearn:.3f}')Afvejningen mellem precision og recall
Precision og recall står i et modsætningsforhold. Du kan altid øge recall til 1,0 ved at forudsige positiv for hvert eneste eksempel — men precision falder sammen, fordi de fleste af disse forudsigelser er false positives. Omvendt forbedrer det precision, hvis du kun forudsiger positiv, når du er ekstremt sikker (meget høj tærskel), men du overser mange ægte positive eksempler, hvilket reducerer recall.
Når du flytter beslutningstærsklen, ændrer du balancen. Hvis du sænker tærsklen, markeres flere eksempler som positive: recall stiger, og precision falder. Hvis du hæver tærsklen, bliver modellen mere selektiv: precision stiger, og recall falder. I de fleste virkelige problemer findes der ingen tærskel, der maksimerer begge dele samtidig.
from sklearn.metrics import precision_score, recall_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import numpy as np
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
X_train_s = StandardScaler().fit_transform(X_train)
X_test_s = StandardScaler().fit_transform(X_test)
model = LogisticRegression(max_iter=1000)
model.fit(X_train_s, y_train)
scores = model.predict_proba(X_test_s)[:, 1]
for threshold in [0.3, 0.5, 0.7, 0.9]:
y_pred = (scores >= threshold).astype(int)
p = precision_score(y_test, y_pred, zero_division=0)
r = recall_score(y_test, y_pred, zero_division=0)
print(f'Threshold {threshold}: Precision={p:.3f} Recall={r:.3f}')F1-score: Afvejning af precision og recall
F1-score kombinerer precision og recall i ét tal ved hjælp af det harmoniske gennemsnit:
F1 = 2 × (Precision × Recall) / (Precision + Recall)
Det harmoniske gennemsnit straffer ekstreme ubalancer: En model med precision 0,9 og recall 0,1 får F1 = 2×0,9×0,1/1,0 = 0,18, ikke 0,5. Derfor er F1 langt sværere at manipulere med end et simpelt gennemsnit. F1 = 1,0 kun når både precision og recall er 1,0.
from sklearn.metrics import f1_score
import numpy as np
# Compare two classifiers
clf_a_prec, clf_a_rec = 0.9, 0.5 # high precision, low recall
clf_b_prec, clf_b_rec = 0.7, 0.7 # balanced
def f1_from_pr(precision, recall):
return 2 * precision * recall / (precision + recall)
f1_a = f1_from_pr(clf_a_prec, clf_a_rec)
f1_b = f1_from_pr(clf_b_prec, clf_b_rec)
print(f'Classifier A: P={clf_a_prec} R={clf_a_rec} F1={f1_a:.3f}')
print(f'Classifier B: P={clf_b_prec} R={clf_b_rec} F1={f1_b:.3f}')
print('\nClassifier B has better F1 despite lower precision.')F-beta-score: Vægtning af precision og recall
F1-score behandler precision og recall som lige vigtige. Fβ-score giver dig mulighed for at vægte recall β gange højere end precision:
Fβ = (1 + β²) × Precision × Recall / (β² × Precision + Recall)
- β = 1: standard-F1 (samme vægt)
- β = 2 (F2): recall er dobbelt så vigtig — bruges til kræftscreening, hvor det er kritisk at undgå at overse et tilfælde
- β = 0,5 (F0.5): precision er dobbelt så vigtig — bruges til spamfiltre, hvor falske alarmer er kostbare
from sklearn.metrics import fbeta_score
import numpy as np
y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 1, 0])
y_pred = np.array([1, 0, 1, 0, 1, 0, 1, 0, 0, 0])
# beta=1 (F1): equal weight
f1 = fbeta_score(y_true, y_pred, beta=1)
# beta=2: emphasise recall
f2 = fbeta_score(y_true, y_pred, beta=2)
# beta=0.5: emphasise precision
f_half = fbeta_score(y_true, y_pred, beta=0.5)
print(f'F1 (beta=1.0): {f1:.3f}')
print(f'F2 (beta=2.0): {f2:.3f} <- emphasises recall')
print(f'F0.5 (beta=0.5): {f_half:.3f} <- emphasises precision')Precision-recall-kurver
I stedet for at evaluere ved én tærskel afbilder en precision-recall-kurve precision i forhold til recall på tværs af alle mulige tærskler. Kurvens form fortæller dig, hvilken afvejning din model højst kan opnå.
En model med et stort areal under precision-recall-kurven (PR-AUC) er bedre til at finde positive eksempler uden at generere for mange falske alarmer. PR-AUC foretrækkes frem for ROC-AUC, når den positive klasse er sjælden, fordi målet fokuserer på præstationen for minoritetsklassen i stedet for at blive påvirket af den store mængde true negatives.
from sklearn.metrics import precision_recall_curve, average_precision_score
import matplotlib.pyplot as plt
# Get probability scores for positive class
scores = model.predict_proba(X_test_s)[:, 1]
precision_vals, recall_vals, _ = precision_recall_curve(y_test, scores)
ap = average_precision_score(y_test, scores)
plt.plot(recall_vals, precision_vals, 'b-', linewidth=2)
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title(f'Precision-Recall Curve (AP={ap:.3f})')
plt.grid(True, alpha=0.3)
plt.show()Makro-, mikro- og vægtede gennemsnit
Ved klassifikation med flere klasser rapporterer scikit-learn flere typer gennemsnit for precision, recall og F1:
- Makrogennemsnit: beregn målet for hver klasse, og beregn derefter det uvægtede gennemsnit. Behandler alle klasser ens uanset størrelse.
- Vægtet gennemsnit: beregn målet for hver klasse, og beregn derefter gennemsnittet vægtet efter antallet af eksempler i hver klasse. Genspejler datasættets samlede præstation.
- Mikrogennemsnit: læg TP/FP/FN sammen på tværs af alle klasser, og beregn derefter målet. For accuracy er dette lig med den samlede accuracy.
from sklearn.metrics import classification_report
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
clf = DecisionTreeClassifier(max_depth=4)
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(classification_report(y_test, y_pred,
target_names=['setosa', 'versicolor', 'virginica']))Vælg det rigtige mål til dit problem
En beslutningsramme til valg af mål:
- Balancerede klasser, samme omkostning ved fejl → Accuracy
- Ubalancerede klasser, høj omkostning ved FP → Precision (f.eks. et spamfilter — undgå at smide gode e-mails væk)
- Ubalancerede klasser, høj omkostning ved FN → Recall (f.eks. sygdomsscreening — undgå at overse syge patienter)
- Både FP og FN er kostbare, og du har brug for ét mål → F1
- FN er langt dyrere end FP → F2 (kræftregistrering, svindel, hvor du kan undersøge sagerne)
- Du skal evaluere på tværs af alle tærskler → PR-AUC eller ROC-AUC
Specificity og den komplette forvekslingsmatrix
To yderligere mål fuldender billedet af en binær klassifikators præstation:
- Specificity (True Negative Rate) = TN / (TN + FP): Af alle de faktisk negative eksempler, hvor stor en andel identificerede modellen korrekt? Høj specificitet betyder få falske alarmer. Bruges sammen med sensitivitet (recall) i medicinske tests.
- Fall-out (False Positive Rate) = FP / (FP + TN): det modsatte af specificitet. Det er x-aksen i ROC-kurven, som du skal studere i lektionen om evalueringsmål.
import numpy as np
from sklearn.metrics import confusion_matrix
y_true = np.array([1, 0, 1, 1, 0, 0, 1, 0, 1, 0])
y_pred = np.array([1, 0, 1, 0, 1, 0, 1, 0, 0, 0])
cm = confusion_matrix(y_true, y_pred)
TN, FP, FN, TP = cm.ravel()
sensitivity = TP / (TP + FN) # recall
specificity = TN / (TN + FP)
fpr = FP / (FP + TN) # false positive rate
print(f'Sensitivity (Recall): {sensitivity:.3f}')
print(f'Specificity (TNR): {specificity:.3f}')
print(f'False Positive Rate: {fpr:.3f}')
print(f'Sensitivity + Specificity should be > 1 for a useful model')Klassifikationsrapport med brugerdefinerede tærskler
Standardtærsklen på 0,5 er ikke altid optimal. En fremgangsmåde til at finde den bedste tærskel er at beregne precision, recall og F1 ved mange tærskler og derefter vælge den tærskel, der maksimerer det mål, som er relevant for dit problem.
I et scenarie med svindelregistrering vil du måske maksimere F2 for at prioritere recall. I et system til indholdsmoderation vil du måske maksimere precision for at undgå fejlagtigt at fjerne legitimt indhold. Funktionen precision_recall_curve giver dig alle de data, du skal bruge til denne analyse.
import numpy as np
from sklearn.metrics import precision_recall_fscore_support
scores = model.predict_proba(X_test_s)[:, 1]
thresholds = np.arange(0.1, 0.95, 0.05)
best_f1, best_threshold = 0, 0.5
for t in thresholds:
y_pred = (scores >= t).astype(int)
p, r, f, _ = precision_recall_fscore_support(y_test, y_pred, average='binary', zero_division=0)
if f > best_f1:
best_f1, best_threshold = f, t
print(f't={t:.2f}: P={p:.3f} R={r:.3f} F1={f:.3f}')
print(f'\nBest F1={best_f1:.3f} at threshold={best_threshold:.2f}')Hurtigt tjek
Test din forståelse af begreberne inden for Machine Learning with Python fra denne lektion.
Opsummering af lektionen
I denne lektion har du lært: at precision måler kvaliteten af positive forudsigelser (TP/(TP+FP)), at recall måler dækningen af faktiske positive eksempler (TP/(TP+FN)), og at det harmoniske gennemsnit F1-score afvejer begge — mens Fβ giver dig mulighed for at vægte recall eller precision højere baseret på din applikations omkostningsstruktur for fejl. Som det næste tager vi fat på det grundlæggende spørgsmål om modelevaluering: hvorfor du ikke kan evaluere en model på de data, den blev trænet på, og hvordan du korrekt estimerer generaliseringspræstation med testmængder, der er holdt ude.
Lær Python med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 30
- Lektioner
- 120
Ofte stillede spørgsmål
Er lektionen “Precision, recall og F1-score i praksis” gratis?
Ja — hele teksten til “Precision, recall og F1-score i praksis” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Machine Learning Academy-kurset, skal du opgradere til CoddyKit PRO. Machine Learning Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Precision, recall og F1-score i praksis”?
Beregn precision og recall, forstå afvejningen mellem precision og recall, og vælg det rette mål til ubalancerede opgaver fra den virkelige verden. Du øver dig i Machine Learning Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Machine Learning Academy?
Der kræves ingen tidligere erfaring. Machine Learning Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Precision, recall og F1-score i praksis”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Machine Learning Academy-lektion?
Ja. Alle Machine Learning Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Fra regression til klassifikation: Beslutninger med tærskler
- Logistisk regression og sigmoidfunktionen
- Forvirringsmatricen forklaret
- Precision, recall og F1-score i praksis