Dasar Pipeline

Merangkai transformer dan estimator menjadi satu alur.

Daftar isi

Pipeline adalah objek scikit-learn yang merangkai langkah-langkah praproses dan satu model menjadi satu kesatuan yang dilatih dan digunakan sebagaimana estimator biasa. Topik ini membahas bentuk langkah di dalam Pipeline, alur fit dan predict yang berjalan dalam satu pintu, bentuk ringkas make_pipeline, serta cara mengakses langkah yang sudah dirangkai. Setelah membacanya, praproses dan pemodelan dapat dipindahkan dari dua objek terpisah menjadi satu objek tunggal dengan satu panggilan fit.

Langkah sebagai pasangan nama dan objek#

Pipeline dibangun dari daftar langkah, yaitu daftar pasangan berupa nama dan objek yang disusun sesuai urutan eksekusinya. Parameter steps menerima daftar tersebut, misalnya [("scaler", StandardScaler()), ("clf", LogisticRegression())] untuk merangkai scaling lalu regresi logistik. Nama berupa string yang unik di dalam satu Pipeline dan menjadi alamat langkah ketika objeknya perlu diakses kembali. Susunan dua elemen inilah bentuk paling umum, meskipun jumlah langkahnya boleh lebih banyak sesuai kebutuhan praproses.

Aturan penyusunannya tegas. Semua langkah sebelum terakhir wajib berupa transformer, yaitu objek yang memiliki pasangan metode fit dan transform sehingga keluarannya dapat diteruskan ke langkah berikutnya. Langkah terakhir wajib berupa estimator, yaitu objek yang mempelajari pola dari data dan menyediakan predict, seperti classifier atau regressor. Apabila langkah tengah tidak memiliki transform, proses fit langsung gagal dengan error TypeError yang pesannya menyatakan “All intermediate steps should be transformers”. Error ini muncul pada saat kode dijalankan, bukan sesudah model digunakan, sehingga kesalahan susunan cepat ketahuan.

Pembagian peran tersebut menjelaskan desainnya. Transformer di tengah hanya menyiapkan data dan tidak boleh menyerap label, sedangkan estimator di ujung menjadi satu-satunya tempat pembelajaran terhadap target terjadi. Konsekuensinya, seluruh Pipeline dapat diperlakukan sebagai satu estimator besar, lengkap dengan parameter yang dirangkai dari parameternya masing-masing.

Alur fit dan predict dalam satu pintu#

Saat fit dipanggil pada Pipeline, data mengalir berantai dari kiri ke kanan. Setiap transformer menjalankan fit untuk mempelajari parameternya dari data yang masuk, kemudian mentransformasikan data yang sama dan menyerahkan hasilnya ke langkah berikutnya. Estimator terakhir menerima data yang sudah ditransformasi seluruhnya dan melakukan pembelajaran terhadap label. Saat predict, predict_proba, atau score dipanggil, alurnya berbeda pada satu titik, yaitu transformer hanya menjalankan transform tanpa fit dan tetap menggunakan parameter yang dipelajari sebelumnya. Diagram berikut merangkum kedua alur tersebut pada Pipeline dua langkah.

Data fiturmentahPipelineStandardScalertransformerLogisticRegressionestimatorPrediksikelasfit(): tiap transformer mempelajari parameternya, lalu mentransform data berantaipredict(): transform dijalankan otomatis sebelum estimator menghasilkan prediksi
Rantai dua langkah di dalam Pipeline beserta alur fit dan predict

Karena transform otomatis terjadi pada setiap panggilan, pemanggil Pipeline tidak pernah menyentuh data antara secara langsung. Kontrak yang diikuti Pipeline pun sama dengan estimator lain, yaitu fit untuk belajar, predict untuk menebak, predict_proba untuk peluang per kelas, dan score untuk penilaian pada data berlabel. Kode yang ditulis untuk estimator biasa tetap bekerja tanpa penyesuaian.

Pipeline pada dataset iris#

Contoh berikut merangkai StandardScaler dan LogisticRegression menjadi satu objek, melatihnya pada dataset iris, dan menilainya pada data uji.

python pipeline-iris.py
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# dataset iris bawaan scikit-learn, 150 baris dan 4 fitur
X, y = load_iris(return_X_y=True)

# pemecahan data latih dan data uji dengan random_state tetap
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42, stratify=y
)

# pipeline dua langkah, diakhiri estimator
model = Pipeline(steps=[
    ("scaler", StandardScaler()),
    ("clf", LogisticRegression(max_iter=1000)),
])

# satu panggilan fit: tiap transformer di-fit lalu mentransform data,
# kemudian estimator terakhir di-fit
model.fit(X_train, y_train)

# score menjalankan transform pada scaler sebelum predict pada clf
print(f"Akurasi test: {model.score(X_test, y_test):.3f}")
print("Langkah pipeline:", model.named_steps)
print("Bentuk koefisien clf:", model.named_steps["clf"].coef_.shape)
text Keluaran
Akurasi test: 0.921
Langkah pipeline: {'scaler': StandardScaler(), 'clf': LogisticRegression(max_iter=1000)}
Bentuk koefisien clf: (3, 4)

Keluaran memperlihatkan satu objek yang melakukan semuanya. Nilai akurasi 0.921 diperoleh dari 38 baris data uji yang disisakan oleh train_test_split dengan stratify=y, sehingga proporsi tiga kelasnya tetap seimbang. Pemanggilan score pada Pipeline secara otomatis mentransformasi X_test menggunakan scaler yang dipelajari dari X_train, baru kemudian memanggil predict pada clf. Kamus named_steps pada baris kedua menampilkan kedua langkah beserta objeknya, dan bentuk koefisien (3, 4) berarti tiga kelas terhadap empat fitur hasil scaling.

make_pipeline dengan nama otomatis#

Menuliskan pasangan nama secara manual wajar dilakukan, tetapi make_pipeline menyediakan bentuk yang lebih ringkas. Fungsi ini menerima objek langkah tanpa nama, lalu menurunkan namanya dari nama kelas masing-masing dengan huruf kecil. Isi yang dihasilkan identik dengan Pipeline eksplisit, sehingga pemilihan bentuknya menjadi perkara keterbacaan.

python Contoh: make_pipeline tanpa nama manual
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

# make_pipeline memberi nama langkah secara otomatis dari nama kelasnya
model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
print(model)
print("Nama otomatis langkah pertama:", model.steps[0][0])
text Keluaran
Pipeline(steps=[('standardscaler', StandardScaler()),
                ('logisticregression', LogisticRegression(max_iter=1000))])
Nama otomatis langkah pertama: standardscaler

Tampilan repr pada keluaran menegaskan bahwa make_pipeline menghasilkan objek Pipeline yang sama, lengkap dengan nama standardscaler dan logisticregression hasil penurunan otomatis. Apabila kelas yang sama muncul dua kali, scikit-learn menambahkan nomor urut seperti standardscaler-1 agar nama tetap unik. Akses model.steps[0][0] memperlihatkan bentuk lain dari daftar langkah, yaitu pasangan nama dan objek yang dapat diindeks.

Nama langkah juga menjadi awalan parameter ketika Pipeline ditala. Pada GridSearchCV, parameter C milik LogisticRegression di dalam contoh di atas ditulis sebagai clf__C, dengan dua garis bawah sebagai pemisah antara nama langkah dan nama parameter. Nama yang bermakna membuat daftar parameter hasil penalaan tetap mudah dibaca.

Mengakses langkah lewat named_steps#

Atribut named_steps bersifat seperti kamus yang memetakan nama langkah ke objeknya, sehingga model.named_steps["clf"] mengembalikan estimator LogisticRegression di dalam contoh iris. Setiap atribut objek tersebut dapat dibaca langsung, seperti coef_ untuk koefisien atau n_features_in_ untuk jumlah fitur masukan. Cara ini menjadi pintu utama pemeriksaan model yang sudah terbungkus.

Alternatifnya adalah atribut steps, yaitu daftar pasangan aslinya. model.steps[0] mengembalikan tuple ("scaler", StandardScaler()), sehingga objeknya berada pada indeks kedua, model.steps[0][1]. scikit-learn juga mendukung pemotongan (slicing) dengan notasi model[:-1], yang mengembalikan Pipeline baru tanpa estimator terakhir dan berguna untuk memeriksa data hasil transformasi. Ketiganya alat membaca, sedangkan penggantian langkah dilakukan melalui parameter steps saat objek dibangun.

Kesalahan umum#

  • Menempatkan estimator di tengah rantai. Langkah tengah yang tidak memiliki metode transform membuat fit gagal dengan error TypeError tentang langkah perantara. Perbaikannya dengan menata ulang steps agar objek tanpa transform hanya berada di posisi terakhir.
  • Menganggap Pipeline mengubah perilaku model. Pipeline hanya mengatur urutan eksekusi, sedangkan model di ujungnya berperilaku sama dengan versi berdiri sendiri. Skor yang berbeda biasanya berasal dari perbedaan data yang diterima model, misalnya scaling yang ikut atau tidak ikut.
  • Mengulang nama langkah. Nama yang sama pada dua langkah membuat named_steps tidak dapat membedakannya dan akses berdasarkan nama menjadi ambigu. Perbaikannya dengan nama unik yang menggambarkan peran tiap langkah.

Ringkasan#

  • Pipeline menyimpan langkah sebagai daftar pasangan nama dan objek, dengan transformer pada seluruh posisi sebelum terakhir dan estimator pada posisi terakhir.
  • Satu panggilan fit menjalankan fit dan transform berantai pada transformer, lalu fit pada estimator, sedangkan predict dan score hanya menjalankan transform berantai sebelum prediksi.
  • make_pipeline menghasilkan objek yang sama dengan nama langkah otomatis dari nama kelasnya.
  • Akses langkah dilakukan melalui named_steps, daftar steps, atau pemotongan seperti model[:-1].

Referensi#