34  Notebook Bab 16 - Rekayasa Fitur Otomatis

Open In ColabNotebook 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.

34.1 Persiapan

%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.')

35 Section 1 - Demo: DFS + Kurasi Manusia

35.1 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])

35.2 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.

36 Section 2 - Mini Project

36.1 Soal

Anda diberi data relasional pengguna dan sesi aplikasi. Targetnya berlangganan (1/0).

Tugas:

  1. Bentuk EntitySet (pengguna sebagai induk, sesi sebagai anak) dan jalankan ft.dfs untuk membangkitkan fitur otomatis.
  2. Latih baseline pada semua fitur DFS.
  3. 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(...).