R: Was sehe ich in partiellen Abhängigkeitsdiagrammen von gbm und RandomForest?

14

Eigentlich dachte ich, ich hätte verstanden, was man mit partieller Abhängigkeit darstellen kann, aber unter Verwendung eines sehr einfachen hypothetischen Beispiels wurde ich ziemlich verwirrt. Im folgenden Codeabschnitt generiere ich drei unabhängige Variablen ( a , b , c ) und eine abhängige Variable ( y ), wobei c eine enge lineare Beziehung zu y aufweist , während a und b nicht mit y korrelieren . Ich mache eine Regressionsanalyse mit einem verstärkten Regressionsbaum unter Verwendung des R-Pakets gbm:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")
par(mfrow = c(2,2))
plot(gbm.gaus, i.var = 1)
plot(gbm.gaus, i.var = 2)
plot(gbm.gaus, i.var = 3)

Es überrascht nicht, dass für die Variablen a und b die partiellen Abhängigkeitsdiagramme horizontale Linien um den Mittelwert von a ergeben . Was mich rätselt, ist die Handlung für Variable c . Ich erhalte horizontale Linien für die Bereiche c <40 und c > 60 und die y-Achse ist auf Werte nahe dem Mittelwert von y beschränkt . Da a und b in keinerlei Beziehung zu y stehen (und daher die variable Bedeutung im Modell 0 ist), habe ich erwartet, dass cwürde für einen sehr eingeschränkten Bereich seiner Werte eine teilweise Abhängigkeit entlang seines gesamten Bereichs anstelle dieser Sigmoidform zeigen. Ich habe versucht, Informationen in Friedman (2001) "Greedy Function Approximation: eine Gradienten-Boosting-Maschine" und in Hastie et al. (2011) "Elemente des statistischen Lernens", aber meine mathematischen Fähigkeiten sind zu gering, um alle darin enthaltenen Gleichungen und Formeln zu verstehen. Also meine Frage: Was bestimmt die Form des partiellen Abhängigkeitsdiagramms für Variable c ? (Erklären Sie dies bitte in Worten, die für einen Nicht-Mathematiker verständlich sind!)

HINZUGEFÜGT am 17. April 2014:

Während ich auf eine Antwort wartete, verwendete ich dieselben Beispieldaten für eine Analyse mit R-package randomForest. Die partiellen Abhängigkeitsdiagramme von randomForest ähneln viel eher dem, was ich von den gbm - Diagrammen erwartet habe: Die partielle Abhängigkeit der erklärenden Variablen a und b variiert zufällig und stark um 50, während die erklärende Variable c eine partielle Abhängigkeit über ihren gesamten Bereich (und über fast den gesamten Bereich) aufweist gesamter Bereich von y ). Was könnten die Gründe für diese unterschiedlichen Formen der partiellen Abhängigkeitsdiagramme in gbmund sein randomForest?

Teilpläne von gbm und randomForest

Hier der geänderte Code, der die Diagramme vergleicht:

a <- runif(100, 1, 100)
b <- runif(100, 1, 100)
c <- 1:100 + rnorm(100, mean = 0, sd = 5)
y <- 1:100 + rnorm(100, mean = 0, sd = 5)
par(mfrow = c(2,2))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")

library(gbm)
gbm.gaus <- gbm(y ~ a + b + c, data = Data, distribution = "gaussian")

library(randomForest)
rf.model <- randomForest(y ~ a + b + c, data = Data)

x11(height = 8, width = 5)
par(mfrow = c(3,2))
par(oma = c(1,1,4,1))
plot(gbm.gaus, i.var = 1)
partialPlot(rf.model, Data[,2:4], x.var = "a")
plot(gbm.gaus, i.var = 2)
partialPlot(rf.model, Data[,2:4], x.var = "b")
plot(gbm.gaus, i.var = 3)
partialPlot(rf.model, Data[,2:4], x.var = "c")
title(main = "Boosted regression tree", outer = TRUE, adj = 0.15)
title(main = "Random forest", outer = TRUE, adj = 0.85)
user7417
quelle
1
Möglicherweise möchten Sie die Hyperparameter auf Knopfdruck optimieren. Ich bin nicht sicher, wie viele Bäume standardmäßig in gbm sind, aber es könnte so klein sein, dass es keine Zeit hat, eine gesunde Krümmung zu erlernen.
Shea Parkes
@Shea Parkes - Du hast recht. Die defaukt Anzahl der Bäume beträgt 100, was nicht ausreichte, um ein gutes Modell zu generieren. Mit 2000 Bäumen sind die Teilabhängigkeitsdiagramme von gbm und Zufallswald nahezu identisch.
User7417

Antworten:

7

Ich habe einige Zeit damit verbracht, meinen eigenen "Partial.function-Plotter" zu schreiben, bevor mir klar wurde, dass er bereits in der R randomForest-Bibliothek enthalten ist.

[BEARBEITEN ... aber dann habe ich ein Jahr damit verbracht, das CRAN-Paket forestFloor zu erstellen , das meiner Meinung nach erheblich besser ist als klassische Teilabhängigkeitsdiagramme ]

Teilfunktionsdiagramme eignen sich hervorragend in Fällen, in denen dieses Simulationsbeispiel, das Sie hier zeigen, die erklärende Variable nicht mit anderen Variablen interagiert. Wenn jede erklärende Variable durch eine unbekannte Funktion additiv zum Ziel-Y beiträgt, ist diese Methode großartig, um diese geschätzte versteckte Funktion zu zeigen. Ich sehe oft eine solche Abflachung an den Grenzen von Teilfunktionen.

Einige Gründe: randomForsest hat ein Argument namens 'node = 5', was bedeutet, dass kein Baum eine Gruppe von 5 oder weniger Mitgliedern unterteilt. Daher kann jeder Baum nicht genauer unterscheiden. Die Bagging / Bootstrapping-Ebene von ensemple glättet durch Abstimmung die vielen Schrittfunktionen der einzelnen Bäume - allerdings nur in der Mitte des Datenbereichs. In der Nähe der Grenzen des für Daten repräsentierten Raums fällt die "Amplitude" der Teilfunktion. Wenn Sie die Knotengröße auf 3 setzen und / oder im Vergleich zu Rauschen mehr Beobachtungen erhalten, kann dies den Randabflachungseffekt verringern. Somit sind die Vorhersagen nicht absolut genau, sondern nur linear mit dem Ziel korreliert. Sie können die Werte a und b als Beispiele für ein extrem niedriges Signal-Rausch-Verhältnis sehen. und deshalb sind diese Teilfunktionen sehr flach. Es ist eine nette Funktion von Random Forest, dass Sie bereits aus dem Bereich der Vorhersagen des Trainingssatzes erraten können, wie gut das Modell funktioniert. OOB.predictions ist auch großartig ..

Die Verflachung von Teilflächen in Regionen ohne Daten ist sinnvoll: Da zufällige Gesamtstrukturen und WARENKORB datengetriebene Modelle sind, gefällt mir persönlich das Konzept, dass diese Modelle nicht extrapoliert werden. Somit ist die Vorhersage von c = 500 oder c = 1100 genau die gleiche wie c = 100 oder in den meisten Fällen auch c = 98.

Hier ein Codebeispiel, bei dem die Randabflachung reduziert ist:

Ich habe das gbm-Paket nicht ausprobiert ...

Hier ist ein Beispielcode, der auf Ihrem Beispiel basiert ...

#more observations are created...
a <- runif(5000, 1, 100)
b <- runif(5000, 1, 100)
c <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
y <- (1:5000)/50 + rnorm(100, mean = 0, sd = 0.1)
par(mfrow = c(1,3))
plot(y ~ a); plot(y ~ b); plot(y ~ c)
Data <- data.frame(matrix(c(y, a, b, c), ncol = 4))
names(Data) <- c("y", "a", "b", "c")
library(randomForest)
#smaller nodesize "not as important" when there number of observartion is increased
#more tress can smooth flattening so boundery regions have best possible signal to             noise, data specific how many needed

plot.partial = function() {
partialPlot(rf.model, Data[,2:4], x.var = "a",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "b",xlim=c(1,100),ylim=c(1,100))
partialPlot(rf.model, Data[,2:4], x.var = "c",xlim=c(1,100),ylim=c(1,100))
}

#worst case! : with 100 samples from Data and nodesize=30
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=30)
plot.partial()

#reasonble settings for least partial flattening by few observations: 100 samples and nodesize=3 and ntrees=2000
#more tress can smooth flattening so boundery regions have best possiblefidelity
rf.model <- randomForest(y ~ a + b + c, data = Data[sample(5000,100),],nodesize=5,ntress=2000)
plot.partial()

#more observations is great!
rf.model <- randomForest(y ~ a + b + c,
 data = Data[sample(5000,5000),],
 nodesize=5,ntress=2000)
plot.partial()
Soren Havelund Welling
quelle
4

Wie in den obigen Kommentaren erwähnt, ist das GBM-Modell mit einigen Parametern besser geeignet. Eine einfache Möglichkeit, Probleme im Modell und die Notwendigkeit solcher Parameter zu erkennen, besteht darin, einige Diagnosediagramme zu erstellen. Zum Beispiel haben wir für das obige GBM-Modell mit den Standardparametern (und unter Verwendung des Plotmo- Pakets zum Erstellen der Plots)

gbm.gaus <- gbm(y~., data = Data, dist = "gaussian")
library(plotmo)   # for the plotres function
plotres(gbm.gaus) # plot the error per ntrees and the residuals

was gibt

Handlung

In der linken Darstellung sehen wir, dass die Fehlerkurve nicht den Boden erreicht hat. Und in der rechten Hand sind die Residuen nicht das, was wir wollen würden.

Wenn wir das Modell mit einer größeren Anzahl von Bäumen umbauen

gbm.gaus1 <- gbm(y~., data = Data, dist = "gaussian",
                 n.trees=5000, interact=3)
plotres(gbm.gaus1)

wir bekommen

Handlung

Wir sehen, dass die Fehlerkurve mit einer großen Anzahl von Bäumen den Grund erreicht und das Residuen-Diagramm gesünder ist. Wir können auch die partiellen Abhängigkeitsdiagramme für das neue gbm-Modell und das Zufallsforstmodell zeichnen

library(plotmo)
plotmo(gbm.gaus1, pmethod="partdep", all1=TRUE, all2=TRUE)
plotmo(rf.model,  pmethod="partdep", all1=TRUE, all2=TRUE)

was gibt

Handlung

Die gbm- und random forest-Modelldiagramme sind nun wie erwartet ähnlich.

Stephen Milborrow
quelle
3

Sie müssen Ihren interaction.depthParameter aktualisieren , wenn Sie Ihr verstärktes Modell erstellen. Der Standardwert ist 1, wodurch alle vom gbmAlgorithmus erstellten Bäume nur einmal geteilt werden. Dies würde bedeuten, dass sich jeder Baum nur in Variablen aufteilt cund sich je nach Stichprobe von Beobachtungen irgendwo zwischen 40 und 60 aufteilt.

Hier sind die Teilpläne mit interaction.depth = 3

Bildbeschreibung hier eingeben

Matt Mills
quelle
Guter Punkt, es ist
Soren Havelund Welling