Une forêt aléatoire correctement exécutée appliquée à un problème mieux "forêt aléatoire appropriée" peut servir de filtre pour supprimer le bruit et générer des résultats plus utiles en tant qu'entrées pour d'autres outils d'analyse.
Avertissements:
- Est-ce une "solution miracle"? En aucune façon. Le kilométrage variera. Cela fonctionne où cela fonctionne, et pas ailleurs.
- Existe-t-il des moyens de l'utiliser brutalement et d'obtenir des réponses erronées? youbetcha. Comme tout outil d'analyse, il a des limites.
- Si vous léchez une grenouille, votre haleine aura-t-elle une odeur de grenouille? probable. Je n'ai pas d'expérience là-bas.
Je dois donner un "cri" à mes "peeps" qui ont fait "Spider". ( lien ) Leur exemple de problème a éclairé mon approche. ( lien ) J'aime aussi les estimateurs de Theil-Sen, et j'aimerais pouvoir donner des accessoires à Theil et Sen.
Ma réponse ne porte pas sur la façon de se tromper, mais sur la façon dont cela pourrait fonctionner si vous aviez la plupart du temps raison. Bien que j'utilise un bruit "trivial", je souhaite que vous réfléchissiez au bruit "non-trivial" ou "structuré".
L’un des atouts d’une forêt aléatoire est sa capacité à s’appliquer aux problèmes de grandes dimensions. Je ne peux pas afficher des colonnes de 20 ko (un espace dimensionnel de 20 ko) de manière visuelle. Ce n'est pas une tâche facile. Toutefois, si vous rencontrez un problème de 20 000 dimensions, une forêt aléatoire peut être un bon outil lorsque la plupart des autres tombent à plat sur leurs "faces".
Voici un exemple de suppression du bruit d'un signal à l'aide d'une forêt aléatoire.
#housekeeping
rm(list=ls())
#library
library(randomForest)
#for reproducibility
set.seed(08012015)
#basic
n <- 1:2000
r <- 0.05*n +1
th <- n*(4*pi)/max(n)
#polar to cartesian
x1=r*cos(th)
y1=r*sin(th)
#add noise
x2 <- x1+0.1*r*runif(min = -1,max = 1,n=length(n))
y2 <- y1+0.1*r*runif(min = -1,max = 1,n=length(n))
#append salt and pepper
x3 <- runif(min = min(x2),max = max(x2),n=length(n)/2)
y3 <- runif(min = min(y2),max = max(y2),n=length(n)/2)
x4 <- c(x2,x3)
y4 <- c(y2,y3)
z4 <- as.vector(matrix(1,nrow=length(x4)))
#plot class "A" derivation
plot(x1,y1,pch=18,type="l",col="Red", lwd=2)
points(x2,y2)
points(x3,y3,pch=18,col="Blue")
legend(x = 65,y=65,legend = c("true","sampled","false"),
col = c("Red","Black","Blue"),lty = c(1,-1,-1),pch=c(-1,1,18))
Permettez-moi de décrire ce qui se passe ici. Cette image ci-dessous montre les données d'entraînement pour la classe "1". La classe "2" est uniformément aléatoire sur le même domaine et la même plage. Vous pouvez voir que "l'information" de "1" est principalement une spirale, mais a été corrompue avec le matériel de "2". Avoir 33% de vos données corrompues peut être un problème pour de nombreux outils d'adaptation. Theil-Sen commence à se dégrader à environ 29%. ( lien )
Nous séparons maintenant les informations et n’avons qu’une idée de ce qu'est le bruit.
#Create "B" class of uniform noise
x5 <- runif(min = min(x4),max = max(x4),n=length(x4))
y5 <- runif(min = min(y4),max = max(y4),n=length(x4))
z5 <- 2*z4
#assemble data into frame
data <- data.frame(c(x4,x5),c(y4,y5),as.factor(c(z4,z5)))
names(data) <- c("x","y","z")
#train random forest - I like h2o, but this is textbook Breimann
fit.rf <- randomForest(z~.,data=data,
ntree = 1000, replace=TRUE, nodesize = 20)
data2 <- predict(fit.rf,newdata=data[data$z==1,c(1,2)],type="response")
#separate class "1" from training data
idx1a <- which(data[,3]==1)
#separate class "1" from the predicted data
idx1b <- which(data2==1)
#show the difference in classes before and after RF based filter
plot(data[idx1a,1],data[idx1a,2])
points(data[idx1b,1],data[idx1b,2],col="Red")
Voici le résultat approprié:
J'aime beaucoup cela, car il peut montrer à la fois les forces et les faiblesses d’une méthode décente face à un problème difficile. Si vous regardez près du centre, vous constaterez que le filtrage est moins efficace. L'échelle géométrique de l'information est petite et la forêt aléatoire en manque. Cela dit quelque chose sur le nombre de nœuds, le nombre d'arbres et la densité d'échantillon pour la classe 2. Il existe également un "écart" proche de (-50, -50) et des "jets" à plusieurs endroits. En général, cependant, le filtrage est correct.
Comparez vs SVM
Voici le code pour permettre une comparaison avec SVM:
#now to fit to svm
fit.svm <- svm(z~., data=data, kernel="radial",gamma=10,type = "C")
x5 <- seq(from=min(x2),to=max(x2),by=1)
y5 <- seq(from=min(y2),to=max(y2),by=1)
count <- 1
x6 <- numeric()
y6 <- numeric()
for (i in 1:length(x5)){
for (j in 1:length(y5)){
x6[count]<-x5[i]
y6[count]<-y5[j]
count <- count+1
}
}
data4 <- data.frame(x6,y6)
names(data4) <- c("x","y")
data4$z <- predict(fit.svm,newdata=data4)
idx4 <- which(data4$z==1,arr.ind=TRUE)
plot(data4[idx4,1],data4[idx4,2],col="Gray",pch=20)
points(data[idx1b,1],data[idx1b,2],col="Blue",pch=20)
lines(x1,y1,pch=18,col="Green", lwd=2)
grid()
legend(x = 65,y=65,
legend = c("true","from RF","From SVM"),
col = c("Green","Blue","Gray"),lty = c(1,-1,-1),pch=c(-1,20,15),pt.cex=c(1,1,2.25))
Il en résulte l'image suivante.
Ceci est un SVM décent. Le gris est le domaine associé à la classe "1" par le SVM. Les points bleus sont les échantillons associés à la classe "1" par le RF. Le filtre RF fonctionne de manière comparable au SVM sans base explicitement imposée. On peut voir que les "données serrées" près du centre de la spirale sont beaucoup plus "étroitement" résolues par le RF. Il y a aussi des "îles" vers la "queue" où le RF trouve une association que le SVM ne fait pas.
Je suis diverti. Sans avoir le fond, j'ai fait l'une des premières choses également faites par un très bon contributeur sur le terrain. L'auteur d'origine utilisait "distribution de référence" ( lien , lien ).
MODIFIER:
Appliquez FOREST de manière aléatoire à ce modèle: bien
que user777 ait bien pensé qu'un CART soit l'élément d'une forêt aléatoire, le principe de base de la forêt aléatoire est "l'agrégation d'ensemble d'apprenants faibles". Le CART est un élève faible connu, mais ce n’est rien à distance d’un "ensemble". L '"ensemble", bien que dans une forêt aléatoire, est destiné "dans la limite d'un grand nombre d'échantillons". La réponse de user777, dans le diagramme de dispersion, utilise au moins 500 échantillons, ce qui en dit long sur la lisibilité humaine et la taille des échantillons. Le système visuel humain (lui-même un ensemble d'apprenants) est un capteur et un processeur de données étonnants et il considère que cette valeur est suffisante pour faciliter le traitement.
Si nous prenons même les paramètres par défaut sur un outil de forêt aléatoire, nous pouvons observer que le comportement de l'erreur de classification augmente pour les premiers arbres, et n'atteint pas le niveau d'arbre avant qu'il y ait environ 10 arbres. Initialement, l'erreur augmente, la réduction d'erreur devient stable autour de 60 arbres. Par stable je veux dire
x <- cbind(x1, x2)
plot(rf,type="b",ylim=c(0,0.06))
grid()
Quels rendements:
Si, au lieu de regarder le "minimum faible apprenant", nous regardons le "minimum faible ensemble" suggéré par une heuristique très brève pour le réglage par défaut de l'outil, les résultats sont quelque peu différents.
Notez, j'ai utilisé des "lignes" pour dessiner le cercle indiquant le bord sur l'approximation. Vous pouvez voir que c'est imparfait, mais bien meilleur que la qualité d'un seul apprenant.
L'échantillonnage d'origine comprend 88 échantillons "intérieurs". Si la taille des échantillons est augmentée (en permettant à l'ensemble de s'appliquer), la qualité de l'approximation s'améliore également. Le même nombre d'apprenants avec 20 000 échantillons constitue un meilleur ajustement.
Les informations d’entrée beaucoup plus qualitatives permettent également d’évaluer le nombre approprié d’arbres. L'inspection de la convergence suggère que 20 arbres est le nombre minimal suffisant dans ce cas particulier pour bien représenter les données.