Cara Split Data Latih dan Data Uji yang Benar
Kamu sudah bersih-bersih data, menghapus kolom aneh, dan mengisi nilai kosong. Model dilatih, akurasinya 0,97. Lalu kamu coba ke data baru dan hasilnya jatuh ke 0,6. Kejadian ini hampir selalu berasal dari satu langkah yang dikerjakan terlalu cepat: membagi data. Cara split data latih dan data uji menentukan apakah angka evaluasimu bisa dipercaya atau cuma ilusi.
Berikut urutan langkah yang saya pakai, termasuk bagian yang paling sering terlewat.
Bagi data sebelum melakukan apa pun pada fitur
Kesalahan paling umum: normalisasi, imputasi, atau seleksi fitur dikerjakan dulu ke seluruh dataset, baru dibagi. Akibatnya, statistik dari data uji ikut merembes ke data latih. Ini yang disebut kebocoran data (data leakage).
Aturannya sederhana. Pisahkan dulu, olah kemudian. Proses olah data hanya boleh “belajar” dari data latih, lalu diterapkan ke data uji dengan parameter yang sama.
from sklearn.model_selection import train_test_split
X_latih, X_uji, y_latih, y_uji = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
Kalau kamu mengikuti langkah di cara menangani data hilang sebelum melatih model, pindahkan proses pengisian nilai kosong ke dalam pipeline agar hanya memakai nilai dari data latih.
Pilih proporsi yang masuk akal untuk ukuran datamu
Angka 80:20 bukan aturan wajib. Yang menentukan adalah jumlah baris dan seberapa tidak seimbang kelasnya.
- Dataset besar (ratusan ribu baris ke atas): 90:10 atau 95:5 sudah cukup. Data uji 10 ribu baris tetap mewakili.
- Dataset sedang (ribuan sampai puluhan ribu baris): 80:20 jadi titik seimbang.
- Dataset kecil (di bawah 1.000 baris): 70:30 atau gunakan validasi silang, karena data uji 200 baris terlalu rentan berubah hasilnya hanya karena kebetulan pembagian.
Kalau kelasmu jarang, misalnya 3% kasus positif, pembagian acak biasa bisa membuat data latih hampir tidak punya contoh positif. Parameter stratify memaksa proporsi kelas tetap sama di kedua bagian.
Pakai data validasi, jangan mengintip data uji
Banyak pemula mengatur hyperparameter berulang kali sambil melihat skor data uji. Setiap kali kamu menyesuaikan parameter berdasarkan hasil data uji, data uji itu perlahan berubah jadi data latih. Skornya naik, tapi bukan karena modelnya membaik.
Solusinya pisahkan tiga bagian: latih, validasi, uji. Data validasi dipakai untuk memilih parameter. Data uji dibuka sekali saja di akhir.
X_sisa, X_uji, y_sisa, y_uji = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
X_latih, X_val, y_latih, y_val = train_test_split(
X_sisa, y_sisa, test_size=0.25, random_state=42, stratify=y_sisa
)
Dengan pembagian ini, data latih 60%, validasi 20%, uji 20%. Angka pastinya kurang penting dibandingkan disiplin memakai masing-masing bagian sesuai fungsinya.
Selalu set random_state agar hasil bisa diulang
Tanpa random_state, setiap kali kode dijalankan, isi data latih dan data uji berubah. Kamu tidak bisa membandingkan dua model secara adil karena keduanya diuji pada data yang berbeda.
Tetapkan satu angka, catat di laporan, dan pakai konsisten. Angka berapa pun boleh. Yang penting sama untuk semua percobaan dalam satu proyek.
Gunakan validasi silang saat data terbatas
Membagi sekali hanya memberi satu angka evaluasi. Angka itu bisa kebetulan bagus atau kebetulan buruk. Validasi silang (cross-validation) membagi data menjadi beberapa lipatan, melatih model berkali-kali, dan melaporkan rata-rata plus sebarannya.
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(max_iter=1000)
skor = cross_val_score(model, X_latih, y_latih, cv=5, scoring="f1")
print(skor.mean(), skor.std())
Perhatikan nilai std-nya. Kalau standar deviasinya besar, artinya performa model tidak stabil di berbagai potongan data, dan itu informasi yang tidak akan kamu dapat dari satu kali split.
Kenali jebakan khusus data deret waktu
Untuk data yang punya urutan waktu seperti penjualan harian atau log sensor, pembagian acak justru merusak. Model bisa belajar dari data bulan depan untuk memprediksi bulan ini.
Gunakan pembagian berdasarkan waktu: data lama untuk latih, data terbaru untuk uji. Di scikit-learn, TimeSeriesSplit menangani ini dengan membuat lipatan yang bergerak maju.
Periksa data uji sebelum percaya hasilnya
Sebelum melaporkan akurasi, bandingkan distribusi kolom penting di data latih dan data uji. Kalau rata-rata usia di data latih 34 tahun sementara di data uji 52 tahun, keduanya bukan sampel dari populasi yang sama dan skor ujimu tidak bermakna.
Cek juga jumlah baris duplikat. Baris yang sama muncul di data latih dan data uji membuat model seolah hafal jawabannya. Hapus duplikat sebelum membagi.
Setelah pembagian rapi, langkah berikutnya adalah memilih angka yang tepat untuk menilai hasilnya, seperti dibahas di cara memilih metrik evaluasi model klasifikasi. Skor yang bagus dari pembagian yang salah hanya menunda masalah.
Ringkasan
Bagi data sebelum mengolah fitur, pilih proporsi sesuai ukuran dataset, pakai stratifikasi untuk kelas tidak seimbang, sediakan data validasi terpisah, dan set random_state. Untuk data terbatas atau data berurutan waktu, ganti pembagian tunggal dengan validasi silang atau pembagian kronologis.
Pertanyaan yang Sering Diajukan
Apakah data uji boleh dipakai lebih dari sekali?
Idealnya sekali, di akhir proses. Kalau kamu memeriksa data uji berkali-kali sambil mengubah model, kamu tanpa sadar menyesuaikan model dengan data itu. Pakai data validasi untuk semua percobaan, lalu buka data uji sekali untuk laporan akhir.
Berapa ukuran data uji minimal?
Tidak ada angka baku, tapi data uji dengan kurang dari seratus baris mudah berubah hasilnya hanya karena kebetulan. Kalau datasetmu sekecil itu, validasi silang memberi gambaran yang lebih stabil daripada satu kali split.
Bagaimana kalau data punya kelompok, misalnya banyak baris dari pasien yang sama?
Pastikan semua baris dari kelompok yang sama masuk ke sisi yang sama, jangan terpecah antara latih dan uji. Scikit-learn menyediakan GroupShuffleSplit untuk kasus ini. Kalau tidak, model bisa mengenali pola milik individu tertentu, bukan pola yang berlaku umum.


