Model ŷ = 54.38 + 5.29·x dari chapter Simple Linear Regression lahir dari rumus Sxy/Sxx dan sekali dicek dengan statistics.linear_regression. Chapter penutup section ini membangun kembali model yang sama dengan tiga lapis alat yang berbeda kemampuan — standard library untuk lingkungan tanpa dependensi, SciPy untuk inferensi koefisien, NumPy untuk polinomial dan pekerjaan matrix — lalu menaikkan tangga ke regresi berganda dengan np.linalg.lstsq dan statsmodels, dan menutupnya dengan prediksi, residual, R², serta grafik garis di atas scatter. Data enam siswa dan data delapan siswa dari section teori dipakai ulang apa adanya, sehingga setiap koefisien yang keluar dari mesin baru dapat dibandingkan langsung dengan hasil chapter teorinya.

Tiga Cara Memfit Garis yang Sama #

Chapter Simple Linear Regression menghitung b1 = 5.2857 dan b0 = 54.3810 untuk data jam belajar dan nilai. Ketiga fungsi berikut memfit garis yang sama dengan jalur yang berbeda: statistics.linear_regression cukup untuk slope dan intercept; linregress menambahkan statistik inferensi; polyfit memfit polinomial derajat satu, yang secara matematis adalah garis.

python
import numpy as np
import statistics
from scipy.stats import linregress

jam = [2, 3, 4, 5, 6, 7]
nilai = [65, 70, 75, 82, 86, 91]

m_std = statistics.linear_regression(jam, nilai)
m_sci = linregress(jam, nilai)
m_np = np.polyfit(jam, nilai, deg=1)

print(f"statistics : slope = {m_std.slope:.4f}  intercept = {m_std.intercept:.4f}")
print(f"linregress : slope = {m_sci.slope:.4f}  intercept = {m_sci.intercept:.4f}")
print(f"polyfit    : slope = {m_np[0]:.4f}  intercept = {m_np[1]:.4f}")
print(f"linregress : r = {m_sci.rvalue:.4f}  p = {m_sci.pvalue:.7f}  stderr = {m_sci.stderr:.4f}")

Output yang Dihasilkan:

text
statistics : slope = 5.2857  intercept = 54.3810
linregress : slope = 5.2857  intercept = 54.3810
polyfit    : slope = 5.2857  intercept = 54.3810
linregress : r = 0.9981  p = 0.0000057  stderr = 0.1650

Ketiga pasangan koefisien jatuh pada 5.2857 dan 54.3810 — identik dengan hitungan manual chapter teori, karena ketiganya menyelesaikan kriteria least squares yang sama. Pembeda ketiganya adalah kelengkapan kembalian: objek linregress menyimpan rvalue (korelasi 0.9981, angka yang sama dengan chapter Korelasi), pvalue (0.0000057 — uji signifikansi slope yang identik dengan uji-t korelasi), dan stderr (0.1650 — standard error slope, bahan confidence interval koefisien). Standard library sengaja hemat: linear_regression hanya mengembalikan slope dan intercept, dan itu sudah memadai bila kebutuhannya sekadar memprediksi.

Prediksi, Residual, dan R² dari Definisi #

Prediksi dan evaluasi paling bersih dikerjakan dengan array NumPy: sekali data menjadi np.array, seluruh observasi diproses sekaligus tanpa loop. Blok berikut memprediksi nilai untuk 5.5 jam, mencetak residual tiap observasi, lalu menghitung dekomposisi variasi dari definisinya — SST, SSR, SSE — dan R² dua cara: manual serta kuadrat korelasi.

python
import numpy as np
from scipy.stats import linregress

jam = np.array([2, 3, 4, 5, 6, 7])
nilai = np.array([65, 70, 75, 82, 86, 91])

m = linregress(jam, nilai)
yhat = m.intercept + m.slope * jam
residual = nilai - yhat

print(f"prediksi 5.5 jam = {m.intercept + m.slope * 5.5:.2f}")
for x, y, yh, e in zip(jam, nilai, yhat, residual):
    print(f"jam = {x}  y = {y}  yhat = {yh:.2f}  e = {e:+.2f}")

ybar = nilai.mean()
SST = float(((nilai - ybar) ** 2).sum())
SSR = float(((yhat - ybar) ** 2).sum())
SSE = float((residual ** 2).sum())
print(f"SST = {SST:.2f}  SSR = {SSR:.2f}  SSE = {SSE:.2f}")
print(f"R2 manual   = {1 - SSE / SST:.4f}")
print(f"R2 rvalue^2 = {m.rvalue ** 2:.4f}")

Output yang Dihasilkan:

text
prediksi 5.5 jam = 83.45
jam = 2  y = 65  yhat = 64.95  e = +0.05
jam = 3  y = 70  yhat = 70.24  e = -0.24
jam = 4  y = 75  yhat = 75.52  e = -0.52
jam = 5  y = 82  yhat = 80.81  e = +1.19
jam = 6  y = 86  yhat = 86.10  e = -0.10
jam = 7  y = 91  yhat = 91.38  e = -0.38
SST = 490.83  SSR = 488.93  SSE = 1.90
R2 manual   = 0.9961
R2 rvalue^2 = 0.9961

Prediksi untuk 5.5 jam menghasilkan 83.45 — interpolasi di dalam rentang data 2-7 jam, bukan ekstrapolasi. Enam baris residual identik dengan tabel chapter Simple Linear Regression: terbesar +1.19 pada siswa yang belajar 5 jam, dan keenamnya menjumlah nol sesuai jaminan rumus intercept. Dekomposisi variasi membenarkan identitas SST = SSR + SSE secara numerik — 490.83 = 488.93 + 1.90 — dan R² yang dihitung manual dari definisi (1 − SSE/SST) jatuh tepat pada kuadrat rvalue, 0.9961; pada regresi sederhana keduanya memang satu benda yang sama, tema yang dibahas tuntas pada chapter Evaluasi Model Regresi. Kebiasaan menghitung R² dua jalan ini murah dan efektif untuk memeriksa kesalahan pemahaman definisi maupun galat ketik.

Regresi Berganda: lstsq dan statsmodels OLS #

Model dua prediktor dari chapter Multiple Linear Regression — nilai dari jam belajar dan jam tidur delapan siswa — tidak bisa ditangani linear_regression, sehingga kita pindah ke aljabar matrix. Trik kuncinya adalah kolom berisi angka 1 pada matrix desain: intercept bekerja sebagai koefisien kolom itu. Dua pustaka dikerjakan sekaligus: np.linalg.lstsq menyelesaikan least squares langsung, statsmodels membangun objek model yang kaya atribut.

python
import numpy as np
import statsmodels.api as sm

belajar = [2, 3, 4, 4, 5, 6, 7, 3]
tidur = [6, 9, 5, 7, 5, 8, 6, 7]
nilai = [59, 66, 62, 67, 64, 74, 74, 62]
n = len(nilai)

A = np.column_stack([belajar, tidur, np.ones(n)])  # kolom 1 menampung intercept
koef, *_ = np.linalg.lstsq(A, np.array(nilai), rcond=None)
print(f"lstsq : b1 = {koef[0]:.4f}  b2 = {koef[1]:.4f}  b0 = {koef[2]:.4f}")

X = sm.add_constant(np.column_stack([belajar, tidur]))
model = sm.OLS(np.array(nilai), X).fit()
print(f"OLS   : b0 = {model.params[0]:.4f}  b1 = {model.params[1]:.4f}  b2 = {model.params[2]:.4f}")
print(f"R-squared = {model.rsquared:.4f}  F = {model.fvalue:.4f}")

Output yang Dihasilkan:

text
lstsq : b1 = 3.0876  b2 = 1.8701  b0 = 40.4887
OLS   : b0 = 40.4887  b1 = 3.0876  b2 = 1.8701
R-squared = 0.9740  F = 93.6371

Kedua pustaka menghasilkan koefisien yang identik: ŷ = 40.49 + 3.09·belajar + 1.87·tidur, persis model chapter teori, dengan R² = 0.9740. Perbedaan praktisnya ada pada kelengkapan: objek model dari statsmodels menyimpan rsquared dan fvalue — F = 93.6371 adalah uji signifikansi keseluruhan model pada df (2, 5), sekeluarga dengan tabel ANOVA regresi chapter Evaluasi Model Regresi — serta metode f_test untuk menguji pembatasan koefisien, misalnya apakah koefisien tidur sama dengan nol (hasil terverifikasi: F = 42.78 dengan p = 0.0013). sm.add_constant menaruh kolom 1 di depan — kebalikan urutan A kita — sehingga koef dan model.params harus dibaca dengan urutan berbeda; kedua tampilan di atas sengaja mencetak keduanya agar perbedaan urutan itu terlihat, bukan tersimpan sebagai kejutan.

Skrip Terpadu: regresi_lengkap.py #

Alur lengkap — fit tiga cara, evaluasi, prediksi, dan visualisasi — dirangkai menjadi satu skrip yang dapat diunduh dan dijalankan ulang.

python regresi_lengkap.py
"""regresi_lengkap.py — fit garis tiga cara, evaluasi, lalu menggambar hasilnya."""

import numpy as np
import statistics
from scipy.stats import linregress
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

jam = [2, 3, 4, 5, 6, 7]
nilai = [65, 70, 75, 82, 86, 91]

m_std = statistics.linear_regression(jam, nilai)
m_sci = linregress(jam, nilai)
m_np = np.polyfit(jam, nilai, deg=1)

print(f"statistics.linear_regression : slope = {m_std.slope:.4f}, intercept = {m_std.intercept:.4f}")
print(f"scipy.stats.linregress       : slope = {m_sci.slope:.4f}, intercept = {m_sci.intercept:.4f}")
print(f"numpy.polyfit                : slope = {m_np[0]:.4f}, intercept = {m_np[1]:.4f}")

R2 = m_sci.rvalue ** 2
print(f"R2 = {R2:.4f}")
print(f"prediksi 5.5 jam = {m_std.intercept + m_std.slope * 5.5:.2f}")

plt.figure()
plt.scatter(jam, nilai, label="data siswa")
plt.plot(jam, m_std.intercept + m_std.slope * np.array(jam),
         color="red", label="garis regresi")
plt.xlabel("Jam belajar per hari")
plt.ylabel("Nilai ulangan")
plt.title("Regresi Nilai terhadap Jam Belajar")
plt.legend()
plt.savefig("regresi_belajar.png")
plt.close()
print("regresi_belajar.png tersimpan")

Output yang Dihasilkan:

text
statistics.linear_regression : slope = 5.2857, intercept = 54.3810
scipy.stats.linregress       : slope = 5.2857, intercept = 54.3810
numpy.polyfit                : slope = 5.2857, intercept = 54.3810
R2 = 0.9961
prediksi 5.5 jam = 83.45
regresi_belajar.png tersimpan

Gambar regresi_belajar.png menampilkan enam titik biru yang menanjak dari kiri bawah ke kanan atas dan satu garis merah yang menembus sebarannya. Garis itu melewati titik pusat data (x̄, ȳ) = (4.5, 78.17) — jaminan geometris rumus intercept yang dibahas chapter teori — dan menanjak 5.29 poin nilai per jam belajar; jarak vertikal tiap titik ke garis adalah residual yang barusan kita hitung, terbesar hanya 1.19 poin sehingga sebaran memang rapat di sekitar garis. Legend pada plt.legend() memetakan warna ke maknanya, pola keterangan yang sama dengan legend multi-seri pada chapter Line Chart. Dokumentasi fungsi-fungsi numerik yang dipakai chapter ini tersedia di NumPy dan dokumentasi statistics Python ; teori evaluasi model yang menjadi kerangka pembacaannya dibahas di Penn State STAT 500 .

Dengan regresi, perjalanan statistika dengan Python menutup lingkarannya: deskriptif untuk merangkum, distribusi untuk menghitung peluang, pengujian untuk memutuskan, dan model untuk memprediksi — semuanya dari data yang sama dengan section teori, kini dalam puluhan baris kode yang dapat dijalankan ulang siapa pun. Alat yang lengkap justru menuntut kehati-hatian yang lebih besar, karena angka presisi enam desimal mudah dipercaya melebihi buktinya. Section berikutnya menghadapkan kita pada kewajiban itu: membaca hasil statistik secara jujur, melaporkannya tanpa melebihi data, dan mengenali batas etika penggunaannya.

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

regresi_lengkap.py

Unduh berkas
python
"""regresi_lengkap.py — fit garis tiga cara, evaluasi, lalu menggambar hasilnya."""

import numpy as np
import statistics
from scipy.stats import linregress
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

jam = [2, 3, 4, 5, 6, 7]
nilai = [65, 70, 75, 82, 86, 91]

m_std = statistics.linear_regression(jam, nilai)
m_sci = linregress(jam, nilai)
m_np = np.polyfit(jam, nilai, deg=1)

print(f"statistics.linear_regression : slope = {m_std.slope:.4f}, intercept = {m_std.intercept:.4f}")
print(f"scipy.stats.linregress       : slope = {m_sci.slope:.4f}, intercept = {m_sci.intercept:.4f}")
print(f"numpy.polyfit                : slope = {m_np[0]:.4f}, intercept = {m_np[1]:.4f}")

R2 = m_sci.rvalue ** 2
print(f"R2 = {R2:.4f}")
print(f"prediksi 5.5 jam = {m_std.intercept + m_std.slope * 5.5:.2f}")

plt.figure()
plt.scatter(jam, nilai, label="data siswa")
plt.plot(jam, m_std.intercept + m_std.slope * np.array(jam),
         color="red", label="garis regresi")
plt.xlabel("Jam belajar per hari")
plt.ylabel("Nilai ulangan")
plt.title("Regresi Nilai terhadap Jam Belajar")
plt.legend()
plt.savefig("regresi_belajar.png")
plt.close()
print("regresi_belajar.png tersimpan")