Pada model pertama kita, seluruh pekerjaan berat terjadi di balik dua kata kunci: fit dan predict. Keseragaman itu bukan kebetulan, melainkan keputusan rancangan yang disebut kontrak estimator — aturan antarmuka yang diikuti seluruh ratusan algoritme di scikit-learn, dari regresi linier sampai gradient boosting. Kontrak inilah yang membuat dokumentasi terasa seragam, yang membuat Pipeline dan GridSearchCV bisa bekerja untuk model apa pun, dan yang memungkinkan kita mengganti algoritme hanya dengan mengubah satu baris. Chapter ini membedah kontrak tersebut metode demi metode, lalu membuktikannya dengan kode yang menyelidiki isi sebuah estimator secara langsung.
Kontrak Estimator: Satu Bahasa untuk Ratusan Algoritme #
Masalah yang dipecahkan kontrak ini nyata: bayangkan setiap algoritme datang dengan antarmuka panggilan sendiri — satu pakai train(), satu pakai learn(), satu pakai execute(). Setiap pustaka baru akan menuntut pembelajaran ulang dari nol. scikit-learn menegakkan satu bentuk untuk semua: konstruktor hanya menyimpan hyperparameter apa adanya tanpa menghitung apa pun; seluruh pembelajaran terjadi di fit(); seluruh penggunaan terjadi di predict() atau transform(); dan hasil pembelajaran tersimpan di atribut berakhiran garis bawah.
Tabel berikut merangkum metode-metode kontrak beserta perannya:
| Metode | Peran | Kapan dipanggil |
|---|---|---|
fit(X, y) | Memelajari parameter dari data; mengembalikan dirinya sendiri | Sekali per pelatihan |
predict(X) | Menghasilkan label/nilai untuk sampel baru | Setelah fit, saat inference |
predict_proba(X) | Probabilitas tiap kelas (estimator klasifikasi saja) | Saat butuh tingkat keyakinan |
transform(X) | Mengubah data memakai aturan hasil belajar | Setelah fit estimator transformer |
fit_transform(X) | fit + transform dalam satu panggilan | Saat pertama menerapkan transformer |
inverse_transform(Z) | Mengembalikan hasil transform ke bentuk asli | Saat perlu membaca balik hasil |
get_params() | Membaca seluruh hyperparameter | Inspeksi konfigurasi; dipakai GridSearchCV |
set_params(**kwargs) | Mengubah hyperparameter tanpa objek baru | Saat penyetelan model |
score(X, y) | Metrik bawaan (akurasi untuk klasifikasi, R² untuk regresi) | Evaluasi cepat |
Konsekuensi praktisnya luar biasa. Karena setiap estimator menaati kontrak yang sama, mengganti algoritme menjadi operasi satu baris:
# Ganti satu baris ini; seluruh sisa kode tetap berjalan tanpa diubah:
model = KNeighborsClassifier(n_neighbors=3) # algoritme A
model = LogisticRegression() # algoritme B, kontrak sama
model = RandomForestClassifier(random_state=42) # algoritme C, kontrak samaRantai Pipeline juga lahir dari kontrak ini: setiap langkah pipa hanya perlu tahu bahwa langkah sebelumnya bisa fit/transform, tanpa peduli apa algoritme di dalamnya. Demikian pula GridSearchCV, yang membaca konfigurasi lewat get_params() dan menyetel ulang lewat set_params() — kita akan memanfaatkannya di section Evaluasi dan Validasi Model.
Membuktikan Kontrak dengan Kode #
Klaim-klaim di atas bisa diverifikasi, bukan sekali dimaklumi. File kontrak-estimator.py berikut melatih LogisticRegression pada data kecil, lalu menyelidiki objeknya: apakah fit benar-benar mengembalikan objek yang sama, apa bentuk keluaran predict, parameter apa saja yang dipelajari, dan bagaimana sisi transformer dari kontrak bekerja lewat StandardScaler.
# Kontrak estimator scikit-learn: fit() mengembalikan objek yang sama,
# predict() menghasilkan array, dan parameter hasil belajar berakhiran "_".
# Semua estimator scikit-learn menaati aturan yang sama seperti di bawah ini.
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
# Data klasifikasi kecil: 10 titik 2D membentuk dua kelompok terpisah.
X = np.array(
[
[1.0, 2.0],
[1.5, 1.8],
[2.0, 3.0],
[1.2, 2.5],
[2.5, 2.2],
[6.0, 7.0],
[6.5, 6.2],
[7.0, 7.5],
[6.2, 8.0],
[7.5, 6.8],
]
)
y = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1])
model = LogisticRegression()
# 1. fit() mengembalikan dirinya sendiri (bukan objek baru).
hasil_fit = model.fit(X, y)
print(f"fit() mengembalikan objek yang sama: {hasil_fit is model}")
# 2. predict() selalu mengembalikan array sepanjang jumlah baris X.
prediksi = model.predict(X)
print(f"predict(X) -> bentuk {prediksi.shape}, isi {prediksi.tolist()}")
# 3. Parameter yang DIPELAJARI tersimpan di atribut berakhiran garis bawah.
print(f"coef_ = [{model.coef_[0][0]:.3f}, {model.coef_[0][1]:.3f}]")
print(f"intercept_ = {model.intercept_[0]:.3f}")
# 4. get_params() mengekspos semua hyperparameter (diatur KITA, bukan dipelajari).
params = model.get_params()
print(f"jumlah hyperparameter: {len(params)}")
print(f"daftar kunci : {', '.join(sorted(params))}")
# 5. set_params() mengubah hyperparameter tanpa membangun objek baru.
model.set_params(C=0.5)
print(f"set_params(C=0.5) -> C sekarang: {model.get_params()['C']}")
print()
# 6. Sisi lain kontrak: transformer memakai transform, bukan predict.
skala = StandardScaler()
Z = skala.fit_transform(X) # fit + transform digabung dalam satu panggilan
print(f"transformer StandardScaler:")
print(f" mean tiap kolom setelah transform ~ 0 : {np.allclose(Z.mean(axis=0), 0)}")
print(f" std tiap kolom setelah transform ~ 1 : {np.allclose(Z.std(axis=0), 1)}")
print(f" inverse_transform mengembalikan data : {np.allclose(skala.inverse_transform(Z), X)}")
print(f" atribut hasil belajar: mean_ = {skala.mean_[0]:.3f}, {skala.mean_[1]:.3f}")Output yang Dihasilkan:
fit() mengembalikan objek yang sama: True
predict(X) -> bentuk (10,), isi [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
coef_ = [0.739, 0.709]
intercept_ = -6.397
jumlah hyperparameter: 15
daftar kunci : C, class_weight, dual, fit_intercept, intercept_scaling, l1_ratio, max_iter, multi_class, n_jobs, penalty, random_state, solver, tol, verbose, warm_start
set_params(C=0.5) -> C sekarang: 0.5
transformer StandardScaler:
mean tiap kolom setelah transform ~ 0 : True
std tiap kolom setelah transform ~ 1 : True
inverse_transform mengembalikan data : True
atribut hasil belajar: mean_ = 4.140, 4.700Bedah kode baris demi baris:
- Baris 9–24 (
Xdany): sepuluh titik dua dimensi membentuk dua kelompok terpisah — lima titik di sekitar(1–2, 2–3)berkelas 0 dan lima titik di sekitar(6–7, 6–8)berkelas 1. Data selengkap ini cukup untuk regresi logistik belajar tanpa peringatan konvergensi. - Baris 26, 28–30 (
hasil_fit is model): pemanggilanfit()TIDAK menghasilkan objek baru; ia memodifikasimodeldi tempat lalu mengembalikan referensi yang sama, dibuktikan operatorisyang mencetakTrue. Nilai balikselfinilah yang membuat pemanggilan berantai sepertiLogisticRegression().fit(X, y).predict(X)sah secara sintaksis. - Baris 32–34 (
predict): keluaranpredictselalu berupa array sepanjang jumlah barisX— di sini bentuk(10,)dengan isi[0, 0, 0, 0, 0, 1, 1, 1, 1, 1], tepat mengikuti pola dua kelompok. Model tidak pernah mengembalikan dirinya sendiri daripredict; data masuk, prediksi keluar. - Baris 36–38 (
coef_,intercept_): dua atribut inilah parameter hasil belajar — bobot tiap fitur dan titik potongnya. Regresi logistik memakainya untuk menghitung probabilitas kelas. Nilainya (0,739; 0,709; −6,397) muncul darifit(), bukan dari kita. - Baris 40–43 (
get_params): lima belas kunci hyperparameter terbaca —C,penalty,solver,max_iter, dan sebagainya. Inilah daftar tuas yang bisa kita putar;GridSearchCVmembaca daftar persis ini saat mencari kombinasi terbaik. - Baris 45–47 (
set_params):Cdiubah menjadi 0,5 tanpa membangun objek baru — objek yang sama kini membawa konfigurasi berbeda dan siap dilatih ulang. - Baris 50–57 (
StandardScaler): sisi transformer dari kontrak.fit_transformmempelajari rata-rata dan simpangan tiap kolom lalu langsung menerapkan transformasinya; hasilZmemiliki rata-rata ≈ 0 dan simpangan ≈ 1 (dibuktikannp.allcloseyang mencetakTrue).inverse_transformmengembalikan data asli secara utuh, dan rata-rata hasil belajar tersimpan di atributmean_— sekali lagi berakhiran garis bawah.
Aturan Garis Bawah: Pemisah Parameter dan Konfigurasi #
Konvensi penamaan scikit-learn tegas: atribut berakhiran _ hanya ada setelah fit() dijalankan. coef_ dan intercept_ milik regresi logistik, cluster_centers_ milik KMeans, classes_ milik classifier — semuanya adalah parameter yang dipelajari dari data. Sebaliknya, n_neighbors, C, atau n_clusters tanpa garis bawah adalah hyperparameter yang tetap tersimpan sejak konstruktor dipanggil, bahkan sebelum model melihat satu baris data pun.
Kontrak fit/predict kini sudah menjadi refleks, dan kita tahu persis apa yang tersimpan di dalam objek model. Namun satu jebakan besar masih menunggu di depan: model yang tampil sempurna pada data latih belum tentu baik pada data baru. Fenomena menghafal-dan-gagal itulah bahasan Chapter Overfitting dan Underfitting.
Referensi Resmi #
- Rolling your own estimator — scikit-learn Developer Guide — spesifikasi resmi kontrak estimator, sumber utama chapter ini.
- sklearn.linear_model.LogisticRegression — API Reference
— daftar parameter dan atribut
coef_/intercept_yang diperiksa pada contoh. - sklearn.preprocessing.StandardScaler — API Reference
— dokumentasi transformer yang memperagakan
transformdaninverse_transform. - Pipeline dan Composite estimators — scikit-learn User Guide
— bagaimana kontrak estimator menjadi fondasi
Pipeline.