DataLens

Metrik klasifikasi: accuracy, precision, recall, F1

Hitung true dan false positive, hitung precision, recall dan F1 secara manual dan dengan scikit-learn, dan pilih metrik yang sesuai dengan biaya bisnisnya.

Level: Menengah · 7 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Idenya

"Modelnya 80% akurat" terdengar bagus, sampai kamu ingat bahwa memprediksi "tidak ada yang churn" sudah 66,5% akurat di data ini, dan bahwa model penipuan bisa 99% akurat sambil tidak menangkap satu penipuan pun. Akurasi memperlakukan setiap kesalahan sama. Dalam bisnis, kesalahan punya biaya yang berbeda:

Untuk melihat pertukarannya, hitung keempat kemungkinan hasilnya.

Empat hasil

Untuk kelas "positif" (churned = 1):

diprediksi churndiprediksi bertahan
sebenarnya churnTP true positive: tertangkapFN false negative: terlewat
sebenarnya bertahanFP false positive: alarm palsuTN true negative: dengan benar dibiarkan
import numpy as np
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

churn = pd.read_csv("churn.csv")
FEATURES = ["tenure_months", "orders_90d", "days_since_last_order", "support_tickets", "app_user"]
X_train, X_test, y_train, y_test = train_test_split(
    churn[FEATURES], churn["churned"], test_size=0.25, random_state=42, stratify=churn["churned"])
model = LogisticRegression(max_iter=1000).fit(X_train, y_train)

y_true = y_test.to_numpy()
y_pred = model.predict(X_test)
tp = int(((y_pred == 1) & (y_true == 1)).sum())
fp = int(((y_pred == 1) & (y_true == 0)).sum())
fn = int(((y_pred == 0) & (y_true == 1)).sum())
tn = int(((y_pred == 0) & (y_true == 0)).sum())
print(tp, fp, fn, tn)
24 11 9 56

Precision dan recall

Dua pertanyaan, dua metrik:

precision = tp / (tp + fp)
recall = tp / (tp + fn)
accuracy = (tp + tn) / len(y_true)
print(round(precision, 3), round(recall, 3), round(accuracy, 3))
0.686 0.727 0.8

Keduanya menarik ke arah yang berlawanan. Turunkan ambangnya dan kamu menandai lebih banyak orang: recall naik (kamu menangkap lebih banyak customer churn), precision turun (lebih banyak alarm palsu). Naikkan ambangnya dan kebalikannya terjadi.

probs = model.predict_proba(X_test)[:, 1]
for threshold in [0.2, 0.35, 0.5, 0.65, 0.8]:
    pred = (probs >= threshold).astype(int)
    tp_t = ((pred == 1) & (y_true == 1)).sum()
    p = tp_t / max(pred.sum(), 1)
    r = tp_t / y_true.sum()
    print(f"{threshold:.2f}  precision {p:.2f}  recall {r:.2f}")
0.20  precision 0.53  recall 0.97
0.35  precision 0.69  recall 0.88
0.50  precision 0.69  recall 0.73
0.65  precision 0.79  recall 0.58
0.80  precision 0.87  recall 0.39

F1: satu angka untuk keduanya

Saat kamu butuh satu angka yang menyeimbangkan keduanya, skor F1 adalah rata-rata harmonisnya:

F1 = 2 × precision × recall / (precision + recall)

Rata-rata harmonis menghukum ketidakseimbangan: precision 1,0 dengan recall 0,1 menghasilkan F1 0,18, bukan 0,55. F1 hanya tinggi saat keduanya lumayan.

Dengan scikit-learn

Kamu sudah menghitung setiap metrik secara manual dari empat hitungan itu, dan itulah cara terbaik untuk memahaminya. Dalam praktiknya, scikit-learn menghitungnya untukmu, dan classification_report mencetak ringkasan lengkap dalam satu panggilan:

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, classification_report

print(round(precision_score(y_true, y_pred), 3), round(recall_score(y_true, y_pred), 3), round(f1_score(y_true, y_pred), 3))
print(classification_report(y_true, y_pred, target_names=["stayed", "churned"]))
0.686 0.727 0.706
              precision    recall  f1-score   support

      stayed       0.86      0.84      0.85        67
     churned       0.69      0.73      0.71        33

    accuracy                           0.80       100
   macro avg       0.77      0.78      0.78       100
weighted avg       0.80      0.80      0.80       100

classification_report menampilkan precision, recall dan F1 untuk setiap kelas, ditambah jumlah contohnya (support). Baca baris kelas yang kamu pedulikan, biasanya yang lebih jarang.

Urutan argumen itu penting: metrik menerima (y_true, y_pred). Menukarnya diam-diam menukar precision dan recall.

Memilih metriknya

SituasiPrioritaskanKenapa
voucher retensi murah, customer berhargarecallmelewatkan customer churn lebih mahal daripada voucher yang terbuang
tim sales menelepon setiap lead yang ditandai (mahal)precisionsetiap alarm palsu membuang waktu seseorang
pemeriksaan penipuan yang memblokir pembayaranprecision dan recall, ditimbang berdasarkan biayamemblokir customer yang baik dan melewatkan penipuan sama-sama merugikan
kelas seimbang, biaya samaakurasi tidak masalah
Ide utama

Tentukan berapa biaya sebuah false positive dan false negative dalam situasimu, lalu pilih metrik (dan ambang) yang mencerminkannya. Jangan pernah melaporkan akurasi saja pada data yang tidak seimbang.

Mengapa ini penting untuk kode yang bersih

Metrik adalah kontrak antara sebuah model dan bisnisnya. Tuliskan metrik dan ambang yang dipilih, beserta alasannya, di samping kode yang menghitungnya. Saat model dilatih ulang, fungsi yang sama menilainya dengan cara yang sama, dan tidak ada yang bisa diam-diam beralih ke angka yang lebih menyanjung.

Rangkuman

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.