ML Atlas

04 · Ocena · 4 min czytania · Interaktywne · aktualizacja

Na czym polega walidacja krzyżowa (cross-validation) i po co się ją stosuje?

W skrócie

Walidacja krzyżowa dzieli dane na k części i każdą z nich po kolei traktuje jako zbiór walidacyjny. Daje stabilniejszą ocenę modelu niż jeden podział.

Co to jest

Walidacja krzyżowa (cross-validation, CV) to metoda szacowania, jak dobrze model będzie działał na nowych danych, w której dane dzieli się na k równych części (foldów), a następnie k razy trenuje model na k − 1 częściach i ocenia na pozostałej. Końcowy wynik to średnia z k ocen, a ich rozrzut mówi, jak bardzo wynik zależy od podziału.

Intuicja: pojedynczy podział na trening i walidację to jak ocena ucznia na podstawie jednej kartkówki — może trafić na łatwe albo trudne pytania. Walidacja krzyżowa to pięć kartkówek z różnych działów: każdy przykład raz trafia do „egzaminu”, a średnia jest znacznie mniej przypadkowa.

Najczęściej używa się k = 5 lub k = 10. Przypadek skrajny, k równe liczbie przykładów, to walidacja leave-one-out.

Mechanizm — dlaczego tak działa

Wynik na pojedynczym zbiorze walidacyjnym ma dwa źródła niepewności: losowość tego, które przykłady trafiły do walidacji, i to, że walidacja jest mała. Walidacja krzyżowa atakuje oba problemy naraz. Każdy przykład zostaje użyty do oceny dokładnie raz, więc ocena opiera się na wszystkich n przykładach, a nie na 20% z nich. Uśrednienie k wyników zmniejsza wpływ szczęśliwego lub pechowego podziału.

Jest też koszt i subtelność. Każdy z k modeli trenuje się na (k − 1)/k danych, czyli na nieco mniejszym zbiorze niż model końcowy. Dlatego CV ma lekkie obciążenie pesymistyczne — model trenowany na wszystkich danych będzie zwykle trochę lepszy. Im większe k, tym mniejsze to obciążenie, ale tym większy koszt obliczeń i tym bardziej podobne do siebie są zbiory treningowe, co może zwiększać wariancję oszacowania. Wartości 5–10 to empiryczny kompromis opisany m.in. przez Kohaviego.

Ważne zastrzeżenie: odchylenie standardowe wyników z k foldów nie jest poprawnym błędem standardowym średniej. Foldy dzielą większość danych treningowych, więc ich wyniki są skorelowane, a prosty wzór s/√k zaniża niepewność. Traktuj rozrzut foldów jako orientacyjny sygnał stabilności, nie jako przedział ufności.

Walidacja krzyżowa zakłada, że przykłady są wymienne — że każdy podział jest tak samo „uczciwy”. Gdy dane mają strukturę (kolejność w czasie, grupy pacjentów, posortowane klasy), zwykłe losowe foldy dają zawyżone lub zaniżone wyniki i trzeba użyć odpowiedniego wariantu. Wreszcie: jeśli na podstawie CV wybieramy najlepszy model spośród wielu, wynik zwycięzcy jest znowu optymistyczny — uczciwą ocenę daje wtedy zagnieżdżona walidacja krzyżowa albo osobny test.

Na przykładzie

Na zbiorze Wine (178 win, 3 odmiany) porównałem dwie procedury oceny tego samego drzewa decyzyjnego (DecisionTreeClassifier(random_state=0)). Najpierw 100 pojedynczych podziałów 80/20 z różnymi random_state od 0 do 99: trafność testowa wahała się od 75% do 100%, średnio 90,9%, z odchyleniem standardowym 4,8 punktu. Zależnie od losowania ten sam model można by więc opisać jako „przeciętny” albo „bezbłędny”.

Następnie 100 powtórzeń 5-krotnej warstwowej walidacji krzyżowej (StratifiedKFold(5, shuffle=True) z różnymi ziarnami): średnie z pięciu foldów wahały się już tylko od 86,5% do 94,4%, z odchyleniem 1,6 punktu — trzy razy mniej. Średnia oszacowania pozostała ta sama (około 90,9%), zniknęła tylko większość przypadkowości. Dla jednego przebiegu z random_state=0 wyniki foldów to 91,7%, 83,3%, 97,2%, 97,1% i 94,3% (średnio 92,7%) — widać, jak bardzo różnią się same foldy.

Ta ilustracja działa w przeglądarce z włączonym JavaScriptem: walidacja krzyżowa kNN na winach ułożonych w pliku klasami: bez tasowania 3 foldy dają średnio 23%, bo całe klasy wypadają z treningu, a po potasowaniu ta sama metoda ma 96%.

Dane: Wine (wina z Piemontu)

W praktyce

  • Najprostsze wywołanie: cross_val_score(model, X, y, cv=5); dla klasyfikacji scikit-learn domyślnie użyje StratifiedKFold.
  • cross_validate(..., scoring=['accuracy', 'f1_macro'], return_train_score=True) zwraca kilka metryk naraz i wynik treningowy do diagnozy przeuczenia.
  • Zawsze przekazuj cały Pipeline (skalowanie, imputacja, model), nie wstępnie przetworzone X — inaczej statystyki z foldów walidacyjnych przeciekną do treningu.
  • Gdy dane mogą być posortowane, ustaw shuffle=True i random_state; dla grup użyj GroupKFold, dla szeregów czasowych TimeSeriesSplit.
  • Przy bardzo małych danych rozważ RepeatedStratifiedKFold, by uśrednić także losowość podziału na foldy.
  • Typowy błąd: wybór cech na całych danych, a dopiero potem CV — wynik bywa zawyżony o dziesiątki punktów.

Najczęstsze pytania

Jakie k wybrać?
Domyślnie 5 albo 10. Przy dużych zbiorach wystarczy 3–5, bo każdy fold i tak jest duży, a koszt trenowania rośnie liniowo z k. Przy bardzo małych zbiorach lepsza jest powtarzana 5- lub 10-krotna CV niż leave-one-out, które bywa niestabilne.
Który z k modeli wybrać na końcu?
Żaden. Walidacja krzyżowa ocenia procedurę uczenia, a nie konkretny egzemplarz modelu. Po wyborze ustawień trenuje się jeden model na wszystkich dostępnych danych treningowych.
Czy walidacja krzyżowa zastępuje zbiór testowy?
Do szacowania jakości jednego, z góry ustalonego modelu — tak. Gdy używasz CV do strojenia lub wyboru spośród wielu modeli, wynik najlepszego jest optymistyczny i potrzebny jest osobny test albo zagnieżdżona CV.

Źródła

  • James G., Witten D., Hastie T., Tibshirani R. „An Introduction to Statistical Learning”, 2nd ed., Springer 2021, rozdz. 5.1 (Cross-Validation).
  • Hastie T., Tibshirani R., Friedman J. „The Elements of Statistical Learning”, 2nd ed., Springer 2009, rozdz. 7.10 (Cross-Validation).
  • Stone M. (1974). Cross-Validatory Choice and Assessment of Statistical Predictions. Journal of the Royal Statistical Society, Series B, 36(2).
  • Kohavi R. (1995). A Study of Cross-Validation and Bootstrap for Accuracy Estimation and Model Selection. Proceedings of IJCAI 1995.
  • Dokumentacja scikit-learn: Cross-validation: evaluating estimator performance — https://scikit-learn.org/stable/modules/cross_validation.html

Zobacz też