Kebocoran data (data leakage) terjadi ketika informasi dari data uji atau dari masa depan menyusup ke proses pelatihan. Model yang bocor menampilkan angka evaluasi yang membaik secara palsu, lalu kinerjanya turun begitu digunakan pada data nyata. Topik ini merinci penyebab yang paling umum, menunjukkan mekanismenya pada dataset bawaan scikit-learn, dan menutup dengan pencegahan melalui disiplin pemecahan serta pipeline, yaitu objek yang menyatukan langkah transformasi dan model.
Penyebab umum kebocoran data#
Sumber kebocoran paling sering bukan kode yang gagal, melainkan langkah yang dieksekusi dengan benar pada data yang keliru. Empat pola berikut muncul berulang kali pada proyek nyata. Semuanya berpangkal pada hal yang sama, yaitu informasi yang seharusnya tersembunyi ikut digunakan selama pelatihan.
- Preprocessing yang di-fit sebelum pemecahan. Statistik seperti rata-rata dan deviasi standar pada
StandardScaler, statistik pengisian nilai hilang, maupun seleksi fitur dihitung dari seluruh dataset bila transformasi dijalankan lebih dahulu. Baris data uji ikut terhitung di dalam statistik tersebut, padahal baris itu seharusnya tidak terlihat sama sekali. - Fitur yang memuat informasi target. Kolom hasil pemeriksaan akhir pada data diagnosa hanya tersedia setelah diagnosis diketahui, sehingga kolom itu tidak boleh menjadi fitur. Penanda seperti
idyang bertambah seiring waktu juga menyandikan urutan kejadian dan memberi petunjuk tentang target. - Pemisahan acak pada data berwaktu. Pembagian acak menaruh baris masa depan ke data latih, sehingga model terlanjur melihat kejadian yang seharusnya diprediksi. Data berwaktu dipecah mengikuti urutan waktunya.
- Contoh yang sama muncul di dua himpunan. Baris ganda atau contoh yang nyaris identik, misalnya hasil pemantauan sensor yang berdekatan waktunya, dapat terbagi ke data latih dan data uji sekaligus. Model kemudian dinilai pada soal yang sudah dihafalnya. Karena itu, baris ganda tetap dicek ulang setelah pemecahan.
Eksperimen: dua cara membagi data#
Mekanisme kebocoran dapat diamati dengan membandingkan dua urutan langkah pada dataset yang sama. Skrip berikut menggunakan dataset breast cancer bawaan scikit-learn dan memecahnya satu kali melalui indeks, sehingga kedua cara menggunakan baris latih dan baris uji yang identik. Cara pertama menghitung statistik StandardScaler dari seluruh data, termasuk baris yang kelak menjadi data uji, sedangkan cara kedua menghitungnya dari data latih saja.
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
X, y = load_breast_cancer(return_X_y=True)
# satu pemecahan pada indeks, dipakai bersama oleh kedua cara
idx = np.arange(len(y))
idx_latih, idx_uji = train_test_split(idx, test_size=0.25, random_state=0)
y_latih, y_uji = y[idx_latih], y[idx_uji]
# cara keliru: statistik skaler dihitung dari SELURUH data, lalu data dipecah
skaler_keliru = StandardScaler().fit(X)
X_semua = skaler_keliru.transform(X)
model_keliru = LogisticRegression(max_iter=1000).fit(X_semua[idx_latih], y_latih)
akurasi_keliru = accuracy_score(y_uji, model_keliru.predict(X_semua[idx_uji]))
# cara benar: skaler di-fit HANYA pada data latih, lalu diterapkan ke data uji
skaler_benar = StandardScaler().fit(X[idx_latih])
X_latih_b = skaler_benar.transform(X[idx_latih])
X_uji_b = skaler_benar.transform(X[idx_uji])
model_benar = LogisticRegression(max_iter=1000).fit(X_latih_b, y_latih)
akurasi_benar = accuracy_score(y_uji, model_benar.predict(X_uji_b))
print(f"Rata-rata fitur pertama, skaler keliru : {skaler_keliru.mean_[0]:.4f}")
print(f"Rata-rata fitur pertama, skaler benar : {skaler_benar.mean_[0]:.4f}")
print()
print(f"Akurasi cara keliru : {akurasi_keliru:.4f}")
print(f"Akurasi cara benar : {akurasi_benar:.4f}")
print(f"Selisih (keliru - benar) : {akurasi_keliru - akurasi_benar:.4f}")Rata-rata fitur pertama, skaler keliru : 14.1273
Rata-rata fitur pertama, skaler benar : 14.1592
Akurasi cara keliru : 0.9650
Akurasi cara benar : 0.9580
Selisih (keliru - benar) : 0.0070Rata-rata fitur pertama berbeda antara kedua skaler, yaitu 14.1273 bila seluruh data diikutkan dan 14.1592 bila hanya data latih. Selisihnya kecil, dan kecilnya selisih itu justru yang membuat kebocoran sulit terasa karena tidak ada pesan error maupun angka yang tampak aneh. Akurasi cara keliru 0.9650 berbanding 0.9580 pada cara benar, sehingga satu dari 143 prediksi data uji berubah. Arah biasnya secara umum optimistis karena model menerima statistik yang telah melihat data uji. Pada dataset yang mudah dan relatif besar ini dampaknya memang kecil. Pada data nyata yang lebih kecil, lebih penuh derau, atau memiliki fitur yang berkorelasi kuat, selisihnya dapat jauh lebih besar.
Mendeteksi kebocoran data#
Tanda yang paling khas adalah skor yang terlalu bagus untuk kenyataannya. Kebocoran memberi model informasi yang pada data baru tidak akan pernah tersedia, sehingga selisih antara skor dan kenyataan baru terasa saat model digunakan. Angka evaluasi dibandingkan dengan baseline, yaitu batas mutu dari model paling sederhana, dan dengan hasil yang dilaporkan pada masalah serupa. Lonjakan besar tanpa penjelasan diperlakukan sebagai pertanyaan yang harus dijawab, bukan sebagai kemenangan. Tanda kedua adalah satu fitur yang mendominasi peringkat kepentingan fitur secara tak wajar, terutama bila fitur itu kebetulan menyandikan target atau waktu.
Tanda ketiga muncul setelah model digunakan, yaitu skor uji yang tinggi tetapi kinerja nyata yang jauh lebih rendah. Pemeriksaan yang paling murah dilakukan sebelum pemodelan dimulai, yaitu meninjau setiap kolom dan mempertanyakan ketersediaannya pada saat prediksi dilakukan. Pemeriksaan pendukungnya adalah mencari baris ganda pada data uji setelah pemecahan. Baris uji yang identik dengan data latih membuat model menjawab soal yang sudah dihafalnya, sehingga skor uji tidak lagi mengukur kemampuan menghadapi contoh baru.
Pencegahan dengan pipeline#
Prinsip pencegahannya satu kalimat, yaitu statistik apa pun yang dipelajari dari data hanya boleh menyesuaikan diri dengan data latih. Menjalankan prinsip itu secara manual mudah terlewat pada proyek dengan banyak langkah transformasi, sehingga scikit-learn menyediakan pipeline yang menyatukan transformasi dan model menjadi satu objek. Panggilan fit pada pipeline menyesuaikan setiap tahap hanya dengan data latih, sedangkan panggilan predict menerapkan statistik data latih itu ke data uji.
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import make_pipeline
from sklearn.metrics import accuracy_score
X, y = load_breast_cancer(return_X_y=True)
X_latih, X_uji, y_latih, y_uji = train_test_split(
X, y, test_size=0.25, random_state=0
)
# pipeline menyatukan penskalaan dan model menjadi satu objek
pipeline = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
# fit pada pipeline sekaligus menyesuaikan skaler DAN model pada data latih
pipeline.fit(X_latih, y_latih)
# predict menerapkan statistik data latih ke data uji tanpa menyentuhnya
akurasi = accuracy_score(y_uji, pipeline.predict(X_uji))
print(f"Akurasi pipeline pada data uji : {akurasi:.4f}")Akurasi pipeline pada data uji : 0.9580Angka 0.9580 sama persis dengan cara benar pada eksperimen dua cara di atas, karena pipeline menjalankan urutan yang sama. Keunggulan pipeline bukan pada angka akurasinya, melainkan pada jaminan strukturnya. Urutan fit dan transform sudah terikat di dalam satu objek, sehingga kesalahan lupa memisahkan statistik latih dan uji tidak mungkin terjadi lagi. Pipeline yang sama pula yang ikut tersimpan saat model diserialisasi, sehingga urutan yang benar tidak hilang pada saat model dipindahkan. Jaminan itu juga tidak melemah ketika jumlah langkah transformasi bertambah, karena setiap tahap baru tinggal ditambahkan ke dalam objek yang sama.
Ringkasan#
- Kebocoran data adalah masuknya informasi data uji atau masa depan ke proses pelatihan, dan akibatnya angka evaluasi menjadi optimistis tanpa pesan error apa pun.
- Penyebab yang paling umum adalah preprocessing yang di-fit sebelum pemecahan, fitur yang memuat informasi target, dan pemisahan acak pada data berwaktu.
- Statistik transformasi dihitung dari data latih saja, kemudian diterapkan ke data validasi dan data uji.
- Pipeline scikit-learn mengikat urutan fit dan transform di dalam satu objek, sehingga kesalahan urutan tidak mungkin terjadi lagi.
Referensi#
- Common pitfalls and recommended practices — scikit-learn — Halaman resmi scikit-learn yang membahas kebocoran data dan cara menghindarinya.
- Pipelines and composite estimators — scikit-learn — Panduan pipeline beserta urutan fit dan transform yang dijalankannya.
- sklearn.preprocessing.StandardScaler — scikit-learn — Dokumentasi skaler yang digunakan pada eksperimen dua cara.