Forêt aléatoire: comment gérer les nouveaux niveaux de facteurs dans l'ensemble de test?

13

J'essaie de faire des prédictions en utilisant un modèle de forêt aléatoire dans R.

Cependant, je reçois des erreurs car certains facteurs ont des valeurs différentes dans l'ensemble de test que dans l'ensemble d'entraînement. Par exemple, un facteur Cat_2a des valeurs 34, 68, 76, etc., dans l'ensemble de test qui n'apparaissent pas dans l'ensemble d'apprentissage. Malheureusement, je n'ai aucun contrôle sur l'ensemble de test ... Je dois l'utiliser tel quel.

Ma seule solution de contournement a été de reconvertir les facteurs problématiques en valeurs numériques, en utilisant as.numeric(). Cela fonctionne mais je ne suis pas très satisfait, car ces valeurs sont des codes qui n'ont aucun sens numérique ...

Pensez-vous qu'il y aurait une autre solution, pour supprimer les nouvelles valeurs de l'ensemble de test? Mais sans supprimer toutes les autres valeurs de facteur (disons les valeurs1, 2, 14, 32 , etc.) qui sont à la fois dans la formation et le test, et contient des informations potentiellement utiles pour les prévisions.

Benoit_Plante
la source
1
Je vois la raison pour laquelle les valeurs du test devraient être dans l'ensemble de formation. L'idée de la classification est d'utiliser les données d'apprentissage pour avoir une idée de ce à quoi ressemblent les densités conditionnelles de classe. Vous ne voyez pas toutes les valeurs possibles de la densité. Si une variable est utilisée dans un arbre divisé, la division détermine la branche à suivre pour toutes les valeurs invisibles ainsi que celles qui ont été vues.
Michael R. Chernick
Vous faites valoir un argument valable, mais sur le plan pratique, en utilisant l'outil spécifique demandé (le package RF dans R), cela n'est pas autorisé. Ma réponse concernant l'imputation est une solution, mais certainement pas la meilleure solution. Cela ne fait au moins pas planter le code, donc au moins fonctionne, pour les petites valeurs de travail.
Bogdanovist
Similaire à ma question ici: stats.stackexchange.com/questions/18004/… . Je pense que je pourrais utiliser GBM au lieu de RF car il semble mieux gérer les nouveaux niveaux de facteurs. Avez-vous également examiné la mise en œuvre de la RF dans le parti? Je n'ai jamais aimé randomForest à cause de ces problèmes (et de l'impossibilité de traiter de manière transparente les valeurs manquantes).
B_Miner

Réponses:

2

Si l'ensemble de test contient beaucoup de ces points avec de nouvelles valeurs de facteur, je ne sais pas quelle est la meilleure approche. S'il ne s'agit que de quelques points, vous pourrez peut-être vous en sortir avec quelque chose de flou, comme traiter les niveaux de facteur erronés comme des données manquantes et les imputer avec l'approche que vous jugerez appropriée. L'implémentation R a deux façons d'imputer les données manquantes, il vous suffit de définir ces niveaux de facteur sur NA pour indiquer qu'ils sont manquants.

Bogdanovist
la source
8

King et Bonoit , cet extrait peut être utile pour harmoniser les niveaux:

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]]))
    }
  }
}

Il imprime également les attributs modifiés. Je n'ai pas trouvé un bon moyen de l'écrire plus élégamment (avec ldply ou quelque chose). Tous les conseils sont appréciés.

user41330
la source
4

Voici un code que j'ai écrit qui répond à la réponse de @ King ci-dessus. Il a corrigé l'erreur:

# 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
la source
salut @ifarb, j'essaie de comprendre votre solution: qu'est-ce que trainingDataSetSMOTEpred et où est-il défini dans le code?
Kasia Kulma du
3

L'ensemble de test et de formation doit être combiné en un seul ensemble, puis modifier les niveaux de l'ensemble de formation. Mes codes sont:

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

Cela fonctionne dans tous les cas où le nombre de niveaux dans le test est plus ou moins que la formation.

Cscode Li
la source
2

J'ai une solution de contournement moche lorsque j'utilise randomForest dans R. Ce n'est probablement pas théoriquement sain, mais cela fait fonctionner la chose.

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

ou l'inverse. Fondamentalement, cela donne juste à R une valeur valide juste qu'il y a 0 cas; alors arrêtez de m'embêter sur l'erreur.

Je ne suis pas assez intelligent pour le coder de sorte qu'il exécute automatiquement l'action pour toutes les fonctionnalités catégorielles. Envoyez-moi le code si vous savez comment ...

Roi
la source
Mais cela ne fonctionne pas si le nombre de niveaux en test est supérieur à la formation. Cela ne fonctionne que si les niveaux des facteurs de données de test sont <= niveaux des facteurs de données d'apprentissage.
KarthikS
1

Je suis sûr que vous auriez déjà pensé à cela si c'était le cas, mais si l'ensemble de test a des valeurs réelles et que vous utilisez l'ensemble de test à des fins de validation croisée, puis divisez à nouveau la trame de données en cadres de données de formation et de test où les deux sont équilibrés sur ces facteurs éviterait votre problème. Cette méthode est connue sous le nom de validation croisée stratifiée .

Goldisfine
la source