Analisis Residual

Membaca error model dan mengenali asumsi yang dilanggar.

Daftar isi

Angka metrik seperti MSE dan R2R^2 mengatakan seberapa besar model meleset, tetapi tidak mengatakan bagaimana model meleset. Topik ini membahas analisis residual, yaitu pemeriksaan sisa error model untuk mengenali pola yang belum tertangkap dan asumsi yang dilanggar. Karena lingkungan contoh di sini tanpa tampilan grafis, seluruh diagnosis disajikan sebagai statistik tercetak, dan setelah membacanya analisis yang sama dapat diterapkan pada model regresi mana pun.

Definisi residual dan polanya#

Residual adalah selisih nilai aktual dan prediksi untuk satu sampel:

ei=yi−y^i e_i = y_i - \hat{y}_i

Model yang sehat menghasilkan residual yang berperilaku seperti derau, yaitu menyebar acak di sekitar nol dengan penyebaran yang kurang lebih sama di seluruh rentang prediksi. Pola yang menyimpang dari keadaan itu adalah petunjuk masalah model. Residual yang bergaris lengkung menandakan pola data yang tidak tertangkap, misalnya hubungan yang sesungguhnya melengkung sedangkan modelnya garis lurus. Residual yang menyebar makin lebar pada prediksi bernilai tinggi menandakan heteroskedastisitas (heteroscedasticity), yaitu variansi error yang berubah-ubah sepanjang rentang data. Diagram berikut merangkum ketiga pola tersebut.

residualacak di sekitar nol0prediksipola lengkung0prediksipenyebar melebar (corong)0prediksi
Tiga pola residual terhadap prediksi, yaitu acak di sekitar nol, pola lengkung, dan penyebar melebar

Diagram sebaran residual terhadap prediksi memang merupakan kebiasaan umum di lapangan, dan pembaca dapat membuatnya sendiri pada lingkungan masing-masing dengan pustaka plot yang tersedia. Tanpa grafik sekalipun, pola-pola di atas tetap dapat didiagnosis dari angka, sebagaimana diulas pada bagian “Statistik residual tanpa grafik”.

Statistik residual tanpa grafik#

Empat statistik menutupi sebagian besar kebutuhan diagnosis residual. Pertama, mean residual yang mendekati nol menunjukkan model tidak menyimpang secara sistemik ke satu arah, misalnya selalu memprediksi terlalu tinggi. Kedua, simpangan baku residual menyatakan besarnya kesalahan tipikal dan dapat dibandingkan langsung dengan RMSE pada topik Metrik Regresi. Ketiga, korelasi antara residual dan prediksi yang dihitung dengan np.corrcoef mendekati nol ketika residual tidak bergantung pada tingkat prediksi, sedangkan nilainya menjauh dari nol ketika kesalahan mengikuti pola tertentu. Keempat, persentase residual di luar dua simpangan baku beserta daftar residual terbesar yang layak ditelusuri satu per satu, dengan patokan sekitar lima persen untuk residual yang berdistribusi mendekati normal.

Program analisis residual pada data diabetes#

Program berikut melatih LinearRegression pada dataset diabetes dengan pola yang sama seperti pada topik Regresi Linear, kemudian menghitung seluruh statistik residual pada data uji.

python analisis-residual.py
import numpy as np
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

data = load_diabetes()
X, y = data.data, data.target
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)

model = LinearRegression().fit(X_train, y_train)
prediksi = model.predict(X_test)
residual = y_test - prediksi

mean_r = residual.mean()
std_r = residual.std()
korelasi = np.corrcoef(prediksi, residual)[0, 1]
persen_luar = 100.0 * np.mean(np.abs(residual - mean_r) > 2 * std_r)
urutan = np.argsort(np.abs(residual))[-3:][::-1]

print(f"Jumlah sampel uji          : {residual.size}")
print(f"Mean residual              : {mean_r:.2f}")
print(f"Std residual               : {std_r:.2f}")
print(f"Korelasi prediksi-residual : {korelasi:.4f}")
print(f"Residual di luar 2 sigma   : {persen_luar:.1f} persen")
print("Tiga residual terbesar (aktual, prediksi, residual)")
for i in urutan:
    print(f"  {y_test[i]:7.1f}  {prediksi[i]:7.1f}  {residual[i]:7.1f}")
text Keluaran
Jumlah sampel uji          : 111
Mean residual              : 1.86
Std residual               : 53.34
Korelasi prediksi-residual : -0.0779
Residual di luar 2 sigma   : 4.5 persen
Tiga residual terbesar (aktual, prediksi, residual)
     52.0    205.7   -153.7
     52.0    185.6   -133.6
    200.0     71.2    128.8

Keluaran tersebut menggambarkan model yang cukup sehat dengan catatan. Mean residual 1.86 jauh lebih kecil daripada simpangan bakunya 53.34, sehingga tidak ada kecenderungan menyimpang ke satu arah. Nilai std 53.34 hampir sama dengan RMSE 53.37 pada topik Metrik Regresi, dan selisih kecilnya berasal dari mean residual yang tidak persis nol. Korelasi prediksi dengan residual bernilai -0.0779, mendekati nol, sehingga tidak ada struktur yang mengikat kesalahan pada tingkat prediksi tertentu. Residual di luar dua sigma sebesar 4.5 persen, dekat dengan patokan lima persen untuk sebaran mendekati normal.

Tiga residual terbesarnya justru bagian yang paling layak ditelusuri. Dua pasien dengan nilai aktual 52.0 diprediksi masing-masing 205.7 dan 185.6, jauh meleset ke atas, sedangkan satu pasien dengan prediksi terendah 71.2 ternyata memiliki aktual 200.0. Kasus-kasus ekstrem semacam ini umumnya ditelusuri ke sumbernya, misalnya keunikan kondisi pasien atau fitur penting yang belum tercakup dalam data.

Membandingkan pola sehat dan corong#

Statistik penyebaran yang dihitung pada dua himpunan residual memisahkan pola sehat dari corong. Program berikut membangkitkan dua dataset garis berderau, satu dengan derau konstan dan satu dengan derau yang membesar seiring nilai fitur, lalu membandingkan simpangan baku residual pada paruh fitur bernilai rendah dan paruh fitur bernilai tinggi.

python pola-corong.py
import numpy as np
from sklearn.linear_model import LinearRegression

rng = np.random.default_rng(42)

# pola sehat: garis dengan derau konstan
x = rng.uniform(0.0, 10.0, 200)
y = 3.0 * x + rng.normal(0.0, 1.0, 200)
X = x.reshape(-1, 1)
model = LinearRegression().fit(X, y)
residual = y - model.predict(X)
tengah = np.median(x)
s_rendah = residual[x < tengah].std()
s_tinggi = residual[x >= tengah].std()
print(f"Data sehat  : std residual rendah {s_rendah:.2f}, tinggi {s_tinggi:.2f}, rasio {s_tinggi / s_rendah:.2f}")

# corong: derau membesar seiring nilai fitur
y2 = 3.0 * x + rng.normal(0.0, 0.2 + 0.5 * x, 200)
model2 = LinearRegression().fit(X, y2)
residual2 = y2 - model2.predict(X)
s2_rendah = residual2[x < tengah].std()
s2_tinggi = residual2[x >= tengah].std()
print(f"Data corong : std residual rendah {s2_rendah:.2f}, tinggi {s2_tinggi:.2f}, rasio {s2_tinggi / s2_rendah:.2f}")
text Keluaran
Data sehat  : std residual rendah 1.01, tinggi 0.98, rasio 0.97
Data corong : std residual rendah 1.79, tinggi 3.83, rasio 2.14

Pada data sehat, kedua paruh menghasilkan simpangan baku yang hampir sama, yaitu 1.01 berbanding 0.98 dengan rasio 0.97 yang praktis menyentuh satu. Pada data corong, simpangan baku paruh fitur tinggi mencapai 3.83, lebih dari dua kali paruh rendahnya, dan rasio 2.14 itulah jejak numerik dari penyebaran yang melebar pada diagram corong. Pola lengkung terdiagnosis dengan cara senada, yaitu residual dirata-ratakan per kelompok nilai prediksi, dan rata-rata per kelompok yang secara sistematis berpindah tanda menandakan kurva yang belum tertangkap. Perbaikannya telah dibahas pada topik Fitur Polinomial, sedangkan penyebar yang timpang lebih sering diselesaikan melalui transformasi target daripada penambahan fitur.

Kesadaran akan asumsi model linear#

Analisis residual pada hakikatnya memeriksa asumsi yang mendasari model linear. Asumsi pertama adalah linearitas, yaitu hubungan fitur dan target benar-benar berupa garis, dan pelanggarannya tampak sebagai pola lengkung pada residual. Asumsi kedua adalah homoskedastisitas (homoscedasticity), yaitu variansi error yang sama di seluruh rentang, dan pelanggarannya tampak sebagai corong. Asumsi ketiga adalah kemandirian antarsampel, yang tidak dapat diperiksa dari residual semata dan lebih bergantung pada cara data dikumpulkan. Asumsi keempat berupa normalitas error, yang diperlukan untuk interval kepercayaan dan uji statistik, dengan persentase residual di luar dua sigma sebagai indikasi kasarnya. Model tetap dapat memberi prediksi yang berguna meskipun sebagian asumsi dilanggar, tetapi pelanggaran tersebut menentukan seberapa jauh angka model boleh dipercaya dan perbaikan apa yang layak dicoba.

Kesalahan umum#

Kesalahan pertama adalah mendiagnosis residual pada data latih. Regresi linear menyetel bobot sehingga residual data latih kehilangan struktur yang bisa ditangkap fitur linear, termasuk korelasi dengan prediksi yang mendekati nol secara otomatis. Penilaian yang sah menggunakan residual data uji atau data yang tidak ikut dilatih.

Kesalahan kedua adalah mencampur konvensi tanda. Konvensi pada topik ini adalah residual bernilai y−y^y - \hat{y}, sehingga residual negatif berarti prediksi lebih tinggi daripada aktual. Sebagian literatur menggunakan tanda sebaliknya, dan membaca diagnosis tanpa menetapkan konvensi berpotensi membalik kesimpulan.

Kesalahan ketiga adalah langsung menghapus sampel dengan residual terbesar. Residual ekstrem dapat berasal dari data yang salah catat, tetapi juga dapat berasal dari pola nyata yang belum dimodelkan. Penelusuran ke sumber data selalu didahulukan sebelum sampel mana pun disingkirkan.

Ringkasan#

  • Residual ei=yi−y^ie_i = y_i - \hat{y}_i yang sehat menyebar acak di sekitar nol, sedangkan pola lengkung menandakan hubungan yang belum tertangkap dan penyebar melebar menandakan heteroskedastisitas.
  • Diagnosis dapat dilakukan tanpa grafik melalui mean dan simpangan baku residual, korelasi residual terhadap prediksi, persentase di luar dua sigma, serta daftar residual terbesar.
  • Pada data uji diabetes, mean residual 1.86, korelasi -0.0779, dan 4.5 persen residual di luar dua sigma menunjukkan model yang relatif sehat dengan tiga kasus ekstrem yang layak ditelusuri.
  • Analisis residual memeriksa asumsi linearitas, homoskedastisitas, kemandirian, dan normalitas error yang mendasari model linear.

Referensi#