Model regresi memprediksi angka — harga, suhu, jumlah gelas terjual — dan kualitas prediksinya juga harus diukur dengan angka. Kita tidak bisa hanya berkata “modelnya cukup dekat”; kita perlu satu angka yang menyimpulkan seberapa jauh prediksi meleset, mudah dibandingkan antar model, dan bisa dikomunikasikan ke orang non-teknis. Pada chapter ini kita bedah empat metrik standar evaluasi regresi — MAE, MSE, RMSE, dan R-squared — dari rumusnya, hitungan manualnya, sampai pemakaian praktisnya lewat scikit-learn.

Galat Prediksi dan Rumus Tiga Metrik #

Bahan dasar semua metrik regresi adalah galat (error): selisih antara nilai aktual dan nilai prediksi untuk tiap baris, galat = y_aktual - y_prediksi. Model yang baik menghasilkan galat yang kecil secara konsisten. Tiga metrik pertama kita hanyalah cara berbeda untuk meringkas deretan galat menjadi satu angka:

text
MAE  = (1/n) * Σ |galat|              -> rata-rata besar meleset, satuan sama dengan target
MSE  = (1/n) * Σ galat²               -> rata-rata galat dikuadratkan, satuan ikut terkuadratkan
RMSE = akar(MSE)                      -> akar dari MSE, satuan kembali seperti semula

Ketiganya membingkai pertanyaan yang sama dari sudut berbeda. MAE bertanya “berapa rata-rata jarak melesetnya?” sehingga galat sebesar 10 dihitung apa adanya. MSE dan RMSE mengkuadratkan galat lebih dulu, sehingga galat besar diberi bobot jauh lebih berat: meleset 10 gelas memberi kontribusi 100 pada MSE, sepuluh kali kontribusi sepuluh hari yang masing-masing meleset 1 gelas. RMSE lalu mengembalikan satuan ke bentuk asli dengan pengakaran, supaya angkanya bisa dibaca kembali dalam gelas, rupiah, atau derajat.

Menghitung Manual: Delapan Hari Penjualan #

Sebelum memakai fungsi scikit-learn, kita hitung dulu dengan tangan supaya rumusnya tidak menjadi kotak gelap. Sebuah kedai mencatat penjualan es kopi susu selama delapan hari dan membandingkannya dengan prediksi model:

python
import math

aktual = [52, 48, 61, 45, 55, 49, 58, 47]
prediksi = [50, 51, 58, 44, 53, 52, 55, 48]

galat = [a - p for a, p in zip(aktual, prediksi)]
print("Galat per hari (aktual - prediksi):", galat)

mae = sum(abs(g) for g in galat) / len(galat)
mse = sum(g ** 2 for g in galat) / len(galat)
rmse = math.sqrt(mse)

print("MAE  = %d/%d = %.3f gelas" % (sum(abs(g) for g in galat), len(galat), mae))
print("MSE  = %d/%d = %.3f" % (sum(g ** 2 for g in galat), len(galat), mse))
print("RMSE = akar(%d/%d) = %.3f gelas"
      % (sum(g ** 2 for g in galat), len(galat), rmse))

Output yang Dihasilkan:

text
Galat per hari (aktual - prediksi): [2, -3, 3, 1, 2, -3, 3, -1]
MAE  = 18/8 = 2.250 gelas
MSE  = 46/8 = 5.750
RMSE = akar(46/8) = 2.398 gelas

Mari kita telaah baris-baris kode di atas:

  1. Baris galat = ...: list comprehension mengurangkan prediksi dari aktual per hari. Tanda minus muncul ketika model meramal terlalu tinggi — arah melesetnya berbeda, tetapi besarnya sama-sama penting.
  2. Baris mae = ...: abs() membuat seluruh galat positif supaya galat +2 dan -2 tidak saling menghapus saat dijumlahkan. Total nilai mutlak 18 dibagi 8 hari menghasilkan 2.250 gelas.
  3. Baris mse = ...: pengkuadratan g ** 2 membuat seluruh galat positif sekaligus memperbesar galat besar. Total 46 dibagi 8 menghasilkan 5.750 — satuan “gelas kuadrat” yang tidak punya makna harian.
  4. Baris rmse = ...: math.sqrt() mengembalikan satuan ke gelas. Nilai 2.398 sedikit di atas MAE 2.250 karena galat terbesar (3) menarik RMSE lebih kuat.

Perhatikan hubungan kedua angka: RMSE selalu ≥ MAE, dan keduanya sama persis hanya jika semua galat sama besar. Selisih keduanya adalah sinyal gratis — RMSE yang jauh lebih besar dari MAE menandakan ada beberapa hari dengan meleset yang jauh lebih parah dari rata-rata.

Empat Metrik Sekaligus dari scikit-learn #

Sekarang kita jalankan alur evaluasi utuh yang mengikuti protokol pembagian data dari chapter sebelumnya. Kembali ke kedai yang sama: 30 hari data suhu udara dan penjualan es kopi susu dibangkitkan dengan seed tetap, model LinearRegression dilatih pada 24 hari, lalu diukur pada 6 hari uji:

python
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import (mean_absolute_error, mean_squared_error,
                             root_mean_squared_error, r2_score)
from sklearn.model_selection import train_test_split

rng = np.random.default_rng(42)
suhu = rng.uniform(22, 33, 30)
penjualan = 15 + 6 * (suhu - 22) + rng.normal(0, 7, 30)

X = suhu.reshape(-1, 1)
y = penjualan

X_latih, X_uji, y_latih, y_uji = train_test_split(
    X, y, test_size=0.20, random_state=42
)

model = LinearRegression()
model.fit(X_latih, y_latih)
y_prediksi = model.predict(X_uji)

print("Jumlah data uji:", len(y_uji))
print("MAE  : %.2f gelas" % mean_absolute_error(y_uji, y_prediksi))
print("MSE  : %.2f" % mean_squared_error(y_uji, y_prediksi))
print("RMSE : %.2f gelas" % root_mean_squared_error(y_uji, y_prediksi))
print("R2   : %.2f" % r2_score(y_uji, y_prediksi))

Output yang Dihasilkan:

text
Jumlah data uji: 6
MAE  : 4.48 gelas
MSE  : 29.71
RMSE : 5.45 gelas
R2   : 0.91

Mari kita telaah bagian-bagian kodenya:

  1. Baris rng = ... hingga penjualan = ...: data uji dibangkitkan dari hubungan linear (tiap kenaikan 1 derajat menambah 6 gelas) ditambah derau normal. Seed 42 membuat data ini sama untuk setiap eksekusi, termasuk di mesin pembaca.
  2. train_test_split dengan test_size=0.20: 6 dari 30 hari menjadi data uji. Untuk regresi pada target kontinu, stratify tidak tersedia — stratifikasi hanya bermakna untuk kelas diskret.
  3. Empat fungsi metrik: semuanya menerima pasangan (y_aktual, y_prediksi) dan mengembalikan satu angka. root_mean_squared_error hadir sejak scikit-learn 1.4; pada versi lama orang menghitung np.sqrt(mean_squared_error(...)).
  4. Pembacaan hasil: MAE 4.48 gelas berarti rata-rata prediksi meleset 4-5 gelas per hari. RMSE 5.45 gelas lebih tinggi dari MAE, menandakan ada hari-hari yang meleset jauh. MSE 29.71 adalah 5.45 kuadrat — angka kerja perhitungan, bukan angka komunikasi.

Angka R2 0.91 perlu dibaca dengan cara berbeda dari ketiganya. R-squared membandingkan galat model kita dengan galat model paling naif yang selalu menebak rata-rata: Model yang berhasil menangkap seluruh pola data mendekati 1.0, model yang sama bergunanya dengan menebak rata-rata mendekati 0.0, dan angka 0.91 berarti 91% variasi penjualan di data uji berhasil dijelaskan hubungan suhu-penjualan.

Memilih Metrik yang Tepat #

Empat metrik ini bukan salinan satu sama lain; masing-masing menjawab pertanyaan audiens yang berbeda. Tabel berikut merangkum kapan masing-masing paling layak dipakai:

MetrikSatuanReaksi terhadap galat besarPaling pas untuk
MAESama dengan targetLinearMelaporkan ke manajemen: “rata-rata meleset 4 gelas”
MSETarget kuadratSangat kuatOptimasi matematis, membandingkan model
RMSESama dengan targetKuatMembandingkan model dengan bahasa yang tetap bisa dibaca
R-squaredTanpa satuanTidak langsungMeringkas seberapa jauh model mengalahkan tebakan rata-rata

Dua pertanyaan panduan mempermudah pilihan. Pertama, siapa pembacanya? Untuk laporan bisnis, MAE dan RMSE menang karena satuannya bisa langsung diterjemahkan ke “gelas” atau “rupiah”. Kedua, apakah meleset besar harus dihukum lebih berat? Prediksi stok obat yang meleset 10 unit bukan dua kali lebih buruk dari meleset 5 unit — dampaknya bisa berlipat — sehingga RMSE atau MSE lebih jujur daripada MAE. Untuk data yang memuat lonjakan sesekali (hari besar, promosi), MAE memberi gambaran khas hari biasa, sedangkan RMSE ikut terangkat oleh hari-hari luar biasa itu.

Rangkuman #

  • Semua metrik regresi berdiri di atas galat per baris y_aktual - y_prediksi; yang membedakannya adalah cara meringkas deretan galat tersebut.
  • MAE membaca rata-rata meleset dalam satuan target; MSE mengkuadratkan galat sehingga meleset besar semakin terasa; RMSE mengakarkan MSE agar satuan kembali normal.
  • RMSE selalu lebih besar atau sama dengan MAE; selisih keduanya mengungkap ada galat yang jauh di atas rata-rata.
  • R-squared membandingkan model dengan penebak rata-rata: 1.0 berarti pola tertangkap penuh, 0.0 berarti sama dengan menebak rata-rata.
  • Pilih metrik mengikuti audiens dan biaya kesalahan: MAE untuk bahasa awam, RMSE/MSE saat meleset besar harus diberi bobot lebih berat.

Angka-angka ini menyimpulkan evaluasi regresi, tetapi separuh dunia machine learning memprediksi label, bukan angka. Untuk klasifikasi, “rata-rata meleset” tidak lagi bermakna — yang dihitung adalah prediksi yang tepat sasaran. Kita mulai dari metrik yang paling terkenal sekaligus paling gampang menipu: akurasi, pada chapter Metrik Evaluasi Klasifikasi .

Referensi #

  1. scikit-learn — Model evaluation: regression metrics
  2. scikit-learn — LinearRegression