1.2 Podział zbioru danych na uczący i testowy
W problemie klasyfikacji, naszym zadaniem jest stworzenie algorytmu (programu), który na podstawie znanych sobie, opisanych wzorców, będzie w stanie efektywnie rozpoznawać wzorce nieopisane i dotąd sobie nieznane.
Potrzebujemy więc znaleźć sposób, aby zapewnić sobie to nieznane i nieopisane niezbędne przeprowadzenia procesu klasyfikacji. Na tę chwilę dysponujemy jedynie spójnym, jednolitym zbiorem danych. Poznajmy więc najpopularniejsze sposoby na jego podział na część wykorzystywaną w uczeniu klasyfikatora (zbiór uczący) i późniejszej klasyfikacji na już wyuczonym klasyfikatorze (zbiór testowy). Wszystkie przydatne nam metody podziału są zaimplementowane w module model_selection
pakietu sklearn
. Zaimportujmy więc w naszym skrypcie ten moduł.
from sklearn import model_selection
Podział prosty
Najprostszym możliwym podejściem jest prosty, losowy podział zbioru na dwie części z zachowaniem jakiejś proporcji pomiędzy nimi. Służy do tego metoda train_test_split
.
Wywołanie jej rozpoczynamy od przekazania parametrów tablic, które chcemy podzielić (X
i y
). Atrybutem test_size
możemy przekazać proporcję pomiędzy podziałami. Dodatkowo, aby zapewnić powtarzalność podziału przy kolejnym uruchomieniu skryptu, warto przekazywać ziarno losowości, w atrybucie random_state
.
splits = model_selection.train_test_split(X, y, test_size=.333, random_state=0)
Podział zwraca nam krotkę zawierającą już docelowe podzbiory. Odłóżmy je do odpowiednich zmiennych i wyświetlmy na ekranie ich wielkości.
X_train, X_test, y_train, y_test = splits
print X_train.shape, X_test.shape, y_train.shape, y_test.shape
(100, 4) (50, 4) (100,) (50,)
Jak widać w parze X_train
, y_train
znalazły się 2/3, a w X_test
, y_test
— 1/3 wczytanego zbioru danych.
Walidacja krzyżowa k-fold
Podział prosty pozwala nam na co prawda na uzyskanie zbioru uczącego i testowego, ale nie możemy mieć przy nim pewności, że losowość nie dokonała się w nim w szczęśliwy dla klasyfikatora sposób, który wykaże jego wyższą jakość. Dla bezpieczeństwa i większej rzeczowości naszych badań musimy dokonać wielokrotnego podziału. Teoretycznie moglibyśmy wielokrotnie dokonać tego rodzaju podziału, aby zdobyć wiele par testowych i uczących, ale w takim podejściu istnieje duże prawdopodobieństwo występowania tych samych próbek w różnych zbiorach uczących. Metodą, która niweluje tego rodzaju problem jest k-fold cross-validation.
W podejściu krzyżowym dzielimy losowo zbiór danych na k
możliwie równych sobie podzbiorów. Uzyskujemy dzięki temu k
par, w których każdy z podzbiorów raz występuje jako zbiór uczący, a pozostała, połączona część zbioru jest wykorzystywana jako zbiór testowy.
Deklarujemy parametr
k
będący liczbą docelowych podziałów. Zwyczajowo stosuje sięk
równie 10 lub 30, w zależności od większości zbioru. Inicjalizujemy nim obiekt podziałucv
. Następnie w pętli iterujemy ten obiekt i wyświetlamy wielkość podzielonych zbiorów oraz zawartość zmiennejtrain
.
k = 10
cv = model_selection.StratifiedKFold(n_splits=k)
fold = 0
for train, test in cv.split(X_train, y_train):
print "Fold %i (%i w TS, %i w VS)" % (fold, len(train), len(test))
print train
fold += 1
Fold 0 (15 w TS, 135 w VS)
[ 0 1 2 ... 102 103 104]
Fold 1 (15 w TS, 135 w VS)
[ 5 6 7 ... 107 108 109]
Fold 2 (15 w TS, 135 w VS)
[ 10 11 12 ... 112 113 114]
Fold 3 (15 w TS, 135 w VS)
[ 15 16 17 ... 117 118 119]
Fold 4 (15 w TS, 135 w VS)
[ 20 21 22 ... 122 123 124]
Fold 5 (15 w TS, 135 w VS)
[ 25 26 27 ... 127 128 129]
Fold 6 (15 w TS, 135 w VS)
[ 30 31 32 ... 132 133 134]
Fold 7 (15 w TS, 135 w VS)
[ 35 36 37 ... 137 138 139]
Fold 8 (15 w TS, 135 w VS)
[ 40 41 42 ... 142 143 144]
Fold 9 (15 w TS, 135 w VS)
[ 45 46 47 ... 147 148 149]
Zauważ, że w zmiennych test
i train
nie zawierają się skompletowane podzbiory a jedynie indeksy wzorców, które powinny się w nich znaleźć.
Last updated