Model regresi yang sudah dilatih menghasilkan angka, tetapi angka itu belum berkata apa-apa sampai kita mengukur seberapa jauh prediksi melenceng dari kenyataan. Untuk itu kita membutuhkan metrik evaluasi regresi — rumus yang meringkas seluruh galat menjadi satu angka yang bisa dibandingkan antar model. Chapter ini membedah empat metrik standar (MAE, MSE, RMSE, R²) dari definisinya, menghitung masing-masing dua kali — manual dengan NumPy dan lewat sklearn.metrics — lalu menjalankan satu eksperimen kecil yang menjelaskan mengapa pilihan metrik bukan urusan selera: melipatduakan satu galat besar ternyata menggerakkan tiap metrik dengan kekuatan yang sangat berbeda.

Empat Metrik dan Pertanyaan Masing-masing #

Misalkan yᵢ adalah nilai aktual dan ŷᵢ prediksi model; galat tiap sampel adalah selisihnya. Keempat metrik dihitung sebagai berikut:

text
MAE  = (1/n) * Σ |yᵢ - ŷᵢ|
MSE  = (1/n) * Σ (yᵢ - ŷᵢ)²
RMSE = akar(MSE)
R²   = 1 - SSE/SST   dengan   SSE = Σ (yᵢ - ŷᵢ)²   dan   SST = Σ (yᵢ - ȳ)²

MAE (mean absolute error) menjawab “rata-rata prediksi meleset berapa?” dalam satuan yang sama dengan target — juta rupiah kalau targetnya harga rumah. MSE (mean squared error) mengkuadratkan galat lebih dulu, sehingga galat besar dihukum jauh lebih berat; satuannya menjadi kuadrat (juta kuadrat) dan angkanya sulit dibaca manusia, tetapi sifat diferensiabelnya membuat MSE cocok sebagai fungsi loss saat training. RMSE (root mean squared error, akar MSE) mengembalikan satuan ke bentuk aslinya sambil mempertahankan kepekaan terhadap galat besar — kompromi yang menjadikannya metrik laporan paling populer. Terakhir R² (koefisien determinasi) membaca hal yang berbeda sama sekali: berapa bagian variasi target yang berhasil dijelaskan model, dibandingkan tebakan naif yang selalu memakai rerata ȳ.

R² punya jangkar yang membuatnya mudah dibaca: tebakan naif “selalu prediksi rerata” bernilai tepat 0, dan model sempurna bernilai 1. Konsekuensinya jarang disadari pemula: R² bisa negatif. Prediksi yang lebih buruk daripada sekadar menebak rerata akan menghasilkan SSE lebih besar daripada SST, dan 1 − SSE/SST jatuh di bawah nol — penanda kuat bahwa model (atau data latihnya) bermasalah serius.

MetrikSatuanSensitivitas pencilanKekuatan utama
MAESama dengan targetRendah — tahan bantingKomunikasi ke pemangku kepentingan
MSEKuadrat satuan targetTinggi — kuadrat galatFungsi loss saat training, optimasi
RMSESama dengan targetTinggi — setara MSELaporan akurasi yang mudah dibaca
R²Tanpa satuan (0–1, bisa negatif)Tinggi lewat SSEPerbandingan relatif antar target

Contoh Kode: Manual vs sklearn.metrics #

File metrik-regresi.py memakai delapan prediksi harga rumah — tujuh prediksi hanya meleset ±5 sampai ±10 juta, satu rumah meleset +120 juta (prediksi 760, terjual 640). Kita menghitung keempat metrik dari rumus mentahnya, membandingkannya dengan hasil sklearn.metrics, lalu melipatduakan galat rumah terakhir menjadi +240 juta dan mengamati efeknya pada tiap metrik.

python
# Metrik evaluasi regresi: MAE, MSE, RMSE, dan R^2 dihitung manual dengan
# NumPy lalu dibandingkan dengan sklearn.metrics -- angkanya identik.

import numpy as np
from sklearn.metrics import (
    mean_absolute_error,
    mean_squared_error,
    r2_score,
    root_mean_squared_error,
)

# Delapan prediksi harga rumah (juta rupiah) vs harga terjual sesungguhnya.
# Rumah terakhir sengaja diberi galat besar: prediksi 760, terjual 640.
y_aktual = np.array([350.0, 420.0, 510.0, 480.0, 620.0, 590.0, 710.0, 640.0])
y_prediksi = np.array([355.0, 415.0, 505.0, 470.0, 625.0, 580.0, 705.0, 760.0])


def metrik_manual(y_a, y_p):
    """Hitung keempat metrik regresi dari definisinya."""
    galat = y_p - y_a
    mae = np.mean(np.abs(galat))
    mse = np.mean(galat**2)
    rmse = np.sqrt(mse)
    sse = np.sum(galat**2)
    sst = np.sum((y_a - y_a.mean()) ** 2)
    r2 = 1.0 - sse / sst
    return mae, mse, rmse, r2


# Bagian 1: rumus manual vs sklearn.metrics pada data yang sama.
mae_m, mse_m, rmse_m, r2_m = metrik_manual(y_aktual, y_prediksi)
print("Perbandingan metrik manual vs sklearn.metrics:")
print(f"{'metrik':<7} {'manual':>12} {'scikit-learn':>14}")
print(f"{'MAE':<7} {mae_m:>12.3f} {mean_absolute_error(y_aktual, y_prediksi):>14.3f}")
print(f"{'MSE':<7} {mse_m:>12.3f} {mean_squared_error(y_aktual, y_prediksi):>14.3f}")
print(f"{'RMSE':<7} {rmse_m:>12.3f} {root_mean_squared_error(y_aktual, y_prediksi):>14.3f}")
print(f"{'R2':<7} {r2_m:>12.3f} {r2_score(y_aktual, y_prediksi):>14.3f}")
print()

# Bagian 2: galat besar pada rumah terakhir dilipatduakan (+120 -> +240),
# enam galat kecil lainnya tidak disentuh.
y_prediksi_2 = y_prediksi.copy()
y_prediksi_2[-1] = 880.0
mae_2, mse_2, rmse_2, r2_2 = metrik_manual(y_aktual, y_prediksi_2)
print("Satu galat besar dilipatduakan (+120 menjadi +240):")
print(f"  MAE  {mae_m:10.3f} -> {mae_2:10.3f}  ({mae_2 / mae_m:.2f}x)")
print(f"  MSE  {mse_m:10.3f} -> {mse_2:10.3f}  ({mse_2 / mse_m:.2f}x)")
print(f"  RMSE {rmse_m:10.3f} -> {rmse_2:10.3f}  ({rmse_2 / rmse_m:.2f}x)")
print(f"  R2   {r2_m:10.3f} -> {r2_2:10.3f}")
print()

# Bagian 3: R^2 bisa NEGATIF jika prediksi lebih buruk daripada
# tebakan naif "selalu tebak rerata".
y_a_kecil = np.array([10.0, 20.0, 30.0, 40.0, 50.0])
y_p_kecil = np.array([50.0, 10.0, 40.0, 20.0, 30.0])
r2_negatif = r2_score(y_a_kecil, y_p_kecil)
print(f"Prediksi melenceng jauh pada lima titik kecil: R2 = {r2_negatif:.3f}")
print("(negatif berarti lebih buruk daripada menebak rerata)")

Output yang Dihasilkan:

text
Perbandingan metrik manual vs sklearn.metrics:
metrik        manual   scikit-learn
MAE           20.625         20.625
MSE         1840.625       1840.625
RMSE          42.903         42.903
R2             0.857          0.857

Satu galat besar dilipatduakan (+120 menjadi +240):
  MAE      20.625 ->     35.625  (1.73x)
  MSE    1840.625 ->   7240.625  (3.93x)
  RMSE     42.903 ->     85.092  (1.98x)
  R2        0.857 ->      0.437

Prediksi melenceng jauh pada lima titik kecil: R2 = -1.600
(negatif berarti lebih buruk daripada menebak rerata)

Bedah kode di atas baris demi baris:

  1. Baris 4–10 (import): keempat fungsi metrik diimpor dari sklearn.metrics; root_mean_squared_error tersedia sejak scikit-learn 1.4 dan menggantikan kebiasaan lama sqrt(mean_squared_error(...)).
  2. Baris 14–15 (data): dua array sejajar — harga aktual dan harga prediksi. Selisih keduanya, galat, adalah bahan mentah seluruh metrik.
  3. Baris 18–27 (metrik_manual): seluruh rumus pada blok text di atas diterjemahkan baris demi baris: nilai mutlak lalu dirata-rata (MAE), kuadrat lalu dirata-rata (MSE), akar kuadrat (RMSE), dan 1 − SSE/SST (R²).
  4. Baris 31–37 (perbandingan): keempat pasangan angka tercetak berdampingan dan identik hingga desimal ketiga — bukti bahwa pustaka mengeksekusi definisi yang sama, tanpa langkah tersembunyi apa pun.
  5. Baris 42–49 (eksperimen pencilan): hanya elemen terakhir y_prediksi_2[-1] yang diubah dari 760 menjadi 880; galatnya naik dari +120 menjadi +240.
  6. Baris 54–58 (R² negatif): lima titik kecil diprediksi buruk sengaja; r2_score menghasilkan −1,600 — di bawah titik nol rerata.

Membaca Hasil Eksperimen Pencilan #

Hasil bagian kedua adalah pelajaran paling penting chapter ini. Melipatduakan satu galat dari +120 ke +240 menggerakkan MAE dari 20,625 ke 35,625 (naik 1,73x) — kenaikan yang jujur sebanding: satu galat membesar dua kali, rata-rata absolut naik seperdelapan dari selisihnya. Metrik yang sama pada MSE melonjak 3,93x (1.840,625 → 7.240,625), karena kuadrat galat tersebut berubah dari 14.400 ke 57.600 dan mendominasi total. RMSE naik 1,98x, dan R² terjun dari 0,857 ke 0,437 — model yang tadinya menjelaskan 86% variasi harga kini hanya 44% gara-gara satu rumah.

Metrik Hanyalah Awal: Perkenalan Residu #

Satu angka ringkasan menyembunyikan pola. Dua model bisa sama-sama berkata “RMSE 42 juta” sementara model pertama meleset merata di semua harga dan model kedua sangat akurat untuk rumah murah tetapi buruk untuk rumah mahal. Analisis residu — memplot galat = y − ŷ terhadap prediksi atau fitur — membongkar hal semacam ini: pola melengkung menandakan hubungan nonlinier yang belum ditangkap, sebaran yang melebar pada prediksi tinggi menandakan heteroskedastisitas, dan satu titik yang menjauh dari kawanannya adalah kandidat pencilan atau kesalahan data. Kita akan banyak memplot residu saat membangun proyek prediksi harga rumah di akhir Course ini.

Empat metrik ini juga memberi kita alat ukur untuk pertanyaan berikutnya: bagaimana jika hubungan fitur dan target tidak lurus? Regresi linier murni akan menghasilkan galat sistematis yang residunya melengkung — dan obatnya bukan meninggalkan dunia linier, melainkan menambahkan fitur berpangkat. Chapter Regresi Polynomial membahas caranya.

Referensi Resmi #