%pip install -q featuretools scikit-learn
import numpy as np
import pandas as pd
import featuretools as ft
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
rng = np.random.default_rng(42)
print('Setup selesai.')Notebook Bab 16 - Rekayasa Fitur Otomatis
Notebook Bab 16 ini punya dua bagian. Bagian Demo tinggal Anda jalankan lalu amati keluarannya; bagian Mini Project berisi soal dan data yang Anda kerjakan sendiri.
Kita menjalankan Deep Feature Synthesis (featuretools) untuk membangkitkan fitur otomatis dari data relasional, lalu kurasi manusia menyaring yang bermakna. Jalankan di Google Colab agar pemasangan pustaka lancar.
Persiapan
Section 1 - Demo: DFS + Kurasi Manusia
Data relasional: pelanggan dan transaksi
Target churn bergantung pada agregat transaksi (total belanja dan frekuensi).
n_cust = 800
cust = pd.DataFrame({'customer_id': range(n_cust)})
rows, tid = [], 0
for c in range(n_cust):
for _ in range(int(rng.integers(3, 20))):
rows.append((tid, c, float(rng.gamma(2, 50000)), int(rng.integers(0, 365))))
tid += 1
tx = pd.DataFrame(rows, columns=['transaction_id', 'customer_id', 'amount', 'day'])
agg = tx.groupby('customer_id')['amount'].agg(['sum', 'count']).sort_index()
logit = 2e-6 * agg['sum'].to_numpy() - 0.05 * agg['count'].to_numpy() - 3
churn = (rng.random(n_cust) < 1 / (1 + np.exp(-logit))).astype(int)
print('Pelanggan:', n_cust, '| transaksi:', len(tx), '| churn rate:', round(churn.mean(), 3))es = ft.EntitySet('data')
es = es.add_dataframe(dataframe_name='customers', dataframe=cust, index='customer_id')
es = es.add_dataframe(dataframe_name='transactions', dataframe=tx, index='transaction_id')
es = es.add_relationship('customers', 'customer_id', 'transactions', 'customer_id')
fm, defs = ft.dfs(entityset=es, target_dataframe_name='customers',
agg_primitives=['sum', 'mean', 'count', 'std', 'max', 'min'],
trans_primitives=[], max_depth=1)
fm = fm.fillna(0).sort_index()
yv = churn[fm.index.to_numpy()]
print('Fitur otomatis DFS:', fm.shape[1])
print('Contoh nama fitur:', list(fm.columns)[:6])Semua fitur DFS vs kurasi manusia (top-5)
acc_auto = cross_val_score(RandomForestClassifier(n_estimators=200, random_state=42), fm, yv, cv=5).mean()
rf = RandomForestClassifier(n_estimators=200, random_state=42).fit(fm, yv)
imp = pd.Series(rf.feature_importances_, index=fm.columns).sort_values(ascending=False)
top = imp.head(5).index
acc_cur = cross_val_score(RandomForestClassifier(n_estimators=200, random_state=42), fm[top], yv, cv=5).mean()
print(f'AutoFE (semua {fm.shape[1]} fitur) akurasi = {acc_auto:.3f}')
print(f'Kurasi manusia (top-5) akurasi = {acc_cur:.3f}')
print('Top-5 fitur:', list(top))🔎 Amati. DFS membangkitkan banyak fitur agregat secara otomatis dari relasi pelanggan-transaksi. Kurasi manusia yang memilih segelintir fitur teratas mempertahankan akurasi dengan jauh lebih sedikit fitur, sekaligus membuang fitur yang kebetulan tampak berguna tetapi tak bermakna. AutoFE mempercepat eksplorasi, tetapi keputusan akhir tetap membutuhkan validator manusia: otomatis namun tetap dirancang manusia.
Section 2 - Mini Project
Soal
Anda diberi data relasional pengguna dan sesi aplikasi. Targetnya berlangganan (1/0).
Tugas:
- Bentuk
EntitySet(pengguna sebagai induk, sesi sebagai anak) dan jalankanft.dfsuntuk membangkitkan fitur otomatis. - Latih baseline pada semua fitur DFS.
- Lakukan kurasi: pilih fitur teratas berdasarkan importance, bandingkan akurasinya, dan periksa apakah nama fiturnya masuk akal.
Luaran: kode DFS + kurasi, perbandingan akurasi, dan 3-4 kalimat tentang fitur mana yang bermakna.
Kriteria penilaian: (a) relasi entityset benar; (b) baseline vs kurasi dibandingkan adil; (c) ada penilaian kebermaknaan fitur.
# DATA AWAL (jangan diubah) - pengguna dan sesi aplikasi.
n_user = 700
users = pd.DataFrame({'user_id': range(n_user)})
srows, sid = [], 0
for u in range(n_user):
for _ in range(int(rng.integers(2, 25))):
srows.append((sid, u, float(rng.gamma(2, 8)), int(rng.integers(0, 30))))
sid += 1
sessions = pd.DataFrame(srows, columns=['session_id', 'user_id', 'durasi_menit', 'hari'])
sagg = sessions.groupby('user_id')['durasi_menit'].agg(['sum', 'count']).sort_index()
logit = 0.02 * sagg['sum'].to_numpy() + 0.03 * sagg['count'].to_numpy() - 3
berlangganan = (rng.random(n_user) < 1 / (1 + np.exp(-logit))).astype(int)
print('Pengguna:', n_user, '| sesi:', len(sessions), '| langganan rate:', round(berlangganan.mean(), 3))# Kerjakan di sini.
# Petunjuk: ft.EntitySet -> add_dataframe(users, index='user_id') & add_dataframe(sessions, index='session_id')
# -> add_relationship('users','user_id','sessions','user_id') -> ft.dfs(...).