Pacote R para floresta aleatória ponderada? opção classwt?

16

Estou tentando usar a floresta aleatória para prever o resultado de um conjunto de dados extremamente desequilibrado (a taxa de classe minoritária é de apenas 1% ou até menos). Como o algoritmo tradicional de floresta aleatória minimiza a taxa de erro geral, em vez de prestar atenção especial às classes minoritárias, ele não é diretamente aplicável a dados desequilibrados. Então, eu quero atribuir um alto custo à classificação incorreta da classe minoritária (aprendizagem sensível aos custos).

Eu li várias fontes que podemos usar a opção classwtde randomForestno R, mas eu não sei como usar isso. E temos outras alternativas para a randomForestfunção?

Metariat
fonte

Respostas:

29

Esse tópico refere-se a outros dois tópicos e a um bom artigo sobre esse assunto. Parece que ponderação de classe e downsampling são igualmente boas. Eu uso downsampling como descrito abaixo.

Lembre-se de que o conjunto de treinamento deve ser grande, pois apenas 1% caracterizará a classe rara. Menos de 25 a 50 amostras dessa classe provavelmente serão problemáticas. Poucas amostras que caracterizam a classe tornarão inevitavelmente o padrão aprendido e menos reprodutível.

O RF usa a votação majoritária como padrão. As prevalências de classe do conjunto de treinamento funcionarão como algum tipo de efetiva anterior. Assim, a menos que a classe rara seja perfeitamente separável, é improvável que essa classe rara ganhe uma votação majoritária ao prever. Em vez de agregar por maioria de votos, você pode agregar frações de votos.

A amostragem estratificada pode ser usada para aumentar a influência da classe rara. Isso é feito com o custo de reduzir a amostragem das outras classes. As árvores cultivadas se tornarão menos profundas, pois menos amostras precisam ser divididas, limitando a complexidade do padrão potencial aprendido. O número de árvores cultivadas deve ser grande, por exemplo, 4000, para que a maioria das observações participe de várias árvores.

No exemplo abaixo, simulei um conjunto de dados de treinamento de 5000 amostras com 3 classes com prevalências de 1%, 49% e 50%, respectivamente. Assim, haverá 50 amostras da classe 0. A primeira figura mostra a verdadeira classe de treinamento definida em função de duas variáveis ​​x1 e x2. Esta figura mostra o padrão simulado para aprender

Quatro modelos foram treinados: Um modelo padrão e três modelos estratificados com estratificação de classes 1:10:10 1: 2: 2 e 1: 1: 1. Principal enquanto o número de amostras inbag (incluindo redesenhos) em cada árvore será 5000, 1050, 250 e 150. Como não uso a votação por maioria, não preciso fazer uma estratificação perfeitamente equilibrada. Em vez disso, os votos em classes raras podem ser ponderados 10 vezes ou em alguma outra regra de decisão. Seu custo de falsos negativos e falsos positivos deve influenciar essa regra.

A próxima figura mostra como a estratificação influencia as frações de voto. Observe que as proporções estratificadas de classe sempre são o centróide das previsões. estratificação e votação

Por fim, você pode usar uma curva ROC para encontrar uma regra de votação que ofereça uma boa relação entre especificidade e sensibilidade. A linha preta não possui estratificação, vermelha 1: 5: 5, verde 1: 2: 2 e azul 1: 1: 1. Para esse conjunto de dados 1: 2: 2 ou 1: 1: 1, parece a melhor opção. curva roc

A propósito, as frações de voto estão aqui com a validação cruzada.

E o código:

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
fonte
oups uma legenda diz 1: 5: 5 em vez de 1: 2: 2
Soren Havelund Welling
muito obrigado pela sua resposta detalhada, que definitivamente vai me ajudar muito no meu trabalho diário. Há uma frase que eu não entendo: "Principal, enquanto o número de amostras da bolsa (incluindo redesenhados) em cada árvore será 5000, 1050, 250 e 150". Você poderia me explicar de onde vêm os números?
Metariat 22/06
11
meu prazer;) neste exemplo, a classe rara tinha 50 membros. Se estratificar 1:10:10, precisaríamos especificar sampsize = c (50.500.500). 50 + 500 + 500 = 1050. Uma árvore totalmente crescida de 1050 amostras terá 1050x2 nós no total.
Soren Havelund Welling
Desculpe se minha pergunta é idiota, mas qual é o significado de estratificação 1:10:10, 1: 2: 2 e 1: 1: 1 aqui? E quando você disse "os votos em classes raras podem ser ponderados 10 vezes". Qual parte do código representa isso? É 1:10:10? Muito obrigado!
Metariat 24/06
11
1:10:10 são as proporções entre as classes. O conjunto de dados simulados foi projetado para ter as proporções 1:49:50. Essas proporções foram alteradas pela amostragem das duas classes maiores. Ao escolher, por exemplo, tamanho da amostra = c (50.500.500) o mesmo que c (1,10,10) * 50, você altera as proporções de classe nas árvores. 50 é o número de amostras da classe rara. Se você definir keep.inbag = TRUE e inspecionar rf $ inbag, verá que amostras das classes raras são inbag em ~ 2/3 árvores, enquanto cada amostra de classe não-rara é incluída em muito poucas árvores devido à amostragem reduzida.
Soren Havelund Welling