Una foresta casuale eseguita correttamente applicata a un problema che è più "foresta casuale appropriata" può funzionare come filtro per rimuovere il rumore e ottenere risultati più utili come input per altri strumenti di analisi.
Avvertenze:
- È un "proiettile d'argento"? Non c'è modo. Il chilometraggio varierà. Funziona dove funziona e non altrove.
- Ci sono modi in cui puoi usarlo gravemente in modo errato e ottenere risposte nel dominio junk-to-voodoo? youbetcha. Come ogni strumento analitico, ha dei limiti.
- Se lecchi una rana, il tuo respiro puzza di rana? probabile. Non ho esperienza lì.
Devo dare un "grido" ai miei "pig" che hanno fatto "Spider". ( link ) Il loro problema di esempio ha informato il mio approccio. ( link ) Adoro anche gli stimatori di Theil-Sen e vorrei poter offrire oggetti di scena a Theil e Sen.
La mia risposta non è su come sbagliarla, ma su come potrebbe funzionare se la prendessi per lo più nel modo giusto. Mentre uso un rumore "banale", voglio che tu pensi al rumore "non banale" o "strutturato".
Uno dei punti di forza di una foresta casuale è quanto bene si applica ai problemi ad alta dimensione. Non riesco a mostrare 20k colonne (ovvero uno spazio dimensionale 20k) in un modo visivamente pulito. Non è un compito facile. Tuttavia, se hai un problema di 20k dimensioni, una foresta casuale potrebbe essere un buon strumento lì quando la maggior parte degli altri si appiattisce sulle loro "facce".
Questo è un esempio di rimozione del rumore dal segnale usando una foresta casuale.
#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))
Lasciami descrivere cosa sta succedendo qui. L'immagine seguente mostra i dati di allenamento per la classe "1". La classe "2" è casuale uniforme nello stesso dominio e intervallo. Puoi vedere che le "informazioni" di "1" sono principalmente una spirale, ma sono state corrotte con materiale proveniente da "2". Avere il 33% dei dati danneggiati può essere un problema per molti strumenti di adattamento. Theil-Sen inizia a degradare a circa il 29%. ( link )
Ora separiamo le informazioni, avendo solo un'idea di cosa sia il rumore.
#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")
Ecco il risultato del montaggio:
Mi piace molto perché può mostrare contemporaneamente sia i punti di forza che i punti deboli di un metodo decente a un problema difficile. Se guardi vicino al centro puoi vedere come c'è meno filtro. La scala geometrica delle informazioni è piccola e manca alla foresta casuale. Dice qualcosa sul numero di nodi, il numero di alberi e la densità del campione per la classe 2. C'è anche uno "spazio" vicino (-50, -50) e "getti" in diverse posizioni. In generale, tuttavia, il filtro è decente.
Confronta vs. SVM
Ecco il codice per consentire un confronto con 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))
Risulta nella seguente immagine.
Questo è un SVM decente. Il grigio è il dominio associato alla classe "1" da SVM. I punti blu sono i campioni associati alla classe "1" dalla RF. Il filtro basato su RF offre prestazioni comparabili a SVM senza una base esplicitamente imposta. Si può vedere che i "dati stretti" vicino al centro della spirale sono molto più "strettamente" risolti dalla RF. Ci sono anche "isole" verso la "coda" in cui la RF trova associazione che SVM non ha.
Sono divertito. Senza avere il background, ho fatto una delle prime cose fatte anche da un ottimo collaboratore sul campo. L'autore originale ha usato la "distribuzione di riferimento" ( link , link ).
MODIFICARE:
Applica FOREST casuale a questo modello:
Mentre user777 ha una buona idea che una CART sia l'elemento di una foresta casuale, la premessa della foresta casuale è "aggregazione di gruppi di discenti deboli". Il CART è uno studente debole noto ma non è nulla di remoto vicino a un "ensemble". L '"insieme", sebbene in una foresta casuale sia inteso "nel limite di un gran numero di campioni". La risposta di user777, nel grafico a dispersione, utilizza almeno 500 campioni e dice qualcosa sulla leggibilità umana e le dimensioni dei campioni in questo caso. Il sistema visivo umano (a sua volta un insieme di discenti) è un sensore e un elaboratore di dati straordinari e trova quel valore sufficiente per facilitare l'elaborazione.
Se prendiamo anche le impostazioni predefinite su uno strumento a foresta casuale, possiamo osservare che il comportamento dell'errore di classificazione aumenta per i primi diversi alberi e non raggiunge il livello di un albero finché non ci sono circa 10 alberi. Inizialmente l'errore cresce, la riduzione dell'errore diventa stabile attorno a 60 alberi. Per stabile intendo
x <- cbind(x1, x2)
plot(rf,type="b",ylim=c(0,0.06))
grid()
Che produce:
Se invece di guardare lo "studente minimo debole" osserviamo l '"insieme minimo debole" suggerito da una breve euristica per l'impostazione predefinita dello strumento, i risultati sono leggermente diversi.
Nota, ho usato "linee" per disegnare il cerchio che indica il bordo sopra l'approssimazione. Puoi vedere che è imperfetto, ma molto meglio della qualità di un singolo studente.
Il campionamento originale ha 88 campioni "interni". Se le dimensioni del campione vengono aumentate (consentendo l'applicazione dell'ensemble), migliora anche la qualità dell'approssimazione. Lo stesso numero di studenti con 20.000 campioni si adatta in modo incredibilmente migliore.
Le informazioni di input di qualità molto più elevata consentono anche la valutazione del numero appropriato di alberi. L'ispezione della convergenza suggerisce che in questo caso particolare 20 alberi rappresentano il numero minimo sufficiente per rappresentare bene i dati.