TL;DR
Model churn end-to-end punya empat tahap: definisikan churn dengan aturan waktu yang jelas, bikin fitur dari riwayat transaksi (recency, frequency, monetary), latih model klasifikasi, lalu ubah skor probabilitas jadi daftar pelanggan prioritas. Di dataset toko_berkah dengan 1.842 pelanggan, model regresi logistik sederhana nangkep 71% pelanggan yang beneran berhenti belanja di 200 nama teratas.
Model churn yang berguna berhenti di satu file: daftar nama pelanggan yang perlu ditelepon minggu ini. Bukan skor AUC 0,87 di notebook.
Aku pernah lihat tim data ngerjain model churn selama enam minggu, presentasi grafik ROC yang cantik, terus nggak ada yang pakai. Masalahnya bukan modelnya. Masalahnya nggak ada yang tau harus ngapain sama angka 0,64 di kolom probabilitas.
Jadi di artikel ini aku jalanin alurnya dari data transaksi mentah sampai daftar prioritas yang bisa langsung dikasih ke tim sales, pakai dataset toko_berkah punya ngulikdata.
Model churn adalah model klasifikasi yang ngasih skor probabilitas tiap pelanggan bakal berhenti beli dalam periode tertentu ke depan. Inputnya riwayat perilaku pelanggan. Outputnya angka 0 sampai 1 yang kamu urutin dari besar ke kecil, terus potong di angka tertentu jadi daftar tindak lanjut.
Kamu butuh model ini kalau jumlah pelanggan udah lewat kapasitas tim buat dicek satu-satu. Toko dengan 80 pelanggan langganan? Pemiliknya udah hafal siapa yang lama nggak muncul.
Toko dengan 1.800 pelanggan dan tim CS dua orang? Di situ urutan prioritas mulai bernilai.
Bisnis langganan gampang. Ada tanggal cancel, itu labelnya.
Ritel dan UMKM nggak punya itu. Pelanggan nggak pernah bilang berhenti, mereka cuma nggak balik lagi. Jadi kamu harus bikin aturannya sendiri.
Cara yang aku pakai: lihat distribusi jarak antar transaksi semua pelanggan. Ambil persentil 90. Kalau 90% jeda pembelian di toko_berkah selesai dalam 74 hari, maka pelanggan yang nggak belanja lebih dari 90 hari aku label churn.
| Persentil jeda antar transaksi | Hari | Implikasi |
|---|---|---|
| P50 | 21 | Ritme normal pelanggan aktif |
| P75 | 44 | Mulai melambat |
| P90 | 74 | Batas wajar terakhir |
| Ambang churn | 90 | Label yang aku pakai |
Angka 90 hari itu bukan aturan universal. Toko bahan bangunan bisa 180 hari, warung sembako bisa 30 hari. Hitung dari datamu sendiri.
Satu hal yang sering kelewat: kamu harus potong waktu dengan benar. Fitur dibangun dari data sampai tanggal X. Label churn dilihat dari perilaku setelah tanggal X. Kalau kamu campur, modelnya bakal belajar dari masa depan dan skornya kelihatan hebat padahal bohong.
Tiga fitur RFM biasanya udah nyumbang sebagian besar sinyalnya. Recency (berapa hari sejak transaksi terakhir), frequency (berapa kali transaksi di periode observasi), monetary (total belanja).
Tapi tiga itu doang bikin model kamu ketinggalan pola yang lebih menarik. Ini daftar fitur yang aku pakai di toko_berkah:
Fitur tren_belanja itu yang paling sering bikin kaget orang. Pelanggan yang belanja Rp 2 juta bulan ini kelihatan sehat, sampai kamu tau bulan lalu dia belanja Rp 6 juta.
Buat ngitung fitur kayak gini di spreadsheet, COUNTIFS dan SUMIFS udah cukup. Kamu nggak perlu Python cuma buat nyusun tabel fitur.
Mulai dari regresi logistik. Alasannya bukan karena paling akurat, tapi karena kamu bisa jelasin hasilnya.
Waktu manajer nanya "kenapa Bu Sari masuk daftar?", kamu bisa jawab: recency-nya 68 hari dan tren belanjanya 0,4. Coba jawab pertanyaan yang sama pakai model ensemble 400 pohon di rapat pertama.
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
fitur = ['recency_hari', 'frekuensi_90d', 'total_belanja_180d',
'tren_belanja', 'ragam_kategori', 'rasio_diskon',
'umur_pelanggan_hari']
model = make_pipeline(
StandardScaler(),
LogisticRegression(class_weight='balanced', max_iter=1000)
)
model.fit(X_train[fitur], y_train)
skor = model.predict_proba(X_test[fitur])[:, 1]
Parameter class_weight='balanced' itu penting. Data churn hampir selalu timpang, dan tanpa penyeimbang model bakal main aman dengan nebak semua orang bertahan. Dokumentasi lengkapnya ada di halaman LogisticRegression scikit-learn.
Sebelum masuk model, pastiin datanya bersih. Duplikat transaksi dan tanggal kosong bakal ngerusak fitur recency diam-diam. Aku biasanya jalanin query cek kualitas data dulu sebelum nyentuh scikit-learn.
Lupakan akurasi. Kalau cuma 12% pelanggan yang churn, model yang nebak semua bertahan langsung dapat akurasi 88% dan nggak berguna sama sekali.
Pakai dua angka ini:
| Metrik | Artinya buat bisnis |
|---|---|
| Recall di top-N | Dari semua pelanggan yang beneran churn, berapa persen masuk daftar N nama teratas |
| Precision di top-N | Dari N nama yang ditelepon tim, berapa persen beneran mau churn |
Angka N bukan keputusan statistik. N itu kapasitas tim. Kalau CS bisa nelpon 50 orang per minggu selama sebulan, N kamu 200.
Dataset toko_berkah punya 1.842 pelanggan dengan riwayat transaksi 18 bulan. Aku potong di bulan ke-12 buat fitur, dan pakai 6 bulan sisanya buat label.
Hasilnya: 214 pelanggan (11,6%) masuk kategori churn.
Model regresi logistik dengan tujuh fitur di atas nangkep 152 dari 214 churn itu di 200 nama teratas. Recall 71%, precision 76%.
Bandingin sama aturan manual "urutkan dari yang paling lama nggak belanja". Aturan itu cuma nangkep 118 dari 214, recall 55%.
| Pendekatan | Churn tertangkap di 200 teratas | Recall |
|---|---|---|
| Urut recency saja | 118 | 55% |
| Regresi logistik 7 fitur | 152 | 71% |
Selisih 34 pelanggan. Dengan rata-rata belanja Rp 1,4 juta per pelanggan per semester, itu Rp 47,6 juta omzet yang punya kesempatan diselamatkan, dari daftar yang panjangnya sama persis.
Koefisien tertinggi jatuh ke tren_belanja, bukan recency. Pelanggan yang belanjanya turun setengah dalam tiga bulan punya risiko churn lebih tinggi daripada pelanggan yang memang jarang belanja tapi ritmenya stabil.
Itu insight yang nggak keliatan kalau kamu cuma urutin tanggal terakhir belanja.
Ini bagian yang paling sering dilewatin. File akhir yang aku kirim ke tim isinya begini:
| Nama | Kontak | Alasan | Nilai 6 bulan |
|---|---|---|---|
| Sari W. | 0812xxxx | 68 hari nggak belanja, sebelumnya rutin 3 minggu sekali | Rp 4.200.000 |
| Toko Melati | 0857xxxx | Belanja turun 60% dibanding kuartal lalu | Rp 11.800.000 |
Kolom "alasan" itu terjemahan dari fitur yang paling ngedorong skor pelanggan tersebut. Tim CS jadi punya bahan pembuka obrolan, bukan cuma nama.
Kolom nilai juga penting buat urutan kerja. Pelanggan berisiko dengan nilai Rp 11 juta jelas ditelepon duluan dibanding yang Rp 400 ribu.
Kalau kamu mau lanjut ke pengelompokan pelanggan sebelum bikin model, konsep segmentation layak dipelajari duluan. Model churn per segmen sering lebih tajam daripada satu model buat semua.
Tiga hal yang menentukan model churn kamu kepakai atau nggak.
Pertama, definisi churn harus dihitung dari distribusi datamu sendiri, bukan dicomot dari artikel orang. Kedua, metriknya recall dan precision di top-N sepanjang kapasitas tim, bukan akurasi. Ketiga, output akhirnya file berisi nama plus alasan, bukan kolom probabilitas.
Mau latihan nyusun fitur RFM-nya duluan? Coba query analisis pola belanja di NgulikSQL buat kenalan sama struktur data transaksi yang biasa dipakai.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Tools AI bisa bikin chart dan ringkas data dalam hitungan detik. Jadi Python masih perlu dipelajari analis di 2026? Jawabannya iya, tapi alasannya udah beda dari 3 tahun lalu.
Aku tes forecasting AI di data penjualan 4 cabang toko grosir. Hasilnya lebih akurat dari tebakan manual, tapi meleset parah di satu titik yang mahal.
Cara ngolah ribuan review pelanggan jadi insight pakai AI, dari nyusun prompt yang konsisten, ngasih label, sampai ngubah hasilnya jadi rekomendasi yang bisa dieksekusi.