Ten wątek odnosi się do dwóch innych wątków i dobrego artykułu na ten temat. Wygląda na to, że ważenie klas i próbkowanie w dół są równie dobre. Używam próbkowania w dół, jak opisano poniżej.
Pamiętaj, że zestaw treningowy musi być duży, ponieważ tylko 1% będzie charakteryzował rzadką klasę. Problemem będzie prawdopodobnie mniej niż 25 ~ 50 próbek tej klasy. Niewiele próbek charakteryzujących klasę nieuchronnie sprawi, że wyuczony wzór będzie surowy i mniej powtarzalny.
RF domyślnie stosuje głosowanie większością głosów. Preferencje klasowe zestawu treningowego będą działać jako pewnego rodzaju skuteczny wcześniej. Tak więc, chyba że rzadka klasa jest całkowicie rozdzielna, jest mało prawdopodobne, że ta rzadka klasa zdobędzie większość głosów podczas przewidywania. Zamiast agregować według większości głosów, można agregować ułamki głosów.
W celu zwiększenia wpływu rzadkiej klasy można zastosować stratyfikowane pobieranie próbek. Odbywa się to na koszt próbkowania w dół innych klas. Wyhodowane drzewa staną się mniej głębokie, ponieważ trzeba będzie podzielić mniej próbek, co ograniczy złożoność poznanego potencjalnego wzoru. Liczba wyhodowanych drzew powinna być duża, np. 4000, aby większość obserwacji uczestniczyła w kilku drzewach.
W poniższym przykładzie przeprowadziłem symulację zestawu danych treningowych 5000 próbek z 3 klasami z częstością odpowiednio 1%, 49% i 50%. Zatem będzie 50 próbek klasy 0. Pierwszy rysunek pokazuje prawdziwą klasę zestawu treningowego jako funkcję dwóch zmiennych x1 i x2.
Przeszkolono cztery modele: model domyślny i trzy modele warstwowe z rozwarstwieniem klas 1:10:10 1: 2: 2 i 1: 1: 1. Główna, podczas gdy liczba próbek inbag (w tym przerysowań) w każdym drzewie będzie wynosić 5000, 1050, 250 i 150. Ponieważ nie stosuję głosowania większością głosów, nie muszę wykonywać idealnie zrównoważonej stratyfikacji. Zamiast tego głosy na rzadkich klasach mogłyby być ważone 10 razy lub według innej reguły decyzyjnej. Twój koszt fałszywych negatywów i fałszywych trafień powinien wpłynąć na tę zasadę.
Kolejny rysunek pokazuje, w jaki sposób rozwarstwienie wpływa na ułamki głosów. Zauważ, że stratyfikowane stosunki klas zawsze są środkiem ciężkości prognoz.
Na koniec możesz użyć krzywej ROC, aby znaleźć regułę głosowania, która zapewnia dobry kompromis między specyficznością a czułością. Czarna linia nie ma rozwarstwienia, czerwona 1: 5: 5, zielona 1: 2: 2 i niebieska 1: 1: 1. W przypadku tego zestawu danych 1: 2: 2 lub 1: 1: 1 wydaje się najlepszym wyborem.
Nawiasem mówiąc, ułamki głosów są tutaj sprawdzane krzyżowo.
I kod:
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)