Dua chapter pertama Section ini memprediksi angka: harga rumah dan pendapatan harian. Sekarang kita menghadapi pertanyaan yang bentuknya berbeda — pelanggan aplikasi belanja ini akan berhenti (churn) atau tetap setia? Regresi logistik adalah model klasifikasi biner paling pertama yang layak dicoba: cepat, stabil, dan mengeluarkan peluang alih-alih sekadar label. Kita pernah membahasnya dari sisi statistik di Regresi Logistik pada Section Teknik Analisis Data ; kali ini sudut pandangnya machine learning — fokus pada alur fit()-predict()-evaluasi dengan data uji, pembacaan predict_proba(), dan batas keputusan model.

Dari Menaksir Angka ke Menaksir Peluang #

Regresi logistik memakai mesin yang sama dengan regresi linear — gabungan linear z = b0 + b1*x1 + b2*x2 — lalu memadatkannya ke rentang 0 sampai 1 dengan fungsi sigmoid. Hasilnya dibaca sebagai peluang kelas positif. Perbedaan pola pemakaiannya dengan regresi linear bisa dirangkum singkat:

AspekRegresi linearRegresi logistik
Jenis tugasRegresi (target angka)Klasifikasi biner (target 0/1)
Keluaran predict()Angka bergerak bebasLabel kelas 0 atau 1
Keluaran tambahanpredict() itu sendiripredict_proba() berisi peluang tiap kelas
Metrik awal yang cocokR²Akurasi

Kenapa tidak memakai regresi linear untuk target 0/1? Karena garis lurus bisa mengeluarkan “peluang” -0,3 atau 1,7 — nilai yang tidak bisa dibaca sebagai peluang. Sigmoid memastikan keluaran selalu berada di antara 0 dan 1; pembahasan lengkap bentuk kurvanya sudah kita kerjakan di chapter statistik, jadi kita langsung ke pemakaian praktisnya.

Melatih Model Churn #

Kasus kita: 36 pelanggan aplikasi belanja “Keranjang Kita”. Dua fitur tercatat untuk tiap pelanggan — order_per_bulan (rata-rata jumlah pesanan per bulan) dan hari_sejak_order (berapa hari sejak pesanan terakhir) — beserta status churn di akhir kuartal: 1 berhenti berbelanja, 0 tetap setia. Ada 17 pelanggan berhenti dan 19 bertahan, cukup seimbang untuk latihan:

python
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

pelanggan = pd.DataFrame({
    "order_per_bulan": [1, 7, 3, 8, 3, 6, 1, 2, 2, 2, 5, 6, 1, 4, 6, 7,
                        5, 5, 4, 3, 0, 2, 4, 7, 6, 10, 3, 9, 2, 8, 4, 9, 7, 8, 6, 9],
    "hari_sejak_order": [10, 25, 5, 5, 15, 10, 30, 14, 26, 8, 15, 20, 18, 20,
                         4, 3, 5, 3, 8, 25, 22, 20, 12, 6, 2, 3, 8, 1, 3, 2,
                         3, 2, 9, 7, 8, 6],
    "churn": [1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
              0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
})

fitur = ["order_per_bulan", "hari_sejak_order"]
X = pelanggan[fitur]
y = pelanggan["churn"]

X_latih, X_uji, y_latih, y_uji = train_test_split(X, y, test_size=0.3,
                                                   stratify=y, random_state=42)
model = LogisticRegression()
model.fit(X_latih, y_latih)

print("Intersep (log-odds): %6.2f" % model.intercept_[0])
for nama, koef in zip(fitur, model.coef_[0]):
    print("%-16s: koef %6.2f  -> odds ratio %.2f" % (nama, koef, np.exp(koef)))
print("Akurasi data latih : %.2f" % model.score(X_latih, y_latih))
print("Akurasi data uji   : %.2f" % model.score(X_uji, y_uji))

Output yang Dihasilkan:

text
Intersep (log-odds):   0.17
order_per_bulan : koef  -1.15  -> odds ratio 0.32
hari_sejak_order: koef   0.58  -> odds ratio 1.78
Akurasi data latih : 0.96
Akurasi data uji   : 0.91

Mari kita telaah baris-baris kode di atas:

  1. train_test_split(..., test_size=0.3, stratify=y, random_state=42): 25 pelanggan menjadi data latih dan 11 menjadi data uji. Argumen stratify=y menjaga proporsi kelas di kedua bagian tetap menyerupai data asli — penting untuk klasifikasi agar data uji tidak kebetulan berisi satu kelas saja.
  2. model.score(X_uji, y_uji) pada model klasifikasi mengembalikan akurasi: porsi prediksi yang tepat. Model kita benar pada 10 dari 11 pelanggan uji (0,91) — satu-satunya yang salah adalah pelanggan dengan 4 order per bulan dan 8 hari tanpa belanja, tepat di wilayah abu-abu antara dua kelas.
  3. model.coef_[0] berbentuk larik dua nilai karena ada dua fitur dan satu kelas positif; np.exp(koef) mengubahkannya menjadi odds ratio yang manusiawi dibaca.

Membaca Koefisien dan Odds Ratio #

Koefisien regresi logistik bekerja pada skala log-odds, sehingga cara membacanya berbeda dari kemiringan regresi linear. Odds ratio hasil np.exp(koefisien) mengubahnya menjadi pengali:

FiturKoefisienOdds ratioCara membacanya
order_per_bulan-1,150,32Tiap tambahan 1 order/bulan mengalikan odds churn dengan 0,32 — makin rajin order, makin kecil kecenderungan berhenti
hari_sejak_order+0,581,78Tiap tambahan 1 hari tanpa belanja mengalikan odds churn dengan 1,78 — makin lama diam, makin besar kecenderungan berhenti

Kedua angka itu masuk akal secara bisnis dan searah dengan pola data yang kita lihat. Jika butuh pendalaman teori log-odds, tabel uji formal, dan cara melaporkannya, pembahasan penuhnya ada di chapter statistik ; pada alur machine learning, koefisien biasanya cukup dipakai sebagai pemeriksaan arah.

Peluang Tiap Pelanggan dan Batas Keputusan #

predict() hanya mengembalikan label akhir, padahal informasi paling berharga justru di tengah prosesnya. Metode predict_proba() memperlihatkan peluang lengkap; kolom [:, 1] adalah peluang kelas 1 (churn). Kita uji empat profil pelanggan:

python
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

pelanggan = pd.DataFrame({
    "order_per_bulan": [1, 7, 3, 8, 3, 6, 1, 2, 2, 2, 5, 6, 1, 4, 6, 7,
                        5, 5, 4, 3, 0, 2, 4, 7, 6, 10, 3, 9, 2, 8, 4, 9, 7, 8, 6, 9],
    "hari_sejak_order": [10, 25, 5, 5, 15, 10, 30, 14, 26, 8, 15, 20, 18, 20,
                         4, 3, 5, 3, 8, 25, 22, 20, 12, 6, 2, 3, 8, 1, 3, 2,
                         3, 2, 9, 7, 8, 6],
    "churn": [1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
              0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
})

fitur = ["order_per_bulan", "hari_sejak_order"]
X_latih, X_uji, y_latih, y_uji = train_test_split(
    pelanggan[fitur], pelanggan["churn"], test_size=0.3,
    stratify=pelanggan["churn"], random_state=42)
model = LogisticRegression()
model.fit(X_latih, y_latih)

calon = pd.DataFrame({
    "order_per_bulan": [7, 4, 4, 2],
    "hari_sejak_order": [3, 6, 9, 25],
})
peluang = model.predict_proba(calon)[:, 1]
for i in range(len(calon)):
    print("Order %d kali/bln, tidak belanja %2d hari -> peluang churn %.2f"
          % (calon["order_per_bulan"][i], calon["hari_sejak_order"][i], peluang[i]))

b0 = model.intercept_[0]
b1, b2 = model.coef_[0]
print()
print("Batas keputusan (z = 0):")
for order in [2, 4, 8]:
    hari_batas = -(b0 + b1 * order) / b2
    print("  order %d kali/bln -> peluang churn melewati 0.5 setelah %.0f hari tanpa belanja"
          % (order, hari_batas))

Output yang Dihasilkan:

text
Order 7 kali/bln, tidak belanja  3 hari -> peluang churn 0.00
Order 4 kali/bln, tidak belanja  6 hari -> peluang churn 0.27
Order 4 kali/bln, tidak belanja  9 hari -> peluang churn 0.68
Order 2 kali/bln, tidak belanja 25 hari -> peluang churn 1.00

Batas keputusan (z = 0):
  order 2 kali/bln -> peluang churn melewati 0.5 setelah 4 hari tanpa belanja
  order 4 kali/bln -> peluang churn melewati 0.5 setelah 8 hari tanpa belanja
  order 8 kali/bln -> peluang churn melewati 0.5 setelah 16 hari tanpa belanja

Tiga hal dari keluaran tersebut:

  1. Dua profil tengah memperlihatkan batas keputusan bekerja: pelanggan 4 order per bulan bernilai peluang 0,27 pada 6 hari tanpa belanja, lalu 0,68 pada 9 hari — peluangnya menyeberangi 0,5 di antara keduanya. predict() hanya mengembalikan kelas 0 untuk yang pertama dan kelas 1 untuk yang kedua, padahal jarak keduanya tipis.
  2. Batas keputusan adalah tempat z = 0 — peluang tepat 0,5. Dengan dua fitur, batas itu berupa garis b0 + b1*order + b2*hari = 0; kita tinggal membalik rumusnya menjadi hari_batas = -(b0 + b1*order)/b2. Pelanggan di atas garis (makin lama diam) masuk wilayah churn.
  3. Garis batas ini bisa langsung dipakai tim operasional: “pelanggan 4 order per bulan yang telah 8 hari tidak belanja masuk daftar tindak lanjut”. Angka hasil model menjadi aturan kerja yang konkret — dan hanya regresi logistik yang mengeluarkan garis lurus semacam ini secara alami.

Kekuatan dan Kelemahan Regresi Logistik #

AspekKeterangan
Cepat dan stabilPelatihan sekejap walau data besar; jarang bermasalah
Keluaran peluangBisa diranking dan diberi ambang sesuai biaya keputusan
Batas keputusan garis lurusHanya memisahkan kelas yang bisa dipisah garis
Koefisien bisa dibacaOdds ratio memberi arah pengaruh tiap fitur
Perlu fitur numerik siap pakaiFitur kategori harus diolah dulu (feature engineering)

Kapan Kita Memakainya #

Regresi logistik adalah baseline wajib untuk klasifikasi biner: skor spam atau bukan, gagal bayar atau tidak, churn atau setia. Ia menonjol ketika kita butuh peluang yang bisa diatur ambangnya, ketika batas keputusan berbentuk garis sudah memadai, dan ketika hasil harus bisa dijelaskan ke pihak non-teknis. Ketika batas antar kelas berbentuk bertingkat — misalnya “setia bila order tinggi ATAU baru saja belanja” — kita perlu model yang menggambar aturan bertingkat itu sendiri. Model itulah bintang chapter berikutnya.

Rangkuman #

  • Regresi logistik memadatkan gabungan linear z ke rentang 0-1 dengan sigmoid; predict() memberi label, predict_proba()[:, 1] memberi peluang kelas positif.
  • Alur ML-nya baku: train_test_split() dengan stratify=y, fit(), lalu akurasi lewat score() — contoh kita mencapai 0,91 pada data uji.
  • Koefisien dibaca lewat odds ratio np.exp(koef): 0,32 per order tambahan dan 1,78 per hari tanpa belanja.
  • Batas keputusan adalah tempat z = 0; dengan dua fitur ia garis lurus yang bisa dibalik menjadi aturan operasional.
  • Ambang 0,5 bisa digeser sesuai biaya kesalahan; akurasi saja belum cukup untuk data timpang.

Selama ini kita memakai satu rumus linear untuk semua pelanggan. Bagaimana jika pola keputusannya memang bertingkat-tingkat — pelanggan istimewa bila belanja di atas 500 ribu, atau bila datang lebih dari enam kali sebulan? Model yang menulis aturan seperti itu sendiri menunggu kita di chapter Decision Tree .

Referensi #

  1. scikit-learn — train_test_split
  2. scikit-learn — Model evaluation (akurasi dan metrik klasifikasi)
  3. scikit-learn — FAQ