Pengenalan glm

Regresi logistik sebagai perkenalan generalized linear model.

Daftar isi

Respons yang bernilai biner, seperti lulus dan tidak lulus, tidak dapat dimodelkan dengan garis lurus, sehingga fungsi glm() beserta keluarganya dibutuhkan. Topik ini memperkenalkan regresi logistik (logistic regression) sebagai anggota pertama generalized linear model, mulai dari data lulus dan tidak lulus, penyesuaian model dengan glm(family = binomial), pembacaan koefisien pada skala log-odds, konversinya menjadi odds ratio dengan exp(), hingga prediksi probabilitas dengan predict(). Batas interpretasinya dan arah pengembangan berikutnya ditutup di bagian akhir.

Keterbatasan regresi linear pada respons biner#

Misalnya pertanyaan diganti menjadi apakah seorang siswa lulus atau tidak, yang disimpan sebagai angka 0 dan 1. Menjalankan lm() atas respons semacam ini menghasilkan dua persoalan sekaligus. Pertama, garis model terus bergerak tanpa batas, sehingga prediksinya dapat keluar dari rentang probabilitas 0 sampai 1, misalnya 1,3 atau -0,2 yang tidak memiliki makna sebagai peluang. Kedua, residualnya membentuk dua pita terpisah karena responsnya hanya memiliki dua nilai, sehingga asumsi normalitas residual langsung runtuh.

Bentuk hubungan yang benar untuk probabilitas memang bukan garis lurus, melainkan kurva S yang mendekati nol di satu sisi dan mendekati satu di sisi lainnya, dengan daerah peralihan di tengahnya. Kurva S dicapai dengan menghubungkan rata-rata respons ke prediktor melalui fungsi tautan (link function), dan inilah gagasan inti generalized linear model. Ketika fungsi tautannya adalah logit, yaitu logaritma dari odds, modelnya disebut regresi logistik dan koefisiennya berada pada skala log-odds. Persamaan modelnya berbentuk

log⁡p1−p=β0+β1×jam \log \frac{p}{1-p} = \beta_0 + \beta_1 \times \text{jam}

dengan pp sebagai probabilitas lulus, dan sisi kirinya disebut log-odds.

Data lulus dan tidak lulus#

Data contohnya berupa 40 siswa dengan jam belajar 1 sampai 8 jam per minggu. Probabilitas lulus tiap siswa disusun dari fungsi logistik plogis() dengan pola dasar -6,5 ditambah 1,15 kali jam belajar, kemudian hasil lulus atau tidaknya ditarik dengan rbinom(). Kolom lulus dibungkus factor() dengan urutan tingkat "Tidak" lalu "Lulus", karena model binomial di R menganggap tingkat kedua faktor sebagai keberhasilan yang dimodelkan.

r
library(tidyverse)

set.seed(2026)
n <- 40
nama <- c("Ali", "Budi", "Citra", "Dewi", "Eka", "Fajar", "Gita", "Hana", "Indra", "Joko",
          "Kartika", "Laila", "Maya", "Nanda", "Oki", "Putri", "Rahmat", "Sari", "Tono", "Umar",
          "Vina", "Wawan", "Yuni", "Zaki", "Bagas", "Dian", "Farhan", "Gading", "Halim", "Intan",
          "Jefri", "Kirana", "Laras", "Mila", "Nadia", "Oscar", "Puspa", "Rizki", "Sinta", "Taufik")
jam <- round(runif(n, min = 1, max = 8), 1)
prob_lulus <- plogis(-6.5 + 1.15 * jam)
belajar <- tibble(
  siswa = nama,
  jam = jam,
  lulus = factor(rbinom(n, size = 1, prob = prob_lulus), levels = c(0, 1), labels = c("Tidak", "Lulus"))
)
slice_head(belajar, n = 10)
count(belajar, lulus)
text Keluaran
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.1     ✔ readr     2.2.0
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.3     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# A tibble: 10 × 3
   siswa   jam lulus
   <chr> <dbl> <fct>
 1 Ali     5.9 Lulus
 2 Budi    4.9 Lulus
 3 Citra   2   Tidak
 4 Dewi    3   Tidak
 5 Eka     4.9 Tidak
 6 Fajar   1.2 Tidak
 7 Gita    4.3 Lulus
 8 Hana    7   Lulus
 9 Indra   2.8 Tidak
10 Joko    5.1 Tidak
# A tibble: 2 × 2
  lulus     n
  <fct> <int>
1 Tidak    30
2 Lulus    10

Sepuluh baris pertama sudah memperlihatkan kecenderungannya, yaitu siswa dengan jam belajar tinggi seperti Ali dan Hana dinyatakan lulus, sedangkan siswa dengan jam belajar rendah tidak. Rekapitulasi menunjukkan 30 siswa tidak lulus dan 10 siswa lulus, sehingga responsnya benar-benar biner.

Menyesuaikan model dengan glm()#

Fungsi glm() menerima formula dan data seperti lm(), dengan tambahan argumen family = binomial yang menetapkan fungsi tautan logit untuk respons biner.

r
model_logistik <- glm(lulus ~ jam, data = belajar, family = binomial)
summary(model_logistik)
text Keluaran

Call:
glm(formula = lulus ~ jam, family = binomial, data = belajar)

Coefficients:
            Estimate Std. Error z value Pr(>|z|)   
(Intercept)  -4.7059     1.4601  -3.223  0.00127 **
jam           0.8563     0.3014   2.841  0.00450 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 44.987  on 39  degrees of freedom
Residual deviance: 32.559  on 38  degrees of freedom
AIC: 36.559

Number of Fisher Scoring iterations: 5

Struktur tabel koefisiennya serupa dengan lm(), tetapi kolom ujinya berganti dari t value menjadi z value karena estimasinya memakai metode maksimum likelihood dengan pendekatan normal. Koefisien jam sebesar 0,8563 berada pada skala log-odds, sehingga dibacanya adalah setiap tambahan satu jam belajar menaikkan log-odds kelulusan sekitar 0,86. Bagian deviance menggantikan peran R-squared sebagai ukuran ketidakcocokan model terhadap data. Null deviance 44,987 pada model tanpa prediktor turun menjadi residual deviance 32,559 dengan penurunan 12,43, dan AIC 36,559 menjadi acuan pembanding antar model dengan kompleksitas berbeda. Baris terakhir melaporkan lima iterasi Fisher scoring, yaitu prosedur numerik yang dijalankan glm() untuk menemukan estimasinya.

Dari log-odds ke odds ratio#

Log-odds memang sulit dipahami secara langsung, sehingga koefisiennya lazim dikonversi menjadi odds ratio dengan fungsi exp().

r
exp(coef(model_logistik))
text Keluaran
(Intercept)         jam 
0.009041696 2.354367417 

Konversi exp() berarti odds, yaitu perbandingan peluang keberhasilan terhadap peluang kegagalan, mengalikan dirinya dengan faktor tertentu untuk setiap tambahan satu jam. Odds ratio jam sebesar 2,354 dibaca bahwa setiap tambahan satu jam belajar per minggu mengalikan odds kelulusan dengan 2,35 kali, dan konversi sebaliknya berlaku untuk koefisien negatif yang mengalikan odds dengan faktor di bawah satu. Nilai pada intersep, yaitu 0,009, merupakan odds kelulusan pada jam belajar nol, dan angka sekecil itu wajar karena tanpa belajar sama sekali, satu keberhasilan berbanding lebih dari seratus kegagalan. Dengan demikian, odds 2,35 berarti keberhasilan 2,35 kali lebih mungkin daripada kegagalannya.

Probabilitas lulus dengan predict()#

Prediksi probabilitas memerlukan argumen type = "response", karena tanpa argumen tersebut predict() mengembalikan nilai pada skala log-odds sebagaimana sisi kiri persamaan modelnya.

r
predict(model_logistik, newdata = tibble(jam = c(2, 4, 6, 8)), type = "response")
text Keluaran
         1          2          3          4 
0.04772655 0.21741063 0.60628525 0.89513193 

Probabilitas lulusnya naik dari 0,048 pada jam belajar 2, menjadi 0,217 pada jam 4, 0,606 pada jam 6, dan 0,895 pada jam 8. Kenaikannya tidak konstan, yaitu pelan di kedua ujung dan paling curam di daerah tengah sekitar jam 5,5, sesuai bentuk kurva S-nya. Konversi dari log-odds ke probabilitas inilah yang menjamin seluruh prediksi tetap berada di antara 0 dan 1.

Kurva logistik dan arah lanjutan#

Kurva probabilitasnya digambar dengan mengevaluasi prediksi model pada seratus titik jam belajar, lalu menimpanya pada titik data 0 dan 1.

r
kurva <- tibble(jam = seq(1, 8, length.out = 100))
kurva$prob <- predict(model_logistik, newdata = kurva, type = "response")
p <- ggplot(belajar, aes(x = jam, y = as.numeric(lulus == "Lulus"))) +
  geom_point(size = 2, color = "#4472C4", alpha = 0.7) +
  geom_line(data = kurva, aes(x = jam, y = prob), color = "#C0504D", linewidth = 1, inherit.aes = FALSE) +
  labs(
    x = "Jam belajar per minggu",
    y = "Lulus (1) atau tidak (0)",
    title = "Kurva probabilitas lulus dari regresi logistik"
  ) +
  theme_minimal()
ggplot2::ggsave("kurva-logistik.svg", p, width = 5, height = 3.2)
0.000.250.500.751.002468Jam belajar per mingguLulus (1) atau tidak (0)Kurva probabilitas lulus dari regresi logistik
Kurva probabilitas lulus dari regresi logistik beserta titik data lulus dan tidak lulus

Kurva pada grafik memang berbentuk S dengan titik-titik data menempel pada ketinggian 0 dan 1, sehingga bentuk modelnya terlihat sesuai dengan sifat responsnya. Interpretasi koefisiennya tetap asosiatif pada data observasional, sama seperti regresi linear, sehingga klaim kausal tidak dapat ditegakkan dari model ini saja.

Regresi logistik ini hanyalah satu anggota generalized linear model. Ganti argumen family menjadi poisson untuk respons berupa hitungan, atau Gamma untuk respons positif dengan sebaran condong, dan seluruh kerangka formula, summary(), serta predict() tetap dipakai tanpa perubahan.

Ringkasan#

  • Respons biner tidak cocok untuk lm() karena prediksinya keluar dari rentang probabilitas dan residualnya membentuk dua pita terpisah, sehingga modelnya diganti melalui fungsi tautan logit.
  • glm(lulus ~ jam, data = belajar, family = binomial) menyesuaikan regresi logistik, dengan tingkat kedua faktor sebagai keberhasilan yang dimodelkan.
  • Koefisien berada pada skala log-odds, dan exp(coef(model)) mengonversinya menjadi odds ratio, yaitu 2,354 kali per tambahan satu jam belajar.
  • predict() dengan type = "response" mengembalikan probabilitas, sedangkan tanpa argumen itu keluarannya berupa log-odds.
  • Keluarga glm() lain seperti poisson memakai kerangka yang sama untuk tipe respons yang berbeda.

Referensi#