Dokładność maszyny zwiększającej gradient zmniejsza się wraz ze wzrostem liczby iteracji

15

Eksperymentuję z algorytmem maszyny do zwiększania gradientu za pośrednictwem caretpakietu w R.

Korzystając z małego zestawu danych o przyjęciach na studia, uruchomiłem następujący kod:

library(caret)

### Load admissions dataset. ###
mydata <- read.csv("http://www.ats.ucla.edu/stat/data/binary.csv")

### Create yes/no levels for admission. ### 
mydata$admit_factor[mydata$admit==0] <- "no"
mydata$admit_factor[mydata$admit==1] <- "yes"             

### Gradient boosting machine algorithm. ###
set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(5000,1000000,5000), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

i zdziwiłem się, że dokładność krzyżowej walidacji modelu spadła, a nie wzrosła wraz ze wzrostem liczby iteracji przypominających, osiągając minimalną dokładność około .59 przy ~ 450 000 iteracji.

wprowadź opis zdjęcia tutaj

Czy nieprawidłowo zaimplementowałem algorytm GBM?

EDYCJA: Zgodnie z sugestią Underminera, ponownie uruchomiłem powyższy caretkod, ale skupiłem się na uruchomieniu od 100 do 5000 iteracji zwiększających:

set.seed(123)
fitControl <- trainControl(method = 'cv', number = 5, summaryFunction=defaultSummary)
grid <- expand.grid(n.trees = seq(100,5000,100), interaction.depth = 2, shrinkage = .001, n.minobsinnode = 20)
fit.gbm <- train(as.factor(admit_factor) ~ . - admit, data=mydata, method = 'gbm', trControl=fitControl, tuneGrid=grid, metric='Accuracy')
plot(fit.gbm)

Wynikowy wykres pokazuje, że dokładność faktycznie osiąga wartość szczytową przy prawie 0,705 przy ~ 1800 iteracjach:

wprowadź opis zdjęcia tutaj

Co ciekawe, dokładność nie osiągnęła plateau przy ~ .70, ale spadła po 5000 iteracji.

RobertF
źródło

Odpowiedzi:

14

Zasadniczo błąd zwiększania może wzrosnąć wraz z liczbą iteracji, szczególnie gdy dane są zaszumione (np. Przypadki błędnie oznaczone). To może być twój problem, ale nie byłbym w stanie powiedzieć, nie wiedząc więcej o twoich danych

Zasadniczo, zwiększenie może „skoncentrować się” na prawidłowym przewidywaniu przypadków, które zawierają dezinformację, a proces pogarsza średnią wydajność w innych przypadkach, które są bardziej istotne.

Ten link ( wzmocnienie i hałas ) pokazuje lepszy opis problemu niż mogę podać.

Ten dokument ( Losowy hałas klasyfikacyjny ) autorstwa Long and Servedio zawiera więcej szczegółów technicznych problemu.

Underminer
źródło
16

To, co pokazałeś, to klasyczny przykład nadmiernego dopasowania. Niewielki wzrost błędu wynika z gorszej wydajności części sprawdzania poprawności zestawu danych poddanych walidacji krzyżowej. Więcej iteracji powinno prawie zawsze poprawić błąd w zestawie szkoleniowym, ale odwrotnie jest w przypadku zestawu sprawdzania poprawności / testu.

Ryan Zotti
źródło
Więc nadprzyrodzenie zwiększające gradient na podstawie # iteracji zwiększających? Ciekawy. Myślałem, że dokładność spadłaby zamiast tego po osiągnięciu optymalnej liczby iteracji.
RobertF
4
To jest poprawne. Przy zwiększaniu gradientu każde kolejne drzewo jest budowane z resztek poprzednich drzew, więc GBM będzie nadal próbował wyciąć pozostały błąd w zestawie danych treningowych, nawet kosztem możliwości uogólnienia do zestawów walidacyjnych / testowych. Dlatego przeprowadzasz walidację krzyżową - ponieważ algorytm dopasowywania natywnie nie wie, kiedy przestać
Ryan Zotti
1
Gradient Boosting jest inspirowany AdaBoost. AdaBoost bardzo rzadko się przepasuje, a kiedy to robi, jest tylko nieznacznie i po wielu, wielu iteracjach. Myślę, że wyjaśnienie @Underminer jest bardziej reprezentatywne dla tego, co się dzieje niż ten komentarz, szczególnie biorąc pod uwagę brak odniesień w tym komentarzu.
Ricardo Cruz,
2
@RicardoCruz Myślę, że to interesujące, że rzadko widziałeś overfit zwiększający gradient. Przez około cztery lata, kiedy go używałem, widziałem coś przeciwnego - zbyt wiele drzew prowadzi do nadmiernego dopasowania. Kiedyś musiałem udowodnić coś podobnego do kolegi i byłem w stanie zredukować błąd na zestawie treningowym do prawie zera, ale błąd walidacji wzrósł znacznie bardziej niż w przypadku niedopasowanego GBM. Nadal uważam, że zwiększanie gradientu to świetny algorytm. Zazwyczaj jest to pierwszy algorytm, którego używam - musisz tylko uważać na zbyt wiele drzew, które można śledzić za pomocą krzyżowej weryfikacji
Ryan Zotti
2
@RyanZotti I wtedy poprawione. Przeczytałem kilka artykułów na temat AdaBoost od Schapire i in., Ponieważ podoba mi się jego piękna mocna podstawa teoretyczna. Autorzy twierdzą, że doładowanie jest podatne na nadmierne dopasowanie, ale jest niezwykle trudne. Nie mam dużego doświadczenia w korzystaniu z niego i nie mają solidnych teoretycznych podstaw do argumentowania tego, i oczywiście autorzy będący autorami, są naturalnie gorliwi w swoim wynalazku, więc jeśli masz doświadczenie przeciwne , Poprawiono mnie.
Ricardo Cruz,
4

Kody do odtworzenia podobnego wyniku bez wyszukiwania siatki,

mod = gbm(admit ~ .,
      data = mydata[,-5],
      n.trees=100000,
      shrinkage=0.001,
      interaction.depth=2,
      n.minobsinnode=10,
      cv.folds=5,
      verbose=TRUE,
      n.cores=2)

best.iter <- gbm.perf(mod, method="OOB", plot.it=TRUE, oobag.curve=TRUE, overlay=TRUE)
print(best.iter)
[1] 1487
pred = as.integer(predict(mod, newdata=mydata[,-5], n.trees=best.iter) > 0)
y = mydata[,1]
sum(pred == y)/length(y)
[1] 0.7225
horaceT
źródło
3

Pakiet gbm ma funkcję do oszacowania optymalnej liczby iteracji (= liczba drzew lub liczba funkcji bazowych),

gbm.perf(mod, method="OOB", plot.it=TRUE, oobag=TRUE, overlay=TRUE)

Nie potrzebujesz do tego pociągu Careta.

horaceT
źródło
Nie wiem, czy to rozwiązuje problem, który mam - wydaje się, że optymalna liczba iteracji wynosi 5000 w moim przypadku, gdzie dokładność jest najwyższa, bliska 0,70 (pierwszy punkt danych na moim wykresie). Ale to wydaje się złe. Więcej iteracji powinno prowadzić do większej dokładności, a nie niższej, prawda?
RobertF
1
@RobertF Po pierwsze, myślę, że nie musisz zmieniać przyznania się w czynnik. Działa równie dobrze: mod = gbm (przyznać ~., Dane = moje dane [, - 5], n. Drzewa = 100000, skurcz = 0,001, interakcja. Głębokość = 2, n. Minobsinnode = 10, cv.folds = 5 , verbose = TRUE, n.cores = 2). Możesz zobaczyć, gdzie gbm wybiera optymalną iterację: best.iter <- gbm.perf (mod, method = "OOB", plot.it = PRAWDA, oobag.curve = PRAWDA, nakładka = PRAWDA). To znaczy, gdy zmiana dewiacji staje się ujemna (patrz wykres z tego wygenerowany).
horaceT
1
@RobertF Jeszcze jedna rzecz. Określając n.trees = (milion) w wywołaniu gbm, uruchomiłbyś wszystkie liczby iteracji od 1 do 1 000 000. Nie musisz więc robić tego za siebie.
horaceT
1
@RobertF Więcej działań następczych. Właśnie uruchomiłem 100 tys. Drzew / iteracji. Dokładność, jaką uzyskałem, wybierając najlepszą iterację z gbm.perf, to 0,7225, co jest bardzo zbliżone do twojego z pełną siatką iteracji.
horaceT