RandomForest de R ne peut pas gérer plus de 32 niveaux. Quelle est la solution de contournement?

22

Le package randomForest de R ne peut pas gérer le facteur avec plus de 32 niveaux. Lorsqu'il reçoit plus de 32 niveaux, il émet un message d'erreur:

Ne peut pas gérer les prédicteurs catégoriels avec plus de 32 catégories.

Mais les données dont je dispose ont plusieurs facteurs. Certains d'entre eux ont plus de 1000 niveaux et certains ont 100+. Il a même un «état» des États-Unis qui est de 52.

Alors, voici ma question.

  1. Pourquoi y a-t-il une telle limitation? randomForest refuse d'exécuter même pour le cas simple.

    > d <- data.frame(x=factor(1:50), y=1:50)
    > randomForest(y ~ x, data=d)
      Error in randomForest.default(m, y, ...) : 
      Can not handle categorical predictors with more than 32 categories.

    Si cela est simplement dû à une limitation de la mémoire, comment le programme randomForeestRegressor de scikit learn peut-il fonctionner avec plus de 32 niveaux?

  2. Quelle est la meilleure façon de gérer ce problème? Supposons que j'ai X1, X2, ..., X50 variables indépendantes et Y est variable dépendante. Et supposons que X1, X2 et X3 aient plus de 32 niveaux. Que devrais-je faire?

    Ce à quoi je pense, c'est d'exécuter un algorithme de clustering pour chacun des X1, X2 et X3 où la distance est définie comme la différence en Y. Je vais exécuter trois groupements car il y a trois variables problématiques. Et dans chaque clustering, j'aimerais pouvoir trouver des niveaux similaires. Et je vais les fusionner.

    Comment ça sonne?

Minkoo Seo
la source
La recherche sur le Web avec le nom du package et le message d'erreur fournit des réponses.
Roland
5
@Roland En fait ça m'a conduit ici…
isomorphismes
1
vous pourriez essayer la science des données car plusieurs esprits statistiques ont de l'expérience dans la programmation de données à plusieurs dimensions.
aeroNotAuto
2
MISE À JOUR: Depuis la version 4.6-9, randomForestpeut gérer des prédicteurs catégoriques avec jusqu'à 53 niveaux. Actualités
Ben
Comment la forêt aléatoire de R détermine-t-elle le nombre de niveaux? Je suppose que le niveau signifie les catégories.
ajp

Réponses:

25

C'est en fait une contrainte assez raisonnable car une division sur un facteur avec niveaux est en fait une sélection de l'une des 2 N - 2 combinaisons possibles. Donc, même avec N comme 25, l'espace des combinaisons est si énorme qu'une telle inférence n'a qu'un sens mineur.N2N2N

N

L'autre option est de changer la représentation - peut-être que votre résultat ne dépend pas directement de l'entité étatique mais, par exemple, la superficie, la population, le nombre de pins par habitant ou d'autres attributs que vous pouvez connecter à votre système d'information à la place.

Il se peut également que chaque État soit une entité si isolée et non corrélée qu'il nécessite un modèle distinct pour lui-même.

Le regroupement basé sur une décision est probablement une mauvaise idée car de cette façon, vous transférez des informations de la décision en attributs, ce qui se termine souvent par un sur-ajustement.


la source
4
Il peut être facilement déplacé, mais d'une manière légèrement fastidieuse. Par exemple, si vous avez entre 33 et 1024 niveaux, créez deux facteurs chacun de <= 32 niveaux.
KalEl
15

La raison principale est la façon dont randomForest est implémenté. La mise en œuvre de R découle beaucoup des spécifications d'origine de Breiman. Ce qui est important ici à noter est que pour les variables factorielles / catégorielles, les critères de division sont binaires avec quelques valeurs d'étiquette à gauche et les valeurs d'étiquette restantes à droite.

01[0;2M1]

Pourquoi les implémentations de Weka et Python fonctionnent?

L'implémentation weka n'utilise pas d'arbres CART par défaut. Il utilise des arbres C45 qui n'ont pas ce problème de calcul, car pour les entrées catégorielles, il se divise en plusieurs nœuds, un pour chaque valeur de niveau.

L'implémentation de forêt aléatoire python ne peut pas utiliser de variables catégorielles / factorielles. Vous devez coder ces variables en variables fictives ou numériques.

M

rapaio
la source
2
Merci beaucoup! Est-ce qu'il découle de votre réponse que l'implémentation de R pour le traitement des valeurs catégorielles est supérieure à celle de Python (je me souviens que Max Kuhn a mentionné que le regroupement des variables catégorielles pour RF fournit des résultats légèrement meilleurs que de les simuler), ou tout au moins exécuter Random Forest dans R vs Python J'ai de très bonnes chances d'obtenir des résultats différents (précision etc ...)? D'après votre expérience, lors de la modélisation, est-il judicieux d'essayer à la fois de regrouper des variables (dans R) et de les facturer puis de comparer deux approches?
Sergey Bushmanov
2
L'encodage factice fonctionne mais il ne peut produire qu'une seule catégorie par rapport à tous. Après le codage, les variables sont testées une fois à la fois. Il est donc impossible d'implémenter le double. Si cette fonctionnalité peut aider, je pense qu'il n'y a pratiquement pas de grandes différences. Cependant, il y a d'autres choses qui pourraient nécessiter une attention particulière lorsque vous travaillez avec une importance variable: certaines implémentations sont biaisées vers des catégories à plusieurs niveaux. Voir les articles de Carolin Strobl pour plus de détails: statistik.uni-dortmund.de/useR-2008/slides/Strobl+Zeileis.pdf . Dans R, certaines implémentations ne présentent pas ce biais.
rapaio
2

Vous pouvez essayer de représenter cette colonne différemment. Vous pouvez représenter les mêmes données qu'une trame de données clairsemée.

Code viable minimum;

example <- as.data.frame(c("A", "A", "B", "F", "C", "G", "C", "D", "E", "F"))
names(example) <- "strcol"

for(level in unique(example$strcol)){
      example[paste("dummy", level, sep = "_")] <- ifelse(example$strcol == level,     1, 0)
}

Remarquez comment chaque valeur de la colonne d'origine devient maintenant une colonne factice distincte.

Exemple de code plus étendu;

set.seed(0)
combs1 = sample.int(33, size= 10000, replace=TRUE)
combs2 = sample.int(33, size= 10000, replace=TRUE)
combs3 = combs1 * combs2 + rnorm(10000,mean=0,100)
df_hard = data.frame(y=combs3, first=factor(combs1), second=factor(combs2))

for(level in unique(df_hard$first)){
    df_hard[paste("first", level, sep = "_")] <- ifelse(df_hard$first == level, 1, 0)
}

for(level in unique(df_hard$second)){
    df_hard[paste("second", level, sep = "_")] <- ifelse(df_hard$second == level, 1, 0)
}

example$first <- NULL
example$second <- NULL

rf_mod = randomForest( y ~ ., data=example )

Même si ce morceau de code montre que vous n'obtiendrez en effet plus l'erreur, vous remarquerez que l'algorithme randomForest a maintenant besoin de beaucoup de temps avant de se terminer. Cela est dû à une contrainte CPU, vous pouvez également réduire cette tâche via l'échantillonnage.

Pour plus d'informations, consultez ce blog:

https://blog.cloudera.com/blog/2013/02/how-to-resample-from-a-large-data-set-in-parallel-with-r-on-hadoop/

Vincent Warmerdam
la source
Le deuxième bloc de code semble déroutant. Bien que vous utilisiez df_hard dans tout le corps, aux dernières lignes, vous définissez "premier" et "deuxième" sur NULL, et utilisez également "exemple" comme données pour randomForest, cela n'a pas de sens pour moi, car il n'y a aucun lien entre l'exemple et df_hard.
Özgür
Vincent, ne pensez-vous pas que je vais me retrouver avec de si gros ennuis si j'ai des niveaux de l'ordre de 100+, suggérez-vous d'ajouter chaque colonne en entrée au hasard?
Hardik Gupta
Une autre alternative consiste à utiliser l'implémentation randomforest dans h2o; cela prend mieux en charge les grands ensembles de données. Je ne comprends pas le bit "ajouter chaque colonne comme entrée à aléatoire".
Vincent Warmerdam
0

Vous pouvez utiliser le package extraTrees à la place. L'algorithme des forêts extrêmement randomisées n'essaye pas de point d'arrêt / division, mais seulement un sous-ensemble aléatoire limité de divisions.

Soren Havelund Welling
la source
1
extraTrees a des limites, dans le sens où votre entrée doit être une matrice de données numériques, n'est-ce pas?
Hardik Gupta
0

Autre option: selon le nombre de niveaux et le nombre d'observations dans vos données, vous pouvez fusionner certains niveaux. Au-delà du dépassement de la limite, cela peut réduire la variance si vous avez plusieurs niveaux avec seulement quelques observations. Hadley « s Forcats: fct_lump fait cela.

Scott Kaiser
la source