Améliorer la classification avec de nombreuses variables catégorielles


37

Je travaille sur un ensemble de données comprenant plus de 200 000 échantillons et environ 50 caractéristiques par échantillon: 10 variables continues et les 40 autres valeurs sont des variables catégorielles (pays, langues, domaines scientifiques, etc.). Pour ces variables catégorielles, vous avez par exemple 150 pays différents, 50 langues, 50 domaines scientifiques etc ...

Jusqu'ici, mon approche est la suivante:

  1. Pour chaque variable catégorielle comportant de nombreuses valeurs possibles, prenons uniquement celle ayant plus de 10 000 échantillons prenant cette valeur. Cela réduit à 5-10 catégories au lieu de 150.

  2. Construisez une variable muette pour chaque catégorie (si 10 pays ajoutez un vecteur binaire de taille 10 pour chaque échantillon).

  3. Nourrir un classifieur de forêt aléatoire (valider les paramètres, etc.) avec ces données.

Actuellement, avec cette approche, je ne parviens qu'à obtenir une précision de 65% et j'estime qu'il est possible de faire plus. En particulier, je ne suis pas satisfait de mon 1) car j'estime que je ne devrais pas supprimer arbitrairement les "valeurs les moins pertinentes" en fonction du nombre d'échantillons dont ils disposent, car ces valeurs moins représentées pourraient être plus discriminantes. D'autre part, ma RAM ne peut pas permettre d'ajouter 500 colonnes * 200 000 lignes aux données en conservant toutes les valeurs possibles.

Auriez-vous une suggestion pour faire face à ces variables beaucoup plus catégoriques?


2
Si vous êtes toujours intéressé, vous pouvez vérifier ma réponse sur la réduction de la dimensionnalité et ma réponse sur la classification hiérarchique .
Aleksandr Blekh le

1
Quand vous dites "construire une variable factice pour chaque catégorie" , cela ressemble à de l’utilisation de Python et non de R? R randomforest peut gérer nativement les catégories, ainsi que la réduction conséquente de la mémoire. Essayez R.
smci

Réponses:


20

1) Les forêts aléatoires doivent être capables de gérer les valeurs catégorielles de manière native. Recherchez donc une implémentation différente afin d'éviter de coder toutes ces fonctionnalités et d'utiliser toute votre mémoire.

2) Le problème avec les caractéristiques catégorielles à haute cardinalité est qu’il est facile de trop les ajuster. Vous avez peut-être suffisamment de données pour que ce ne soit pas un problème, mais faites attention.

3) Je suggère d’examiner la sélection aléatoire des caractéristiques forestières en utilisant soit la méthode proposée par Brieman, soit les contrastes artificiels . La méthode des contrastes artificiels (ACE) est intéressante car elle compare l’importance de la fonction à l’importance d’une version mélangée de celle-ci qui combat certains problèmes de haute cardinalité. Il existe un nouveau document intitulé "Forêts aléatoires guidées par module" qui pourrait être intéressant si vous disposiez de beaucoup plus de fonctionnalités, car il utilise une méthode de sélection de fonctionnalité prenant en compte des groupes de fonctionnalités hautement corrélées.

4) Une autre option utilisée consiste à peaufiner l’algorithme afin qu’il utilise les valises out of bag pour effectuer la sélection finale des caractéristiques après avoir ajusté les divisions dans les valises in bag, ce qui permet parfois de lutter contre les surajustements.

Il y a une implémentation presque complète de l'as ici et j'ai une implémentation plus efficace de mémoire / rapide qui gère les variables catégorielles de manière native ici ... l'option -evaloob supporte l'option 4 Je travaille sur l'ajout de la prise en charge de ACE et de quelques autres basé sur les méthodes de sélection des fonctionnalités mais cela n’a pas encore été fait.


4
Toutes ces suggestions sont intéressantes. Je conviens que la forêt aléatoire devrait gérer des variables catégorielles de manière native, mais scikit-learn ne le fait pas ... Je pense que c'est l'un des principaux défauts de scikit. Je vais essayer votre code sur mes données pour voir ce qui se passe et voir vos autres suggestions!
Bertrand R

1
Essayez l'implémentation de R. La course est un one-line. La lecture des données est extrêmement facile et il existe une nouvelle implémentation parallèle qui est rapide et efficace en mémoire: r-bloggers.com/… D'un autre côté. Vos cours sont-ils déséquilibrés? dans l'implémentation r, vous pouvez développer chaque arbre à partir d'un échantillon bootstrap équilibré, sampsize = c (x, x). Cela a produit de meilleures classifications binaires pour moi. Vous pouvez jouer avec les tailles et modifier très facilement la classification en utilisant les sorties R de la matrice de confusion OOB.
JEquihua

2
L'implémentation randomForest de R autorise les facteurs avec un maximum de 32 niveaux. scikit-learn est moins restrictif, à condition de créer d’abord des variables factices (voir la pandas.get_dummiesfonction). L'implémentation de la forêt aléatoire par H2O a très bien fonctionné pour moi (voir 0xdata.com/docs/master/model/rf ).
Alex Woolford

1
il y a une implémentation plus récente et plus rapide de la forêt aléatoire, le paquet s'appelle ranger. Super truc vraiment. Des ordres de grandeur plus rapides et n’ont pas la limite de 32 niveaux.
Marbel

6

Au lieu de dummifier vos catégories, pourquoi ne pas simplement utiliser une seule variable numérique pour chacune? Dans le contexte des forêts aléatoires, je me suis souvent demandé quelles en seraient les conséquences (car je conviens qu'il semble suspect d'introduire de l'ordinalité dans des données catégorielles avec lesquelles, souvent, cela n'a pas de sens), mais en pratique (du moins avec l’application scikit-learn des RF que j’utilise), j’ai souvent observé que cela n’a aucune incidence sur les résultats (je ne sais pas pourquoi, cependant).


1
Cela convient parfaitement aux entités qualitatives avec n <= 3, car vous pouvez générer les mêmes divisions que vous le feriez en considérant l’entité comme catégorique. Pour n plus grand, il est possible d'obtenir des ensembles de scissions équivalents à la scission par catégorie, mais l'algorithme peut ou non les trouver aussi efficacement ... toutefois, si vous scindez l'entité en n entités numériques, vous réduisez également l'efficacité avec laquelle l'algorithme peut trouver des divisions. Quelqu'un a besoin d'ajouter un support de variable catégorique dans l'implémentation de scikit-learn, sinon c'est génial.
Ryan Bressler

Je suis d'accord avec vous lorsque vous dites qu'il est suspect d'introduire de l'ordinalité dans des données catégoriques ... Je préférerais ne pas avoir à le faire, mais je peux au moins essayer et voir ce qui se passe!
Bertrand R

4
J'ai eu une longue discussion sur cette question sur la liste de diffusion de sklearn (vous pouvez en lire des parties ici: mail-archive.com/scikit-learn-general@lists.sourceforge.net/… ). L’opinion de l’un des responsables de la mise en œuvre était qu’avec des arbres suffisamment profonds, les caractéristiques catégorielles codées en ordinal pourraient fonctionner assez bien (en plus d’être plus efficaces en calcul). Quoi qu'il en soit, si vous l'essayez, je serais très intéressé par vos résultats / conclusions, car c'est un problème que je n'arrête pas de bousculer.
Cjauvin

1
J'ai donc essayé de garder une seule variable numérique pour les variables catégoriques, et cela fonctionne en fait étonnamment bien, et bien mieux que d'ajouter un grand nombre d'entrées binaires ... J'ai également essayé de trier les valeurs en fonction de leur moyenne par rapport à la cible. . Et ça marche bien aussi
Bertrand R

Je ne suis pas étonné par cela en fait… cela correspond à ce que j’ai observé dans plusieurs contextes différents, bien que, à en juger par le nombre de votes positifs, c’est une idée plutôt contre-intuitive.
cjauvin

5

Je pense que vous devriez envisager une / plusieurs technique (s) de réduction variable . Il se débarrasse des prédicteurs moins influents.

J'ai beaucoup lu sur le prétraitement des données et c'est une excellente solution pour réduire le n ° de vos variables.

Mes suggestions sont les suivantes:

  • pour les variables qualitatives , remplacez les valeurs manquantes par la catégorie "manquant". Cela peut introduire un biais si les données ne manquent pas au hasard, mais au moins, vous aurez toutes vos observations intactes et le manque pourrait révéler un comportement différent.
  • élimine les prédicteurs de variance zéro ou les prédicteurs de variance proches de zéro (veillez à ne pas éliminer les variables muettes avec des catégories non équilibrées élevées qui peuvent séparer efficacement votre Y. Faites des graphiques pour les variables que vous pensez être importantes). En R, vous pouvez utiliser la 'nzv'fonction du 'caret'package. Cela réduira fortement votre dimension de données.
  • éliminer les prédicteurs corrélés . Utilisez la matrice de corrélation de Kendall car il est plus approprié de la construire en présence de variables catégorielles. L'inconvénient est que vous devez transformer tous vos vars nominaux en catégoriques.
  • il existe des méthodes de sélection de caractéristiques qui réduiront encore leur nombre (clustering - vous choisissez un seul représentant de chaque cluster, la régression LASSO, etc.). Je n'ai pas encore eu la chance de les tester car les autres étapes ont réduit mes variables à moins de 100.

Aussi, je suggérerais d'utiliser l' algorithme AdaBoost au lieu de RF. Personnellement, les recherches que j'ai effectuées m'ont donné des coefficients de Gini très similaires pour ces deux méthodes. La bonne partie de AdaBoost est que, dans R, il gère les observations manquantes. Donc, vous pouvez sauter la 1ère étape de cette liste

J'espère que ça a aidé un peu. Bonne chance


4

Vous voudrez peut-être envisager des modèles à effets mixtes. Ils sont populaires en sciences sociales en raison de leurs performances sur les données catégorielles à haute cardinalité, et je les ai utilisés pour créer de grands modèles prédictifs surpassant les approches classiques d’apprentissage automatique telles que les arbres à gradient accéléré, les forêts aléatoires et la régression logistique régularisée sur réseau élastique. L'implémentation la plus connue est le paquetage lme4 de R; la fonction que vous utiliseriez pour la classification est glmer, qui implémente la régression logistique à effets mixtes. Vous pouvez avoir des problèmes avec la mise à l'échelle de votre jeu de données, mais j'ai réalisé 80 000 lignes avec 15 entités sans trop de difficulté.


2
  1. Quand vous dites "construire une variable factice pour chaque catégorie" , cela ressemble à de l’utilisation de Python et non de R? R randomforest peut gérer nativement les catégories, ainsi que la réduction conséquente de la mémoire. Essayez R.

  2. Ensuite, vous n’avez pas besoin de supprimer / fusionner manuellement les niveaux de catégories, cela ressemble à une douleur majeure. Et même si vous le faisiez, vous n'êtes pas assuré que les catégories les plus peuplées sont les plus prévisibles. Contrôler la complexité de la forêt aléatoire avec le paramètre forêt aléatoire avec la taille de nœud de: commencez par une grande taille de nœud et réduisez-la progressivement (il s'agit de la recherche par hyperparamètre).

  3. La sélection des variables sera utile. @lorelai donne de bonnes recommandations. Essayez d'éliminer les fonctionnalités inutiles (de faible importance ou hautement corrélées). La construction des arbres est quadratique par rapport au nombre de fonctionnalités, donc si vous en éliminez une troisième, cela vous rapportera des dividendes.


0

Vous devriez regarder le paquet H2O.ai. Il gère les variables catégoriques prêtes à l'emploi sans avoir à coder (assurez-vous que les variables sont des facteurs).

J'aime particulièrement leur implémentation de Gradient Boosted Machine (GBM), car vous pouvez ensuite examiner l'importance variable après la construction du modèle. Les GBM ont également la particularité d'être résistants à la suralimentation.

Si vous voulez explorer d'autres modèles, ils ont: GLM, Random Forest, Naive Bayes, Deep Learning, etc.

Voir: http://docs.h2o.ai/h2o/latest-stable/h2o-docs/data-science/gbm.html

Il est également facile à installer (Windows, Linux, Mac) et à exécuter avec des API utilisant R, Python, Java et Scala.

Il peut utiliser plusieurs cœurs pour accélérer les choses.

Dans un proche avenir, ils prendront en charge les GPU.

Il est également open source et gratuit (il existe un support Enterprise).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.