Pembagian train, validation, dan test adalah disiplin yang menjaga evaluasi model tetap jujur, yaitu setiap keputusan dilakukan pada data yang berbeda dari data yang mengukur keberhasilannya. Topik ini menetapkan peran masing-masing bagian, menunjukkan pembagiannya dengan kode, dan membahas kebocoran data sebagai kegagalan paling berbahaya dari disiplin ini. Setelah selesai, seluruh eksperimen pada sisa jalur memakai tata pembagian yang sama.
Tiga peran yang tidak boleh bercampur#
Data pelatihan dipakai optimizer untuk menyesuaikan parameter. Data validasi dipakai untuk keputusan yang menyertai pelatihan, seperti memilih jumlah epoch terbaik, menala learning rate, atau membandingkan dua arsitektur. Data test menyimpan jawaban akhir dan sebaiknya hanya disentuh sekali, yaitu ketika model final sudah ditetapkan, karena angka test yang dilihat berulang kali secara perlahan berubah menjadi data validasi dan kejujurannya hilang.
Analogi yang tepat berasal dari dunia ujian, yaitu data pelatihan sebagai soal latihan berpembahasan, data validasi sebagai ujian coba yang menuntun penalaan, dan data test sebagai ujian akhir yang dikerjakan sekali. Melatih pada test sama dengan mengerjakan ujian akhir berulang-ulang sampai hafal, dan kinerjanya tidak lagi berkata apa-apa tentang kemampuan pada data baru. Proporsi pembagian yang lazim adalah 70 sampai 80 persen untuk pelatihan, dengan sisanya terbagi ke validasi dan test, dan dataset raksasa dapat menyisakan satu persen saja untuk test tanpa mengurangi keandalannya.
Membagi data dengan benar dalam kode#
Pada PyTorch, pembagian acak yang dapat direproduksi dilakukan dengan random_split dan generator yang diberi benih. Kode berikut membagi dua puluh contoh menjadi dua belas, empat, dan empat, lalu memverifikasi bahwa ketiganya saling lepas dan totalnya pas.
import torch
from torch.utils.data import random_split
data = list(range(20))
generator = torch.Generator().manual_seed(42)
train, val, test = random_split(data, [12, 4, 4], generator=generator)
print("ukuran:", len(train), len(val), len(test))
print("indeks test:", sorted(test.indices))
semua = sorted(train.indices + val.indices + test.indices)
print("lepas & total:", semua == list(range(20)))ukuran: 12 4 4
indeks test: [5, 9, 16, 19]
lepas & total: TrueDua pengecualian menuntut perlakuan berbeda dari pembagian acak. Data deret waktu tidak boleh diacak pada pembagiannya karena contoh masa depan tidak boleh berada di pelatihan, sehingga pembagiannya kronologis, misalnya tahun pertama hingga kedelapan untuk pelatihan dan sisanya untuk evaluasi. Data yang tidak seimbang antar kelas menguntungkan pembagian berstrata, yaitu proporsi kelas yang dipertahankan sama di setiap bagian, dan pustaka seperti scikit-learn menyediakannya lewat opsi stratify pada train_test_split.
Kebocoran data: kegagalan yang diam#
Kebocoran data (data leakage) adalah kebocoran informasi dari data evaluasi ke proses pelatihan, dan bentuknya paling sering justru berupa kode yang tampak tidak berbahaya. Contoh utamanya adalah normalisasi yang statistiknya, yaitu rata-rata dan simpangan baku, dihitung dari seluruh dataset sebelum pembagian, sehingga data test telah memengaruhi skala pelatihan. Cara yang benar adalah menghitung statistik dari data pelatihan saja, lalu menerapkan transformasi yang sama ke validasi dan test.
Bentuk lain yang sering terjadi meliputi penghapusan duplikat setelah pembagian sehingga contoh yang sama ada di dua sisi, pembagian acak pada data yang dikelompokkan seperti rekaman yang sama dari satu pasien, serta pemilihan fitur berdasarkan seluruh data. Semuanya memberi model jendela kecil ke data test, dan angkanya terlihat bagus persis saat keandalannya rusak. Pemeriksaan yang menolong adalah menghitung ulang statistik transformasi hanya dari train dan menanyakan asal setiap keputusan preprocessing.
Kode berikut memeragakan selisih statistik antara normalisasi yang bocor dan yang benar pada data kecil, sehingga ukuran dampaknya terlihat nyata.
import torch
torch.manual_seed(0)
semua = torch.randn(1000) * 3.0 + 10.0
train = semua[:800]
rata_bocor = semua.mean()
rata_bersih = train.mean()
print("rata-rata seluruh data :", round(rata_bocor.item(), 4))
print("rata-rata train saja :", round(rata_bersih.item(), 4))
print("selisih :", round(abs(rata_bocor - rata_bersih).item(), 4))rata-rata seluruh data : 10.0868
rata-rata train saja : 10.1954
selisih : 0.1087Selisihnya kecil pada contoh ini, tetapi itulah sifat kebocoran pada umumnya, yaitu tidak menyebabkan error dan hanya menggeser angka evaluasi ke arah yang terlalu optimistis. Pada skala produksi, pergeseran kecil tersebut cukup untuk membuat peringkat dua model saling terbalik.
Kaidah kerja yang dipakai sepanjang jalur#
Kaidah kerjanya dapat diringkas menjadi tiga. Pertama, pisahkan data sebelum transformasi apa pun yang menyimpan statistik, dan terapkan kembali transformasinya dengan statistik train. Kedua, simpan keputusan penalaan untuk data validasi dan jadikan data test sebagai pengukuran akhir yang dipanggil sekali. Ketiga, tuliskan benih generator pembagian pada catatan eksperimen, sebagaimana dibahas pada topik Pelacakan eksperimen, karena hasil yang tidak dapat direproduksi sama sulitnya dinilai dengan hasil yang tidak jujur.
Ketiga kaidah ini berlaku tanpa berubah ketika datanya berupa citra, teks, maupun deret waktu, yang hanya membedakan cara memilih indeks pembagiannya. Modul Jaringan konvolusional dan Model sekuens menerapkannya kembali pada konteks masing-masing.
Ringkasan#
- Train melatih parameter, validasi menuntun keputusan penalaan, dan test diukur sekali pada model final.
random_splitdengan generator berbenih memberi pembagian acak yang dapat direproduksi, sementara deret waktu memakai pembagian kronologis.- Kebocoran paling sering lahir dari statistik transformasi yang dihitung dari seluruh data, dan gejalanya adalah angka evaluasi yang terlalu optimistis tanpa error apa pun.
- Benih pembagian dicatat sebagai bagian dari reproduktibilitas eksperimen.
Referensi#
- Model Selection, Underfitting, and Overfitting — Dive into Deep Learning — Bab yang membahas peran data validasi dan kesalahan pembagian.
- train_test_split — scikit-learn — Dokumentasi yang memuat opsi stratify untuk pembagian berstrata.
- torch.utils.data — PyTorch
— Dokumentasi
random_splitbeserta perilaku generatornya.