35  Notebook Bab 17 - Sintesis: Merancang Pipeline

Open In ColabNotebook Bab 17 ini punya dua bagian. Bagian Demo tinggal Anda jalankan lalu amati keluarannya; bagian Mini Project berisi soal dan data yang Anda kerjakan sendiri.Bab penutup ini merangkai seluruh buku: dari tujuan prediksi ke satu pipeline utuh yang menangani data campuran (numerik, kategorikal, dan nilai hilang) tanpa leakage.

35.1 Persiapan

import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import accuracy_score

RANDOM_STATE = 42
rng = np.random.default_rng(RANDOM_STATE)
print('Setup selesai.')
Setup selesai.

36 Section 1 - Demo: Pipeline Utuh untuk Data Campuran

Kerangkanya: tentukan unit dan target, pisahkan data, transformasikan tiap tipe kolom, latih model, lalu evaluasi. Semua transformasi hidup di dalam satu objek pipeline.

36.1 Data pelanggan: numerik + kategorikal + nilai hilang

n = 3000
usia = rng.integers(18, 70, n).astype(float)
pendapatan = rng.gamma(3, 3000000, n)
kota = rng.choice(['A', 'B', 'C', 'D'], n)
paket = rng.choice(['basic', 'premium', 'enterprise'], n, p=[0.5, 0.35, 0.15])

usia_f = usia.copy()
pend_f = pendapatan.copy()
logit = (-0.05 * (usia_f - 40) - 5e-8 * pend_f
         + np.where(paket == 'basic', 0.9, 0.0) + np.where(kota == 'D', 0.6, 0.0))
churn = (rng.random(n) < 1 / (1 + np.exp(-logit))).astype(int)

usia[rng.random(n) < 0.10] = np.nan       # nilai hilang
pendapatan[rng.random(n) < 0.08] = np.nan
df = pd.DataFrame({'usia': usia, 'pendapatan': pendapatan, 'kota': kota, 'paket': paket, 'churn': churn})
print('Data:', df.shape, '| churn rate:', round(df['churn'].mean(), 3))
df.head()
Data: (3000, 5) | churn rate: 0.494
usia pendapatan kota paket churn
0 22.0 1.370557e+07 C premium 1
1 NaN 4.504013e+06 A basic 0
2 52.0 1.388587e+07 C premium 0
3 40.0 3.207951e+06 B basic 0
4 40.0 2.847432e+06 D basic 1

36.2 Rangkai ColumnTransformer + model dalam satu pipeline

num = ['usia', 'pendapatan']
cat = ['kota', 'paket']

pra = ColumnTransformer([
    ('num', Pipeline([('imp', SimpleImputer(strategy='median')), ('sc', StandardScaler())]), num),
    ('cat', Pipeline([('imp', SimpleImputer(strategy='most_frequent')), ('oh', OneHotEncoder(handle_unknown='ignore'))]), cat),
])
pipe = Pipeline([('pra', pra), ('clf', LogisticRegression(max_iter=1000))])

X = df.drop(columns='churn')
y = df['churn']
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.25, random_state=RANDOM_STATE, stratify=y)
pipe.fit(Xtr, ytr)

print('Akurasi uji :', round(accuracy_score(yte, pipe.predict(Xte)), 3))
print('CV 5-fold   :', round(cross_val_score(pipe, X, y, cv=5).mean(), 3))
Akurasi uji : 0.657
CV 5-fold   : 0.658

🔎 Amati. Satu objek pipeline menangani imputasi dan scaling kolom numerik, imputasi dan one-hot kolom kategorikal, lalu model, semuanya sekaligus. Parameter di-fit hanya pada data latih, jadi evaluasi bebas leakage dan objek yang sama siap dipakai untuk inferensi dengan cukup memanggil predict. Inilah kerangka yang berulang di sepanjang buku: unit dan target, pemisahan, transformasi, model, lalu evaluasi.

37 Section 2 - Mini Project## SoalAnda menerima data pinjaman berisi kolom numerik dan kategorikal, sebagian dengan nilai yang hilang. Target prediksinya gagal_bayar (1/0).Tugas:1. Rancang satu pipeline lengkap: ColumnTransformer (imputasi + scaling untuk kolom numerik; imputasi + encoding untuk kolom kategorikal), lalu sebuah model di ujungnya.2. Pisahkan data lebih dulu, latih model hanya pada bagian latih, lalu ukur performa pada data uji dan lewat cross-validation.3. Jelaskan tiap keputusan berdasarkan kerangka: unit, target, split, transformasi, model, evaluasi.Luaran: kode pipeline lengkap, metrik uji dan CV, serta satu paragraf yang menghubungkan tiap bagian kode dengan kerangka desain.Kriteria penilaian: (a) semua transformasi berada di dalam pipeline; (b) parameter di-fit hanya dari data latih; (c) penjelasan disusun mengikuti kerangka desain.

# DATA AWAL (jangan diubah) - data pinjaman campuran.
n = 2500
penghasilan = rng.gamma(3, 2500000, n)
tenor = rng.integers(6, 60, n).astype(float)
pekerjaan = rng.choice(['pns', 'swasta', 'wiraswasta', 'lainnya'], n)
pendidikan = rng.choice(['sma', 'd3', 's1', 's2'], n, p=[0.4, 0.2, 0.3, 0.1])
logit = (-4e-7 * penghasilan + 0.02 * tenor
         + np.where(pekerjaan == 'wiraswasta', 0.5, 0.0) - np.where(pendidikan == 's2', 0.4, 0.0))
gagal_bayar = (rng.random(n) < 1 / (1 + np.exp(-logit))).astype(int)
penghasilan[rng.random(n) < 0.09] = np.nan
tenor[rng.random(n) < 0.07] = np.nan
pinjaman = pd.DataFrame({'penghasilan': penghasilan, 'tenor': tenor,
                         'pekerjaan': pekerjaan, 'pendidikan': pendidikan, 'gagal_bayar': gagal_bayar})
print('Data:', pinjaman.shape, '| gagal_bayar rate:', round(pinjaman['gagal_bayar'].mean(), 3))
pinjaman.head()
Data: (2500, 5) | gagal_bayar rate: 0.176
penghasilan tenor pekerjaan pendidikan gagal_bayar
0 5.589871e+06 32.0 lainnya s1 0
1 1.112347e+07 56.0 swasta d3 0
2 1.539417e+07 6.0 lainnya d3 0
3 4.417312e+06 56.0 wiraswasta sma 0
4 8.945099e+06 41.0 swasta d3 0
# Kerjakan di sini.
# Petunjuk: ColumnTransformer([...num..., ...cat...]) -> Pipeline -> train_test_split -> fit -> evaluasi.