Train / Test / Validasi Set Memisahkan di Sklearn

59

Bagaimana saya bisa membagi secara acak sebuah matriks data dan vektor label yang sesuai menjadi X_train, X_test, X_val, y_train, y_test, y_val dengan Sklearn? Sejauh yang saya tahu, sklearn.cross_validation.train_test_splithanya mampu membelah menjadi dua, bukan dalam tiga ...

Hendrik
sumber

Jawaban:

81

Anda bisa menggunakan sklearn.model_selection.train_test_splitdua kali saja. Pertama untuk membagi untuk melatih, menguji dan kemudian membagi lagi kereta ke validasi dan melatih. Sesuatu seperti ini:

 X_train, X_test, y_train, y_test 
    = train_test_split(X, y, test_size=0.2, random_state=1)

 X_train, X_val, y_train, y_val 
    = train_test_split(X_train, y_train, test_size=0.2, random_state=1)
hh32
sumber
1
Ya, ini bekerja tentu saja tetapi saya berharap untuk sesuatu yang lebih elegan;) Sudahlah, saya menerima jawaban ini.
Hendrik
1
Saya ingin menambahkan bahwa jika Anda ingin menggunakan set validasi untuk mencari parameter hiper terbaik, Anda dapat melakukan hal berikut setelah pemisahan: gist.github.com/albertotb/1bad123363b186267e3aeaa26610b54b
skd
12
Jadi apa proporsi kereta, tes, validasi terakhir dalam contoh ini? Karena pada yang kedua train_test_split , Anda melakukan ini selama 80/20 sebelumnya. Jadi val Anda adalah 20% dari 80%. Proporsi pembagian tidak terlalu mudah dengan cara ini.
Monica Heddneck
1
Saya setuju dengan @Monica Heddneck bahwa kereta 64%, validasi 16% dan tes splt 20% bisa lebih jelas. Ini inferensi menyebalkan yang harus Anda buat dengan solusi ini.
Perry
33

Ada jawaban yang bagus untuk pertanyaan ini pada SO yang menggunakan numpy dan panda.

Perintah (lihat jawaban untuk diskusi):

train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))])

menghasilkan pemisahan 60%, 20%, 20% untuk pelatihan, validasi, dan set tes.

0_0
sumber
2
Saya bisa melihat .6artinya 60% ... tapi apa .8artinya?
Tom Hale
1
@ TomHale np.splitakan membagi 60% dari panjang array yang dikocok, kemudian 80% dari panjang (yang merupakan 20% dari data tambahan), sehingga menyisakan 20% dari data yang tersisa. Ini karena definisi fungsi. Anda dapat menguji / bermain dengan x = np.arange(10.0)np.split(x, [ int(len(x)*0.6), int(len(x)*0.8)])
:,
3

Paling sering Anda akan menemukan diri Anda tidak membelahnya sekali tetapi pada langkah pertama Anda akan membagi data Anda dalam satu set pelatihan dan tes. Selanjutnya Anda akan melakukan pencarian parameter yang menggabungkan splitting yang lebih kompleks seperti validasi silang dengan algoritma 'split k-fold' atau 'leave-one-out (LOO)'.

JLT
sumber
3

Anda bisa menggunakan train_test_splitdua kali. Saya pikir ini yang paling mudah.

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=1)
X_train, X_val, y_train, y_val = train_test_split(
    X_train, y_train, test_size=0.25, random_state=1)

Dengan cara ini, train, val, testset akan 60%, 20%, 20% dari dataset masing-masing.

David Jung
sumber
2

Jawaban terbaik di atas tidak menyebutkan bahwa dengan memisahkan dua kali menggunakan train_test_splittidak mengubah ukuran partisi tidak akan memberikan partisi yang dimaksud:

x_train, x_remain = train_test_split(x, test_size=(val_size + test_size))

Kemudian bagian dari validasi dan set tes di x_remain berubah dan bisa dihitung sebagai

new_test_size = np.around(test_size / (val_size + test_size), 2)
# To preserve (new_test_size + new_val_size) = 1.0 
new_val_size = 1.0 - new_test_size

x_val, x_test = train_test_split(x_remain, test_size=new_test_size)

Dalam kesempatan ini semua partisi awal disimpan.

A.Ametov
sumber
1

Berikut pendekatan lain (mengasumsikan pembagian tiga arah yang sama):

# randomly shuffle the dataframe
df = df.reindex(np.random.permutation(df.index))

# how many records is one-third of the entire dataframe
third = int(len(df) / 3)

# Training set (the top third from the entire dataframe)
train = df[:third]

# Testing set (top half of the remainder two third of the dataframe)
test = df[third:][:third]

# Validation set (bottom one third)
valid = df[-third:]

Ini bisa dibuat lebih ringkas tetapi saya tetap menggunakannya untuk tujuan penjelasan.

Vishal
sumber
0

Diberikan train_frac=0.8, fungsi ini menciptakan pemisahan 80% / 10% / 10%:

import sklearn

def data_split(examples, labels, train_frac, random_state=None):
    ''' https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html
    param data:       Data to be split
    param train_frac: Ratio of train set to whole dataset

    Randomly split dataset, based on these ratios:
        'train': train_frac
        'valid': (1-train_frac) / 2
        'test':  (1-train_frac) / 2

    Eg: passing train_frac=0.8 gives a 80% / 10% / 10% split
    '''

    assert train_frac >= 0 and train_frac <= 1, "Invalid training set fraction"

    X_train, X_tmp, Y_train, Y_tmp = sklearn.model_selection.train_test_split(
                                        examples, labels, train_size=train_frac, random_state=random_state)

    X_val, X_test, Y_val, Y_test   = sklearn.model_selection.train_test_split(
                                        X_tmp, Y_tmp, train_size=0.5, random_state=random_state)

    return X_train, X_val, X_test,  Y_train, Y_val, Y_test
Tom Hale
sumber
0

Menambahkan ke jawaban @ hh32 , sambil menghormati proporsi yang telah ditentukan sebelumnya seperti (75, 15, 10):

train_ratio = 0.75
validation_ratio = 0.15
test_ratio = 0.10

# train is now 75% of the entire data set
# the _junk suffix means that we drop that variable completely
x_train, x_test, y_train, y_test = train_test_split(dataX, dataY, test_size=1 - train_ratio)

# test is now 10% of the initial data set
# validation is now 15% of the initial data set
x_val, x_test, y_val, y_test = train_test_split(x_test, y_test, test_size=test_ratio/(test_ratio + validation_ratio)) 

print(x_train, x_val, x_test)
Andrei Florea
sumber
0

Perpanjangan jawaban @ hh32 dengan rasio yang diawetkan.

# Defines ratios, w.r.t. whole dataset.
ratio_train = 0.8
ratio_val = 0.1
ratio_test = 0.1

# Produces test split.
x_remaining, x_test, y_remaining, y_test = train_test_split(
    x, y, test_size=test_ratio)

# Adjusts val ratio, w.r.t. remaining dataset.
ratio_remaining = 1 - ratio_test
ratio_val_adjusted = ratio_val / ratio_remaining

# Produces train and val splits.
x_train, x_val, y_train, y_val = train_test_split(
    x_remaining, y_remaining, test_size=ratio_val_adjusted)

Karena dataset yang tersisa berkurang setelah pemisahan pertama, rasio baru sehubungan dengan dataset yang dikurangi harus dihitung dengan menyelesaikan persamaan:

RremainingRnew=Rold

Jorge Barrios
sumber