Pacchetto R per Foresta casuale ponderata? opzione classwt?


16

Sto cercando di utilizzare Random Forest per prevedere il risultato di un set di dati estremamente squilibrato (il tasso di classe di minoranza è solo dell'1% o anche meno). Poiché l'algoritmo tradizionale Foresta casuale riduce al minimo il tasso di errore complessivo, anziché prestare particolare attenzione alle classi di minoranza, non è direttamente applicabile ai dati squilibrati. Quindi desidero assegnare un costo elevato alla classificazione errata della classe di minoranza (apprendimento sensibile ai costi).

Ho letto diverse fonti che possiamo utilizzare l'opzione classwtdi randomForestin R, ma non so come usare questo. E abbiamo altre alternative alla randomForestfuntion?

Risposte:


29

Questa discussione fa riferimento ad altre due discussioni e ad un bell'articolo su questo argomento. Sembra che il peso in classe e il downsampling siano ugualmente buoni. Uso il downsampling come descritto di seguito.

Ricorda che il set di allenamento deve essere ampio in quanto solo l'1% caratterizzerà la classe rara. Meno di 25 ~ 50 campioni di questa classe probabilmente saranno problematici. Pochi esempi che caratterizzano la classe renderanno inevitabilmente il modello appreso grezzo e meno riproducibile.

RF utilizza il voto a maggioranza come predefinito. Le prevalenze di classe del set di addestramento funzioneranno come una sorta di precedente efficace. Pertanto, a meno che la classe rara non sia perfettamente separabile, è improbabile che questa classe rara ottenga il voto a maggioranza quando prevede. Invece di aggregare per maggioranza, puoi aggregare le frazioni di voto.

Il campionamento stratificato può essere utilizzato per aumentare l'influenza della classe rara. Questo viene fatto sul costo del downsampling delle altre classi. Gli alberi cresciuti diventeranno meno profondi poiché sarà necessario suddividere un numero inferiore di campioni, limitando quindi la complessità del potenziale modello appreso. Il numero di alberi coltivati ​​dovrebbe essere elevato, ad esempio 4000, in modo tale che la maggior parte delle osservazioni partecipi a più alberi.

Nell'esempio seguente, ho simulato un set di dati di allenamento di 5000 campioni con 3 classi con prevalenza rispettivamente dell'1%, 49% e 50%. Quindi ci saranno 50 campioni di classe 0. La prima figura mostra la vera classe di training set in funzione di due variabili x1 e x2. Questa immagine mostra il modello simulato da imparare

Sono stati formati quattro modelli: un modello predefinito e tre modelli stratificati con stratificazione delle classi 1:10:10 1: 2: 2 e 1: 1: 1. Principalmente, mentre il numero di campioni inbag (incl. Ridisegni) in ciascun albero sarà 5000, 1050, 250 e 150. Dato che non utilizzo il voto a maggioranza, non ho bisogno di effettuare una stratificazione perfettamente bilanciata. Invece i voti su classi rare potrebbero essere ponderati 10 volte o su qualche altra regola decisionale. Il costo dei falsi negativi e dei falsi positivi dovrebbe influenzare questa regola.

La figura seguente mostra come la stratificazione influenza le frazioni di voto. Si noti che i rapporti di classe stratificati sono sempre il centroide delle previsioni. stratificazione e votazione

Infine, puoi usare una curva ROC per trovare una regola di voto che ti dia un buon compromesso tra specificità e sensibilità. La linea nera non è stratificata, rossa 1: 5: 5, verde 1: 2: 2 e blu 1: 1: 1. Per questo set di dati 1: 2: 2 o 1: 1: 1 sembra la scelta migliore. curva roc

A proposito, le frazioni di voto sono qui cross-validate fuori borsa.

E il codice:

library(plotrix)
library(randomForest)
library(AUC)

make.data = function(obs=5000,vars=6,noise.factor = .2,smallGroupFraction=.01) {
X = data.frame(replicate(vars,rnorm(obs)))
yValue = with(X,sin(X1*pi)+sin(X2*pi*2)+rnorm(obs)*noise.factor)
yQuantile = quantile(yValue,c(smallGroupFraction,.5))
yClass = apply(sapply(yQuantile,function(x) x<yValue),1,sum)
yClass = factor(yClass)
print(table(yClass)) #five classes, first class has 1% prevalence only
Data=data.frame(X=X,y=yClass)
}

plot.separation = function(rf,...) {
triax.plot(rf$votes,...,col.symbols = c("#FF0000FF",
                                       "#00FF0010",
                                       "#0000FF10")[as.numeric(rf$y)])
}

#make data set where class "0"(red circles) are rare observations
#Class 0 is somewhat separateble from class "1" and fully separateble from class "2"
Data = make.data()
par(mfrow=c(1,1))
plot(Data[,1:2],main="separation problem: identify rare red circles",
     col = c("#FF0000FF","#00FF0020","#0000FF20")[as.numeric(Data$y)])

#train default RF and with 10x 30x and 100x upsumpling by stratification
rf1 = randomForest(y~.,Data,ntree=500, sampsize=5000)
rf2 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,500,500),strata=Data$y)
rf3 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,100,100),strata=Data$y)
rf4 = randomForest(y~.,Data,ntree=4000,sampsize=c(50,50,50)  ,strata=Data$y)

#plot out-of-bag pluralistic predictions(vote fractions).
par(mfrow=c(2,2),mar=c(4,4,3,3))
plot.separation(rf1,main="no stratification")
plot.separation(rf2,main="1:10:10")
plot.separation(rf3,main="1:5:5")
plot.separation(rf4,main="1:1:1")

par(mfrow=c(1,1))
plot(roc(rf1$votes[,1],factor(1 * (rf1$y==0))),main="ROC curves for four models predicting class 0")
plot(roc(rf2$votes[,1],factor(1 * (rf1$y==0))),col=2,add=T)
plot(roc(rf3$votes[,1],factor(1 * (rf1$y==0))),col=3,add=T)
plot(roc(rf4$votes[,1],factor(1 * (rf1$y==0))),col=4,add=T)

la didascalia di una cifra dice 1: 5: 5 anziché 1: 2: 2
Soren Havelund Welling,

grazie mille per la tua risposta dettagliata, che sicuramente mi aiuterà molto nel mio lavoro quotidiano. C'è una frase che non capisco: "Principale mentre il numero di campioni inbag (incl. Ridisegni) in ogni albero sarà 5000, 1050, 250 e 150". Potresti spiegarmi da dove provengono i numeri?
Metariat,

1
piacere mio;) in questo esempio la rara classe contava 50 membri. Se si stratifica 1:10:10 dovremmo specificare sampsize = c (50.500.500). 50 + 500 + 500 = 1050. Un albero completamente cresciuto di 1050 campioni avrà 1050x2 nodi in totale.
Soren Havelund Welling,

Scusate se la mia domanda è idiota, ma qual è il significato della stratificazione 1:10:10, 1: 2: 2 e 1: 1: 1 qui? E quando hai detto "i voti sulle classi rare potevano essere ponderati 10 volte". Quale parte del codice rappresenta quello? È 1:10:10? Grazie mille!
Metariat,

1
1:10:10 sono i rapporti tra le classi. Il set di dati simulato è stato progettato per avere i rapporti 1:49:50. Questi rapporti sono stati modificati campionando le due classi più grandi. Scegliendo ad esempio sampsize = c (50.500.500) lo stesso di c (1,10,10) * 50 si modificano i rapporti di classe negli alberi. 50 è il numero di campioni della classe rara. Se impostate inoltre keep.inbag = TRUE e ispezionate rf $ inbag, vedrete che campioni di classi rare sono incorporati in ~ 2/3 alberi mentre ogni campione di classe non rara è incluso in pochissimi alberi a causa del down sampling.
Soren Havelund Welling,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.