Dieser Thread bezieht sich auf zwei weitere Threads und einen guten Artikel zu diesem Thema. Es scheint, dass Klassengewichtung und Downsampling gleich gut sind. Ich benutze Downsampling wie unten beschrieben.
Denken Sie daran, dass der Trainingssatz groß sein muss, da nur 1% die seltene Klasse charakterisieren. Weniger als 25 bis 50 Proben dieser Klasse werden wahrscheinlich problematisch sein. Wenige Samples, die die Klasse charakterisieren, machen das erlernte Muster zwangsläufig grob und weniger reproduzierbar.
RF verwendet standardmäßig die Mehrheitsentscheidung. Die Klassenprävalenzen des Trainingssatzes gelten als eine Art wirksamer Prior. Daher ist es unwahrscheinlich, dass diese seltene Klasse bei der Vorhersage eine Mehrheit erhält, es sei denn, die seltene Klasse ist vollständig trennbar. Anstatt nach Stimmenmehrheit zu aggregieren, können Sie Stimmenbruchteile aggregieren.
Schichtproben können verwendet werden, um den Einfluss der seltenen Klasse zu erhöhen. Dies geschieht auf der Grundlage der Kosten für das Downsampling der anderen Klassen. Die gewachsenen Bäume werden weniger tief, da viel weniger Proben aufgeteilt werden müssen, wodurch die Komplexität des erlernten potenziellen Musters begrenzt wird. Die Anzahl der gewachsenen Bäume sollte groß sein, z. B. 4000, so dass die meisten Beobachtungen an mehreren Bäumen teilnehmen.
Im folgenden Beispiel habe ich einen Trainingsdatensatz von 5000 Proben mit 3 Klassen mit Prävalenzen von 1%, 49% bzw. 50% simuliert. Somit gibt es 50 Proben der Klasse 0. Die erste Abbildung zeigt die wahre Trainingsklasse als Funktion von zwei Variablen x1 und x2.
Es wurden vier Modelle trainiert: Ein Standardmodell und drei geschichtete Modelle mit einer 1: 2: 2- und einer 1: 1: 1-Klassenschichtung von 1:10:10. Main, während die Anzahl der Inbag-Samples (inkl. Neuzeichnungen) in jedem Baum 5000, 1050, 250 und 150 beträgt. Da ich keine Mehrheitsabstimmung verwende, muss ich keine perfekt ausgewogene Schichtung vornehmen. Stattdessen könnten die Stimmen in seltenen Klassen zehnmal oder nach einer anderen Entscheidungsregel gewichtet werden. Ihre Kosten für falsch negative und falsch positive Ergebnisse sollten diese Regel beeinflussen.
Die nächste Abbildung zeigt, wie die Schichtung die Stimmenanteile beeinflusst. Beachten Sie, dass die geschichteten Klassenverhältnisse immer der Schwerpunkt der Vorhersagen sind.
Zuletzt können Sie eine ROC-Kurve verwenden, um eine Abstimmungsregel zu finden, die Ihnen einen guten Kompromiss zwischen Spezifität und Sensitivität bietet. Schwarze Linie ist keine Schichtung, rot 1: 5: 5, grün 1: 2: 2 und blau 1: 1: 1. Für diesen Datensatz scheint 1: 2: 2 oder 1: 1: 1 die beste Wahl zu sein.
Stimmenbruchteile werden hier übrigens out-of-bag crossvalidiert.
Und der Code:
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)