Wybór modelu i walidacja krzyżowa: właściwa droga

34

W CrossValidated znajduje się wiele wątków na temat wyboru modelu i weryfikacji krzyżowej. Tu jest kilka:

Jednak odpowiedzi na te wątki są dość ogólne i głównie podkreślają problemy ze szczególnym podejściem do weryfikacji krzyżowej i wyboru modelu.

Aby wszystko było jak najbardziej konkretne , powiedzmy na przykład, że pracujemy z maszyną SVM z jądrem RBF: K(x,x)=(γ|xx|)2 oraz że mam zestaw danych funkcjiXi etykiety, i że chcę

  1. Znajdź najlepsze możliwe wartości mojego modelu ( γ i C )
  2. Trenuj SVM z moim zestawem danych (do ostatecznego wdrożenia)
  3. Oszacuj błąd uogólnienia i niepewność (wariancję) wokół tego błędu

Aby to zrobić, osobiście przeszukałem siatkę, np. Wypróbowałem każdą możliwą kombinację C i γ . Dla uproszczenia możemy przyjąć następujące zakresy:

  • C{10,100,1000}
  • γ{0.1,0.2,0.5,1.0}

Mówiąc dokładniej, korzystając z mojego pełnego zestawu danych, wykonuję następujące czynności:

  1. Dla każdej pary ( , γ ) wykonuję powtarzane iteracje (np. 100 losowych powtórzeń) K- krotnej walidacji krzyżowej (np. K = 10 ) w moim zbiorze danych, tj. Trenuję moją SVM na fałdach K - 1 i oceniam błąd na lewej zakładce, iterując wszystkie fałdy K. Ogólnie zbieram 100 x 10 = 1000 błędów testowych.CγKK=10K1K
  2. Dla każdej takiej ( , γ ) pary, to obliczyć średnią i wariancję 1000-tych testowych Błędy jj, M , Ď M .CγμM,σM

Teraz chcę wybrać najlepszy model (najlepsze parametry jądra), którego użyłbym do wyszkolenia mojej ostatecznej SVM na pełnym zbiorze danych. Rozumiem, że wybór modelu o najniższej średniej błędu i wariancji i σ M byłby właściwym wyborem, a μ M tego modelu to σ M, to moje najlepsze oszacowania błędu i wariancji błędu uogólnienia modelu podczas treningu z pełny zestaw danych.μMσMμMσM

ALE po przeczytaniu odpowiedzi w powyższych wątkach mam wrażenie, że ta metoda wyboru najlepszego SVM do wdrożenia i / lub oszacowania jego błędu (wydajności uogólnienia) jest wadliwa i istnieją lepsze sposoby wyboru najlepszy SVM i zgłaszanie jego błędu. Jeśli tak, jakie one są? Proszę o konkretną odpowiedź.

Trzymając się tego problemu, jak konkretnie mogę wybrać najlepszy model i właściwie oszacować jego błąd generalizacji ?

Amelio Vazquez-Reina
źródło
Aby wszystko było jak najbardziej konkretne, powiedz nam: Ile statystycznie niezależnych przypadków masz w zbiorze danych? Jaką funkcję docelową oceniasz pod kątem optymalizacji / Jakiego rodzaju błędu używasz? Czy faktycznie obserwujesz spójne zachowanie wybranej miary błędu na siatce parametrów? Jeśli mówisz o klasyfikacji, a miara błędu na to pozwala: w jaki sposób iterowane wyniki krzyżowej weryfikacji porównują się z oczekiwaną (ale nie można zmierzyć) wariancją ze względu na skończoną wielkość próby?
cbeleites wspiera Monikę
Artykuł, który może Cię zainteresować: optimprediction.com/files/pdf/V2A5.pdf
user31256
2
+1 za bardzo jasne i szczegółowe pytanie, a także bardzo trafne pytanie do całej społeczności zajmującej się analizą danych.
NickBraunagel

Odpowiedzi:

20

Mój artykuł w JMLR zajmuje się dokładnie tym pytaniem i pokazuje, dlaczego procedura zaproponowana w tym pytaniu (lub co najmniej jednym bardzo podobnym) skutkuje optymistycznie stronniczymi szacunkami wydajności:

Gavin C. Cawley, Nicola LC Talbot, „O nadmiernym dopasowaniu w wyborze modelu i późniejszym odchyleniu w selekcji w ocenie wydajności”, Journal of Machine Learning Research, 11 (lipiec): 2079-2107, 2010. ( www )

Kluczową rzeczą do zapamiętania jest to, że walidacja krzyżowa jest techniką szacowania wydajności uogólnienia dla metody generowania modelu, a nie samego modelu. Jeśli więc wybór parametrów jądra jest częścią procesu generowania modelu, musisz również zweryfikować krzyżowo proces wyboru modelu, w przeciwnym razie skończysz z optymistycznie tendencyjnym oszacowaniem wydajności (tak jak stanie się z proponowaną przez ciebie procedurą).

Załóżmy, że masz funkcję fit_model, która pobiera zestaw danych składający się z atrybutów X i pożądanych odpowiedzi Y, i który zwraca dopasowany model dla tego zestawu danych, w tym strojenie hiperparametrów (w tym przypadku parametry jądra i regularyzacji). To dostrajanie hiper-parametrów można wykonać na wiele sposobów, na przykład minimalizując błąd weryfikacji krzyżowej w stosunku do X i T.

Krok 1 - Dopasuj model do wszystkich dostępnych danych, używając funkcji fit_model. To daje model, którego będziesz używać podczas pracy.

Krok 2 - Ocena wydajności. Wykonaj wielokrotną weryfikację krzyżową przy użyciu wszystkich dostępnych danych. W każdym folderze dane są dzielone na zestaw szkoleniowy i zestaw testowy. Dopasuj model za pomocą zestawu treningowego (zapisz wartości hiperparametrów dla dopasowanego modelu) i oceń wydajność zestawu testowego. Użyj średniej dla wszystkich zestawów testowych jako oszacowania wydajności (i być może przyjrzyj się także rozkładowi wartości).

Krok 3 - Zmienność ustawień hiperparametrów - wykonaj analizę wartości hiperparametrów zebranych w kroku 3. Należy jednak zauważyć, że w hiperparametrach nie ma nic specjalnego, są to tylko parametry modelu, które zostały oszacowane (pośrednio ) z danych. Są one traktowane raczej jako hiperparametry niż parametry dla wygody obliczeniowej / matematycznej, ale nie musi tak być.

The problem with using cross-validation here is that the training and test data are not independent samples (as they share data) which means that the estimate of the variance of the performance estimate and of the hyper-parameters is likely to be biased (i.e. smaller than it would be for genuinely independent samples of data in each fold). Rather than repeated cross-validation, I would probably use bootstrapping instead and bag the resulting models if this was computationally feasible.

The key point is that to get an unbiased performance estimate, whatever procedure you use to generate the final model (fit_model) must be repeated in its entirety independently in each fold of the cross-validation procedure.

Dikran Marsupial
źródło
This is a great answer. When you say rather than repeated cross-validation you would go for bootstrapping - What is exactly the difference? Both involve multiple repetitions of dividing the data into train and test and then training in train and evaluating in test, don't they?
Josh
4
Bootstrapping (sampling with replacement) seems a more natural way of performing a large number of re-samplings, as it is more randomised than repeated cross-validation. For bootstrapping the use of bagged enembles is a nice feature, with the out-of-bag error as a performance estimate. There isn't a huge amount to choose between the two.
Dikran Marsupial
Thanks @Dikran - This made me wonder, assuming that one uses e.g. bootstrapping, how would you choose a good model considering the mean and variance across repetitions? (i.e. what model selection protocol would you follow?). This question poses exactly this question. Getting your input on that thread would be extremely valuable!
Josh
@DikranMarsupial Could you post code (e.g., Python or R) for your steps 1-3? I find it a lot easier to understand such procedures when seeing concrete code.
tobip
1
Key message: "The key point is that to get an unbiased performance estimate, whatever procedure you use to generate the final model (fit_model) must be repeated in its entirety independently in each fold of the cross-validation procedure." This exact message is also conveyed in The Elements of Statistical Learning (see section 7.10.2): web.stanford.edu/~hastie/Papers/ESLII.pdf
NickBraunagel
0

Using a SVM with fixed hyperparameters (γ and C) is a machine learning algorithm.

A procedure that optimizes these hyperparameters and trains a SVM with these is also just a machine learning algorithm. Instead of only optimizing the internal parameters of the SVM (the support vectors) it also optimizes the hyperparameters.

Now you have two problems [that can be solved independently]:

Read Cross-validation misuse (reporting performance for the best hyperparameter value) to make sure that you don't mix them up.


A specific (probably not optimal) solution to the concrete problem of your question:

k = 5
loss_CV = zeros(k)
for i in 1:k 
    Xi_train, Xi_test = folds(X,k)[i]
    loss = zeros((3,3))
    for lambda in {0.1,0.2,0.5,1.0}
        for C in {10,100,1000}
            for j in 1:k
                Xj_train, Xj_test = folds(Xi_train,k)[j]
                model = SVM(Xj_train,lambda, C)
                loss[lambda,C] += test_error(model,Xj_test)
    lambda, C = argmax(loss)
    model = SVM(Xi_train,lambda, C)
    loss_CV += test_error(model,Xi_test)

loss = zeros((3,3))
for lambda in {0.1,0.2,0.5,1.0}
    for C in {10,100,1000}
        for j in 1:k
            Xj_train, Xj_test = folds(Xi_train,k)[j]
            model = SVM(Xj_train,lambda, C)
            loss[lambda,C] += test_error(model,Xj_test)
lambda, C = argmax(loss)
model = SVM(Xi_train,lambda, C)

Here, model would be your "best model" and loss_CV a "proper estimate of its generalization error" (although biased upward, but you cannot have the cake and eat it too).

jan-glx
źródło