DataLens

Regresi linear (intuisi matematikanya)

Cocokkan garis (dan bidang) yang meminimalkan error kuadrat, baca koefisiennya sebagai efek bisnis, bandingkan least squares NumPy dengan scikit-learn, dan periksa residualnya.

Level: Menengah · 8 menit baca

Latihan modul ini

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

Idenya

Regresi linear memprediksi sebuah angka sebagai jumlah berbobot dari fitur-fitur ditambah sebuah konstanta:

units = w₁·temperature + w₂·weekend + w₃·promo + w₄·ad_spend + b

Itulah X @ w + b dari modul aljabar linear NumPy, dan "model + loss" dari dua modul lalu, dengan satu sifat istimewa: bobot dengan MSE terendah bisa dihitung secara eksak, dengan sebuah rumus, tanpa perlu mencari. Ini model pertama yang dicoba untuk masalah regresi apa pun, dan sering menjadi yang akhirnya dirilis, karena koefisiennya menjelaskan dirinya sendiri.

Satu fitur: sebuah garis

Mulai dari versi paling sederhana pertanyaannya: apakah belanja iklan yang lebih banyak menjual lebih banyak unit? Dengan satu fitur, model linear hanyalah garis lurus yang melewati titik-titiknya, dan NumPy bisa langsung mencari garis yang paling pas:

import numpy as np
import pandas as pd

demand = pd.read_csv("daily_demand.csv")
x = demand["ad_spend"].to_numpy()
y = demand["units"].to_numpy()

w, b = np.polyfit(x, y, 1)
print(round(w, 2), round(b, 2))
7.51 44.56

Kemiringan w berarti: setiap tambahan sejuta Rupiah iklan berkaitan dengan sekitar sebanyak itu unit terjual. Intercept b adalah unit yang diprediksi dengan belanja iklan nol.

Bagaimana cara menghitungnya? Least squares punya jawaban dalam bentuk tertutup. Untuk satu fitur, rumusnya cukup pendek untuk ditulis:

w_formula = np.sum((x - x.mean()) * (y - y.mean())) / np.sum((x - x.mean()) ** 2)
b_formula = y.mean() - w_formula * x.mean()
print(round(w_formula, 2), round(b_formula, 2))
7.51 44.56

Jawabannya sama. Kemiringannya adalah "seberapa banyak x dan y bergerak bersama" dibagi "seberapa banyak x bergerak", dan garisnya selalu melewati titik (rata-rata x, rata-rata y).

Beberapa fitur: sebuah bidang

Dengan beberapa fitur, NumPy menyelesaikan masalah least squares dengan np.linalg.lstsq. Tambahkan kolom berisi angka satu supaya model bisa mempelajari intercept-nya:

features = ["temperature", "weekend", "promo", "ad_spend"]
X = demand[features].to_numpy()
X1 = np.column_stack([X, np.ones(len(X))])          # kolom terakhir: intercept
coefs, *_ = np.linalg.lstsq(X1, y, rcond=None)
for name, c in zip(features + ["intercept"], coefs):
    print(f"{name:12} {c:8.2f}")
temperature     -1.67
weekend          5.75
promo           18.92
ad_spend         7.62
intercept       85.75

Setiap koefisien adalah efek dengan fitur-fitur lain dibuat tetap:

Itulah daya tarik regresi linear: seorang manajer bisa membacanya. "Promosi bernilai sekitar 19 unit per hari" adalah kalimat yang bisa ditindaklanjuti (bandingkan dengan biaya sebuah promosi).

Ide utama

Regresi linear menemukan bobot yang meminimalkan error kuadrat, secara eksak. Setiap bobot adalah efek dari satu fitur dengan yang lain dibuat tetap, dalam satuan fitur tersebut.

Hal yang sama dengan scikit-learn

Dalam praktik kamu memakai scikit-learn, yang punya antarmuka yang sama untuk setiap model: fit, lalu predict:

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(demand[features], y)
print(np.round(model.coef_, 2), round(model.intercept_, 2))

tomorrow = pd.DataFrame({"temperature": [29.0], "weekend": [1], "promo": [1], "ad_spend": [2.0]})
print(model.predict(tomorrow).round(1))
[-1.67  5.75 18.92  7.62] 85.75
[77.2]

Koefisiennya identik dengan lstsq. predict mengubah fitur hari baru menjadi ramalan: hari Sabtu yang panas dengan promosi dan iklan Rp 2 jt.

R²: seberapa banyak yang dijelaskan?

model.score(X, y) mengembalikan R²: porsi variasi y yang dijelaskan oleh model (1,0 = sempurna, 0 = tidak lebih baik daripada memprediksi rata-ratanya).

print(round(model.score(demand[features], y), 3))
0.811

Modul metrik regresi menjelaskan R² dengan benar. Di sini ia menyatakan bahwa keempat fitur ini menjelaskan sebagian besar variasi penjualan dari hari ke hari.

Periksa residualnya

Sebuah model bisa punya skor yang lumayan tapi tetap salah secara sistematis. Lihat residual-nya (nilai sebenarnya − prediksi):

residuals = y - model.predict(demand[features])
print("average is ~0:", bool(np.isclose(residuals.mean(), 0)), "| typical size:", round(residuals.std(), 2))
by_weekend = pd.Series(residuals).groupby(demand["weekend"]).mean()
print("weekday and weekend averages ~0:", bool(np.allclose(by_weekend, 0)))
average is ~0: True | typical size: 4.98
weekday and weekend averages ~0: True

Tanda-tanda yang baik: residual rata-ratanya nol secara keseluruhan dan di dalam kelompok (tidak ada kelompok yang konsisten diprediksi terlalu tinggi atau terlalu rendah), dan sebarannya (sekitar ±5 unit) sesuai dengan noise yang kamu harapkan. Pola di residual (misalnya, selalu memprediksi terlalu rendah di hari panas) berarti model melewatkan sesuatu: hubungan yang melengkung, interaksi, atau sebuah fitur.

Keterbatasan

Mengapa ini penting untuk kode yang bersih

Regresi linear adalah baseline yang harus dikalahkan setiap model regresi lainnya, dan yang paling bisa dijelaskan yang akan pernah kamu deploy. Jaga daftar fitur tetap eksplisit, cetak koefisien beserta namanya, dan selalu periksa residual. Model rumit yang mengalahkannya sebesar 1% sering tidak sepadan dengan hilangnya penjelasan.

Rangkuman

Latihan modul ini

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

Berikutnya: Regresi logistik dan klasifikasi →