Pakiet R dla Weighted Random Forest? opcja classwt?

16

Próbuję użyć Losowego Lasu, aby przewidzieć wynik bardzo niezrównoważonego zestawu danych (wskaźnik klasy mniejszości wynosi około 1% lub nawet mniej). Ponieważ tradycyjny algorytm losowego lasu minimalizuje ogólny poziom błędu, zamiast zwracać szczególną uwagę na klasy mniejszości, nie ma bezpośredniego zastosowania do niezrównoważonych danych. Chcę więc przypisać wysoki koszt błędnej klasyfikacji klasy mniejszościowej (uczenie wrażliwe na koszty).

Czytałem kilka źródeł, że możemy skorzystać z opcji classwtz randomForestw R, ale nie wiem jak tego używać. Czy mamy jakieś inne alternatywy dla tej randomForestfunkcji?

Metariat
źródło

Odpowiedzi:

29

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. To zdjęcie pokazuje symulowany wzór do nauki

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. rozwarstwienie i głosowanie

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. krzywa Roca

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)
Soren Havelund Welling
źródło
oups jeden podpis liczby mówi 1: 5: 5 zamiast 1: 2: 2
Soren Havelund Welling
bardzo dziękuję za szczegółową odpowiedź, która zdecydowanie pomoże mi w codziennej pracy. Jest jedno zdanie, którego nie rozumiem: „Główne, podczas gdy liczba próbek inbag (łącznie z przerysowaniem) w każdym drzewie będzie wynosić 5000, 1050, 250 i 150”. Czy mógłbyś mi wyjaśnić, skąd pochodzą te liczby?
Metariat
1
z przyjemnością;) w tym przykładzie rzadka klasa liczyła 50 członków. Jeśli rozwarstwiając 1:10:10, musielibyśmy podać sampsize = c (50.500.500). 50 + 500 + 500 = 1050. W pełni dorosłe drzewo z 1050 próbek będzie miało łącznie 1050 x 2 węzły.
Soren Havelund Welling
Przepraszam, jeśli moje pytanie jest idiotą, ale jakie znaczenie ma tutaj rozwarstwienie 1:10:10, 1: 2: 2 i 1: 1: 1? A kiedy powiedziałeś „głosy na rzadkie klasy mogą być ważone 10 razy”. Która część kodu to reprezentuje? Czy to 1:10:10? Dziękuję Ci bardzo!
Metariat
1
1:10:10 to stosunki między klasami. Symulowany zestaw danych zaprojektowano tak, aby miał stosunki 1:49:50. Te współczynniki zostały zmienione przez próbkowanie w dół dwóch większych klas. Wybierając np. Sampsize = c (50.500.500) tak samo jak c (1,10,10) * 50, zmieniasz stosunki klas w drzewach. 50 to liczba próbek rzadkiej klasy. Jeśli ponadto ustawisz keep.inbag = PRAWDA i sprawdzisz rf $ inbag, zobaczysz, że próbki rzadkich klas są inbag u ~ 2/3 drzew, podczas gdy każda nierzadka próbka klasy jest zawarta w bardzo niewielu drzewach z powodu zmniejszonego próbkowania.
Soren Havelund Welling