Die Maschinengenauigkeit zur Steigerung des Gradienten nimmt mit zunehmender Anzahl von Iterationen ab

15

Ich experimentiere mit dem Algorithmus der Gradientenverstärkungsmaschine über das caretPaket in R.

Unter Verwendung eines kleinen Datensatzes für Hochschulzulassungen habe ich den folgenden Code ausgeführt:

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)

und stellte zu meiner Überraschung fest, dass die Kreuzvalidierungsgenauigkeit des Modells eher abnahm als zunahm, als die Anzahl der verstärkenden Iterationen zunahm und eine Mindestgenauigkeit von etwa 0,69 bei ~ 450.000 Iterationen erreichte.

Bildbeschreibung hier eingeben

Habe ich den GBM-Algorithmus falsch implementiert?

BEARBEITEN: Nach dem Vorschlag von Underminer habe ich den obigen caretCode erneut ausgeführt, mich jedoch darauf konzentriert, 100 bis 5.000 Boosting-Iterationen auszuführen:

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)

Das resultierende Diagramm zeigt, dass die Genauigkeit bei ~ 1.800 Iterationen bei fast 0,705 tatsächlich einen Spitzenwert aufweist:

Bildbeschreibung hier eingeben

Was merkwürdig ist, ist, dass die Genauigkeit nicht bei ~ 0,70 lag, sondern nach 5.000 Iterationen abnahm.

RobertF
quelle

Antworten:

14

Im Allgemeinen kann der Boosting-Fehler mit der Anzahl der Iterationen zunehmen, insbesondere wenn die Daten verrauscht sind (z. B. in Fällen mit falscher Bezeichnung). Dies könnte Ihr Problem sein, aber ich würde es nicht sagen können, ohne mehr über Ihre Daten zu wissen

Grundsätzlich kann sich Boosting auf die korrekte Vorhersage von Fällen konzentrieren, die Fehlinformationen enthalten, und dabei die durchschnittliche Leistung in anderen Fällen verschlechtern, die substanzieller sind.

Dieser Link ( Boosting and Noise ) beschreibt das Problem besser als ich es beschreiben kann.

Dieses Dokument ( Random Classification Noise ) von Long and Servedio enthält weitere technische Details zu diesem Problem.

Underminer
quelle
16

Was Sie angezeigt haben, ist ein klassisches Beispiel für eine Überanpassung. Der kleine Anstieg des Fehlers ist auf eine schlechtere Leistung im Validierungsteil Ihres kreuzvalidierten Datensatzes zurückzuführen. Weitere Iterationen sollten fast immer den Fehler im Trainingssatz verbessern, aber das Gegenteil gilt für den Validierungs- / Testsatz.

Ryan Zotti
quelle
Steigungsverstärkende Overfits basierend auf der Anzahl der verstärkenden Iterationen? Interessant. Ich dachte, die Genauigkeit hätte stattdessen nach dem Erreichen der optimalen Anzahl von Iterationen ein Plateau erreicht.
RobertF
4
Das ist richtig. Bei der Gradientenverstärkung wird jeder nachfolgende Baum aus den Residuen der vorherigen Bäume aufgebaut, sodass der GBM weiterhin versucht, den verbleibenden Fehler im Trainingsdatensatz zu beseitigen, selbst wenn die Verallgemeinerung auf Validierungs- / Testsätze nicht möglich ist. Aus diesem Grund führen Sie eine Kreuzvalidierung durch, da der Anpassungsalgorithmus ursprünglich nicht weiß, wann er zu stoppen ist
Ryan Zotti,
1
Gradient Boosting ist von AdaBoost inspiriert. AdaBoost passt sehr selten über und wenn, dann nur geringfügig und nach vielen, vielen Iterationen. Ich denke, dass die Erklärung von @Underminer eher repräsentativ für das ist, was gerade passiert, als dieser Kommentar, insbesondere wenn man bedenkt, dass in diesem Kommentar keine Verweise enthalten sind.
Ricardo Cruz
2
@RicardoCruz Ich finde es interessant, dass Sie selten einen Gradienten gesehen haben, der die Überanpassung verstärkt. In den vier oder mehr Jahren, in denen ich es benutzt habe, habe ich das Gegenteil gesehen - zu viele Bäume führen zu Überanpassung. Ich musste einmal etwas Ähnliches wie ein Kollege nachweisen und konnte den Fehler im Trainingssatz auf nahezu Null reduzieren, aber der Validierungsfehler stieg deutlich mehr als der des nicht überanpassungsfähigen GBM. Ich denke immer noch, dass Gradientenverstärkung ein großartiger Algorithmus ist. Es ist normalerweise der erste Algorithmus, den ich verwende - man muss nur auf zu viele Bäume achten, die man durch Kreuzvalidierung verfolgen kann
Ryan Zotti
2
@ RyanZotti Ich stehe dann korrigiert. Ich habe eine Reihe von Artikeln über AdaBoost von Schapire et al. Gelesen, weil mir die schöne starke theoretische Grundlage gefällt. Die Autoren argumentieren, dass Boosten zu Überanpassung neigt, aber äußerst schwierig ist. Ich habe nicht viel Erfahrung damit, und sie haben keine solide theoretische Grundlage, um dies zu argumentieren, und natürlich sind Autoren, die Autoren sind, von Natur aus eifrig mit ihrer Erfindung, wenn Sie also Erfahrung mit dem Gegenteil haben , Ich stehe korrigiert.
Ricardo Cruz
4

Codes zur Wiedergabe eines ähnlichen Ergebnisses ohne Rastersuche,

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
quelle
3

Das gbm-Paket hat eine Funktion zum Schätzen der optimalen Anzahl von Iterationen (= Anzahl von Bäumen oder Anzahl von Basisfunktionen).

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

Dafür brauchen Sie keinen Caret-Zug.

HoraceT
quelle
Ich weiß nicht, ob das Problem dadurch behoben wird. In meinem Fall, in dem die Genauigkeit am höchsten ist und nahe bei 0,70 liegt (dem ersten Datenpunkt in meinem Diagramm), scheint die optimale Anzahl von Iterationen 5.000 zu betragen. Das scheint aber falsch. Mehr Iterationen sollten zu einer höheren Genauigkeit führen, nicht zu einer niedrigeren, oder?
RobertF
1
@RobertF Erstens, ich denke, du musst dich nicht in einen Faktor verwandeln. Es funktioniert genauso gut: mod = gbm (zugeben ~., Data = mydata [, - 5], n.trees = 100000, shrinkage = 0.001, interaction.depth = 2, n.minobsinnode = 10, cv.folds = 5 , verbose = TRUE, n.cores = 2). Sie können sehen, wo gbm den optimalen Iter wählt: best.iter <- gbm.perf (mod, method = "OOB", plot.it = TRUE, oobag.curve = TRUE, overlay = TRUE). Das heißt, wenn die Änderung der Abweichung negativ wird (siehe den daraus generierten Plot).
HoraceT
1
@RobertF Noch eine Sache. Durch Angabe von n.trees = (eine Million) im gbm-Aufruf hätten Sie alle Iterationszahlen von 1 bis 1.000.000 ausgeführt. Sie brauchen also kein Caret, um das für Sie zu tun.
HoraceT
1
@ RobertF Weitere Follow-up. Ich habe gerade 100.000 Bäume / Iterationen ausgeführt. Die Genauigkeit, die ich bei der Auswahl der besten Iteration mit gbm.perf erhalten habe, beträgt 0,7225, was ziemlich nahe an Ihrer liegt, wenn ich ein vollständiges Raster von Iterationen durchführe.
HoraceT