Losowe lasy nie są czarną skrzynką. Opierają się na drzewach decyzyjnych, które są bardzo łatwe do interpretacji:
#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)
W rezultacie powstaje proste drzewo decyzyjne:
> 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) *
Jeśli długość płatka <4,95, drzewo to klasyfikuje obserwację jako „inne”. Jeśli jest większy niż 4,95, klasyfikuje obserwację jako „virginica”. Losowy las to prosty zbiór wielu takich drzew, z których każde jest trenowane na losowym podzbiorze danych. Każde drzewo następnie „głosuje” na ostateczną klasyfikację każdej obserwacji.
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
Możesz nawet wyciągać pojedyncze drzewa z RF i patrzeć na ich strukturę. Format jest nieco inny niż w przypadku rpart
modeli, ale możesz sprawdzić każde drzewo, jeśli chcesz, i zobaczyć, jak modeluje dane.
Ponadto żaden model nie jest tak naprawdę czarną skrzynką, ponieważ można zbadać przewidywane odpowiedzi w stosunku do rzeczywistych odpowiedzi dla każdej zmiennej w zestawie danych. To dobry pomysł niezależnie od tego, jaki model budujesz:
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)
Znormalizowałem zmienne (długość i szerokość płatka i płatka) do zakresu 0-1. Odpowiedź wynosi również 0-1, gdzie 0 to inne, a 1 to virginica. Jak widać, losowy las jest dobrym modelem, nawet na zestawie testowym.
Ponadto losowy las obliczy różne miary o różnym znaczeniu, które mogą być bardzo pouczające:
> importance(model.rf, type=1)
MeanDecreaseAccuracy
Sepal.Length 0.28567162
Sepal.Width -0.08584199
Petal.Length 0.64705819
Petal.Width 0.58176828
Ta tabela przedstawia, jak bardzo usunięcie każdej zmiennej zmniejsza dokładność modelu. Na koniec istnieje wiele innych działek, które można wykonać z losowego modelu lasu, aby zobaczyć, co dzieje się w czarnej skrzynce:
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)])
Możesz wyświetlić pliki pomocy dla każdej z tych funkcji, aby uzyskać lepszy obraz tego, co wyświetlają.