Floresta aleatória: como lidar com novos níveis de fatores no conjunto de testes?

13

Estou tentando fazer previsões usando um modelo aleatório de floresta em R.

No entanto, recebo erros, pois alguns fatores têm valores diferentes no conjunto de testes e no conjunto de treinamento. Por exemplo, um fator Cat_2possui valores 34, 68, 76, etc., no conjunto de testes que não aparecem no conjunto de treinamento. Infelizmente, não tenho controle sobre o conjunto de testes ... devo usá-lo como está.

Minha única solução alternativa foi converter os fatores problemáticos novamente em valores numéricos, usando as.numeric(). Ele funciona , mas não estou muito satisfeito, uma vez que estes valores são códigos que não têm nenhum senso numérico ...

Você acha que haveria outra solução, eliminar os novos valores do conjunto de testes? Mas sem remover todos os outros valores de fator (digamos 1, 2, 14, 32, valores etc.) que estão no treinamento e no teste, e contém informações potencialmente úteis para previsões.

Benoit_Plante
fonte
1
Vejo a razão pela qual os valores no teste precisariam estar no conjunto de treinamento. A idéia da classificação é usar os dados de treinamento para ter uma idéia de como são as densidades condicionais de classe. Você não consegue ver todo valor possível da densidade. Se uma variável é usada em uma divisão em uma árvore, a divisão determina qual ramo seguir para quaisquer valores invisíveis, bem como aqueles que foram vistos.
Michael R. Chernick
Você faz uma observação válida, mas em um nível prático, usando a ferramenta específica consultada sobre (o pacote RF em R), isso não é permitido. Minha resposta envolvendo imputação é uma maneira de contornar isso, embora certamente não seja a melhor solução. É, pelo menos, faz com que o código não falhe, pelo menos funciona, para pequenos valores de trabalho.
Bogdanovist
Semelhante à minha pergunta aqui: stats.stackexchange.com/questions/18004/… . Eu acho que posso usar GBM em vez de RF, pois parece lidar melhor com novos níveis de fatores. Além disso, você analisou a implementação de RF em terceiros? Eu nunca gostei de randomForest por causa desses problemas (e incapacidade de lidar perfeitamente com os valores ausentes).
B_Miner

Respostas:

2

Se o conjunto de testes possui muitos desses pontos com novos valores de fator, não tenho certeza de qual é a melhor abordagem. Se for apenas um punhado de pontos, você poderá se safar de algo obsceno, como tratar os níveis de fatores errantes como dados ausentes e imputá-los com a abordagem que achar melhor. A implementação do R tem duas maneiras de imputar dados ausentes, basta definir esses níveis de fator como NA para indicar que eles estão ausentes.

Bogdanovist
fonte
8

King e Bonoit , esse trecho pode ser útil para harmonizar níveis:

for(attr in colnames(training))
{
  if (is.factor(training[[attr]]))
  {
    new.levels <- setdiff(levels(training[[attr]]), levels(testing[[attr]]))
    if ( length(new.levels) == 0 )
    { print(paste(attr, '- no new levels')) }
    else
    {
      print(c(paste(attr, length(new.levels), 'of new levels, e.g.'), head(new.levels, 2)))
      levels(testing[[attr]]) <- union(levels(testing[[attr]]), levels(training[[attr]]))
    }
  }
}

Também imprime quais atributos foram alterados. Não encontrei uma boa maneira de escrever com mais elegância (com ldply ou algo assim). Todas as dicas são apreciadas.

user41330
fonte
4

Aqui está um código que escrevi que aborda a resposta de @ King acima. Corrigiu o erro:

# loops through factors and standardizes the levels
for (f in 1:length(names(trainingDataSet))) {
    if (levels(testDataSet[,f]) > levels(trainingDataSet[,f])) {    
            levels(testDataSet[,f]) = levels(trainingDataSet[,f])       
    } else {
            levels(trainingDataSetSMOTEpred[,f]) = levels(testDataSet[,f])      
    }
}
lfarb
fonte
oi @ifarb, estou tentando entender sua solução: o que é trainingDataSetSMOTEpred e onde está definido no código?
Kasia Kulma
3

O conjunto de teste e treinamento deve ser combinado como um conjunto e depois alterar os níveis do conjunto de treinamento. Meus códigos são:

totalData <- rbind(trainData, testData)
for (f in 1:length(names(totalData))) {
  levels(trainData[, f]) <- levels(totalData[, f])
}

Isso funciona em todos os casos em que o número de níveis em teste é mais ou menos que o treinamento.

Cscode Li
fonte
2

Eu tenho uma solução ruim quando uso randomForest em R. Provavelmente não é teoricamente bom, mas deixa tudo funcionando.

levels(testSet$Cat_2) = levels(trainingSet$Cat_2)

ou do outro modo. Basicamente, ele apenas informa ao R que é um valor válido, pois existem 0 casos; então pare de me incomodar com o erro.

Não sou inteligente o suficiente para codificá-lo, de modo que ele execute automaticamente a ação para todos os recursos categóricos. Envie-me o código, se você souber como ...

Rei
fonte
Mas isso não funciona se o número de níveis em teste for maior que o treinamento. Funciona apenas se os níveis de fator de dados de teste forem <= níveis de fator de dados de treinamento.
precisa saber é o seguinte
1

Tenho certeza de que você já teria pensado nisso, se esse fosse o caso, mas se o conjunto de testes tiver valores reais e você estiver usando o conjunto de testes para fins de validação cruzada, re-divida o quadro de dados em quadros de dados de treinamento e teste onde os dois estão equilibrados com esses fatores, evitaria o seu problema. Esse método é conhecido popularmente como validação cruzada estratificada .

goldisfine
fonte