Zufällige Wälder sind kaum eine Black Box. Sie basieren auf Entscheidungsbäumen, die sehr einfach zu interpretieren sind:
#Setup a binary classification problem
require(randomForest)
data(iris)
set.seed(1)
dat <- iris
dat$Species <- factor(ifelse(dat$Species=='virginica','virginica','other'))
trainrows <- runif(nrow(dat)) > 0.3
train <- dat[trainrows,]
test <- dat[!trainrows,]
#Build a decision tree
require(rpart)
model.rpart <- rpart(Species~., train)
Daraus ergibt sich ein einfacher Entscheidungsbaum:
> model.rpart
n= 111
node), split, n, loss, yval, (yprob)
* denotes terminal node
1) root 111 35 other (0.68468468 0.31531532)
2) Petal.Length< 4.95 77 3 other (0.96103896 0.03896104) *
3) Petal.Length>=4.95 34 2 virginica (0.05882353 0.94117647) *
Wenn Petal.Length <4,95, klassifiziert dieser Baum die Beobachtung als "andere". Wenn es größer als 4,95 ist, wird die Beobachtung als "virginica" klassifiziert. Eine zufällige Gesamtstruktur ist einfach eine Sammlung vieler solcher Bäume, wobei jeder auf eine zufällige Teilmenge der Daten trainiert wird. Jeder Baum "stimmt" dann über die endgültige Klassifizierung jeder Beobachtung ab.
model.rf <- randomForest(Species~., train, ntree=25, proximity=TRUE, importance=TRUE, nodesize=5)
> getTree(model.rf, k=1, labelVar=TRUE)
left daughter right daughter split var split point status prediction
1 2 3 Petal.Width 1.70 1 <NA>
2 4 5 Petal.Length 4.95 1 <NA>
3 6 7 Petal.Length 4.95 1 <NA>
4 0 0 <NA> 0.00 -1 other
5 0 0 <NA> 0.00 -1 virginica
6 0 0 <NA> 0.00 -1 other
7 0 0 <NA> 0.00 -1 virginica
Sie können sogar einzelne Bäume aus dem RF ziehen und deren Struktur betrachten. Das Format ist ein wenig anders als bei rpart
Modellen, aber Sie können jeden Baum untersuchen, um zu sehen, wie die Daten modelliert werden.
Darüber hinaus ist kein Modell wirklich eine Black Box, da Sie für jede Variable im Dataset die vorhergesagten Antworten mit den tatsächlichen Antworten vergleichen können. Dies ist eine gute Idee, unabhängig davon, welche Art von Modell Sie erstellen:
library(ggplot2)
pSpecies <- predict(model.rf,test,'vote')[,2]
plotData <- lapply(names(test[,1:4]), function(x){
out <- data.frame(
var = x,
type = c(rep('Actual',nrow(test)),rep('Predicted',nrow(test))),
value = c(test[,x],test[,x]),
species = c(as.numeric(test$Species)-1,pSpecies)
)
out$value <- out$value-min(out$value) #Normalize to [0,1]
out$value <- out$value/max(out$value)
out
})
plotData <- do.call(rbind,plotData)
qplot(value, species, data=plotData, facets = type ~ var, geom='smooth', span = 0.5)
Ich habe die Variablen (Länge und Breite der Kelchblätter und Blütenblätter) auf einen Bereich von 0-1 normalisiert. Die Antwort ist ebenfalls 0-1, wobei 0 eine andere und 1 eine virginica ist. Wie Sie sehen, ist der zufällige Wald ein gutes Modell, auch auf dem Test-Set.
Darüber hinaus berechnet eine zufällige Gesamtstruktur verschiedene Maße von unterschiedlicher Wichtigkeit, die sehr informativ sein können:
> importance(model.rf, type=1)
MeanDecreaseAccuracy
Sepal.Length 0.28567162
Sepal.Width -0.08584199
Petal.Length 0.64705819
Petal.Width 0.58176828
Diese Tabelle gibt an, um wie viel das Entfernen jeder Variablen die Genauigkeit des Modells verringert. Schließlich gibt es noch viele andere Diagramme, die Sie aus einem zufälligen Waldmodell erstellen können, um zu sehen, was in der Blackbox vor sich geht:
plot(model.rf)
plot(margin(model.rf))
MDSplot(model.rf, iris$Species, k=5)
plot(outlier(model.rf), type="h", col=c("red", "green", "blue")[as.numeric(dat$Species)])
Sie können die Hilfedateien für jede dieser Funktionen anzeigen, um eine bessere Vorstellung davon zu erhalten, was sie anzeigen.