Precision, Recall, dan F1

Memilih kompromi antara presisi dan cakupan.

Daftar isi

Precision dan recall membedah kualitas prediksi kelas positif secara terpisah, sedangkan F1 merangkum keduanya menjadi satu bilangan. Topik ini menurunkan rumus ketiganya dari sel-sel confusion matrix, menunjukkan trade-off precision dan recall terhadap threshold, yaitu ambang keputusan prediksi positif, serta membahas argumen pos_label dan average pada fungsi metriknya. classification_report digunakan sebagai ringkasan sekali baca. Seluruh contoh menggunakan data tidak seimbang 95:5 yang membuat accuracy terlihat menyesatkan.

Rumus precision dan recall#

Precision mengukur porsi prediksi positif yang benar, sedangkan recall mengukur porsi positif yang tertangkap model. Keduanya diturunkan dari empat sel confusion matrix berikut. Keduanya juga hanya menilai satu sisi, yaitu kelas positif, sehingga selalu dibaca sebagai pasangan dan bukan sebagai dua metrik yang berdiri sendiri.

precision=TPTP+FPrecall=TPTP+FN \text{precision} = \frac{TP}{TP + FP} \qquad \text{recall} = \frac{TP}{TP + FN}

Precision menyatakan seberapa dapat dipercaya setiap prediksi positif, karena penyebutnya mencakup semua sampel yang diprediksi positif, benar maupun salah. Recall menyatakan seberapa luas cakupan model atas kelas positif, karena penyebutnya mencakup semua sampel yang benar-benar positif. Model yang konservatif, misalnya hanya memprediksi positif ketika sangat yakin, cenderung precision tinggi dengan recall rendah. Model yang longgar bergerak ke arah sebaliknya, yaitu recall tinggi dengan banyak FP sehingga precision turun.

Trade-off keduanya dikendalikan oleh threshold. Kebanyakan model klasifikasi mengeluarkan probabilitas melalui predict_proba, sedangkan predict menerapkan threshold 0.5 secara bawaan. Menggeser threshold ke bawah memperbanyak prediksi positif sehingga recall naik, tetapi FP ikut bertambah sehingga precision turun. Geseran sebaliknya membuat model lebih selektif, sehingga precision naik dan recall turun.

Efek threshold pada data 95:5#

Kode berikut menunjukkan trade-off tersebut pada data nyata. Probabilitas positif diambil dari predict_proba, lalu threshold diuji pada tiga nilai dengan prediksi manual, yaitu probabilitas yang bernilai sama atau lebih besar dari threshold dihitung positif. Perbandingan proba >= t digunakan secara manual agar mekanisme threshold terlihat bekerja tanpa bantuan fungsi predict.

python Contoh: precision dan recall pada tiga threshold
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import precision_score, recall_score
from sklearn.model_selection import train_test_split

X, y = make_classification(
    n_samples=600, n_features=6, n_informative=3, n_redundant=0,
    weights=[0.95, 0.05], random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)
proba = model.predict_proba(X_test)[:, 1]

for t in [0.5, 0.3, 0.1]:
    pred = (proba >= t).astype(int)
    print(f"threshold {t:.1f}: precision={precision_score(y_test, pred):.4f}  recall={recall_score(y_test, pred):.4f}")
text Keluaran
threshold 0.5: precision=1.0000  recall=0.1667
threshold 0.3: precision=0.7500  recall=0.5000
threshold 0.1: precision=0.3529  recall=1.0000

Keluaran memperlihatkan trade-off dengan jelas. Pada threshold 0.5, model hanya memprediksi satu sampel positif dan prediksi itu benar, sehingga precision 1.0000 tetapi recall hanya 0.1667. Menurunkan threshold ke 0.3 dan 0.1 memperluas cakupan hingga seluruh enam sampel positif tertangkap pada 0.1, tetapi precision turun ke 0.3529 karena banyak sampel negatif ikut terprediksi positif. Tidak ada threshold yang unggul pada keduanya sekaligus, sehingga pilihannya ditentukan oleh jenis kesalahan yang lebih mahal pada domain yang dipegang.

F1 dan pilihan average#

F1 adalah rata-rata harmonik (harmonic mean) dari precision dan recall, yaitu bentuk rata-rata yang menghukum nilai ekstrem lebih keras daripada rata-rata biasa. Nilai 1.0 berarti kedua sisi sempurna, sedangkan nilai 0 berarti salah satu sisi bernilai nol. Rumusnya adalah sebagai berikut.

F1=2⋅precision×recallprecision+recall F_1 = 2 \cdot \frac{\text{precision} \times \text{recall}}{\text{precision} + \text{recall}}

Bentuk harmonik membuat F1 tinggi hanya bila precision dan recall sama-sama tinggi. Contohnya, precision 1.0 dan recall 0.1667 menghasilkan F1 0.2857, jauh di bawah rata-rata biasa 0.583, karena recall yang sangat rendah dihukum. Fungsi precision_score, recall_score, dan f1_score menerima argumen average yang menentukan cara merangkum banyak kelas. Nilai binary hanya menilai kelas positif, macro menghitung rata-rata polos atas tiap kelas sehingga kelas kecil berbobot sama, sedangkan weighted menimbang tiap kelas dengan supportnya sehingga hasilnya mendekati accuracy. Argumen pos_label menetapkan kelas mana yang dihitung pada mode binary, dengan nilai bawaan 1.

python presisi-recall.py
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, f1_score, precision_score, recall_score
from sklearn.model_selection import train_test_split

X, y = make_classification(
    n_samples=600, n_features=6, n_informative=3, n_redundant=0,
    weights=[0.95, 0.05], random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
model = LogisticRegression(max_iter=1000)
model.fit(X_train, y_train)
pred = model.predict(X_test)

print("precision :", round(precision_score(y_test, pred), 4))
print("recall    :", round(recall_score(y_test, pred), 4))
print("f1 binary :", round(f1_score(y_test, pred), 4))
print("f1 macro  :", round(f1_score(y_test, pred, average="macro"), 4))
print("f1 weighted:", round(f1_score(y_test, pred, average="weighted"), 4))
print()
print(classification_report(y_test, pred))
text Keluaran
precision : 1.0
recall    : 0.1667
f1 binary : 0.2857
f1 macro  : 0.6321
f1 weighted: 0.9439

              precision    recall  f1-score   support

           0       0.96      1.00      0.98       114
           1       1.00      0.17      0.29         6

    accuracy                           0.96       120
   macro avg       0.98      0.58      0.63       120
weighted avg       0.96      0.96      0.94       120

Angka pada keluaran memperlihatkan efek pilihan average. Mode binary mencatat F1 0.2857 untuk kelas 1 yang minoritas, sedangkan mode macro naik ke 0.6321 karena kelas 0 yang hampir sempurna ikut dirata-ratakan dengan bobot sama. Mode weighted mencatat 0.9439 yang tampak mengesankan, padahal angka itu didorong oleh kelas mayoritas. classification_report pada keluaran yang sama merangkum semuanya per kelas, termasuk support 6 untuk kelas 1, sehingga laporan ini layak menjadi keluaran bawaan setiap evaluasi klasifikasi.

Nilai average yang tersedia juga mencakup micro, yaitu perhitungan dengan menjumlahkan TP, FP, dan FN seluruh kelas terlebih dahulu sebelum dibagi. Pada klasifikasi dengan satu label per sampel, F1 micro sama persis dengan accuracy, sehingga mode ini tidak menambah informasi untuk kasus pada modul ini. Pilihan macro dan weighted justru yang sering digunakan pada data tidak seimbang karena keduanya menyoroti perbedaan mutu antarkelas.

Kesalahan umum#

Tiga kesalahan berikut sering muncul saat menggunakan ketiga metrik ini.

  • Melaporkan F1 tanpa menyebut nilai average yang digunakan, sehingga angkanya tidak dapat direproduksi atau dibandingkan. Perbaikannya, sebutkan mode average setiap kali F1 atau F1 makro dilaporkan.
  • Membaca F1 weighted yang tinggi sebagai bukti kelas minoritas terlayani, padahal angka itu didominasi kelas mayoritas. Perbaikannya, baca baris per kelas pada classification_report sebelum menyimpulkan.
  • Menurunkan threshold untuk menaikkan recall tanpa mengukur precision yang turun, atau sebaliknya. Perbaikannya, ukur selalu keduanya pada setiap nilai threshold yang diuji.

Ringkasan#

  • Precision adalah TP dibagi seluruh prediksi positif, sedangkan recall adalah TP dibagi seluruh sampel positif yang sebenarnya.
  • Threshold mengendalikan trade-off keduanya, yaitu threshold rendah menaikkan recall dan menurunkan precision.
  • F1 adalah rata-rata harmonik precision dan recall, dan argumen average menentukan cara merangkum banyak kelas.
  • classification_report menyajikan precision, recall, F1, dan support per kelas dalam satu tabel.

Referensi#