les chaînes en tant qu'entités dans l'arbre de décision / la forêt aléatoire

64

Je fais quelques problèmes sur une application d'arbre de décision / forêt aléatoire. J'essaie d'adapter un problème comportant à la fois des chiffres et des chaînes (telles que le nom du pays). Maintenant, dans la bibliothèque, scikit-learn prend uniquement des nombres en tant que paramètres, mais je souhaite injecter les chaînes, car elles contiennent une quantité importante de connaissances.

Comment gérer un tel scénario?

Je peux convertir une chaîne en nombres par un mécanisme tel que le hachage en Python. Mais j'aimerais connaître la meilleure pratique pour traiter les chaînes dans les problèmes d'arbre de décision.

utilisateur3001408
la source
Dans le cas de sckitlearn, nous avons constaté que nous devions coder les variables catégoriques. Sinon, la méthode fit jetterait une erreur en disant ValueError: impossible de convertir une chaîne en float
Kar

Réponses:

56

Dans la plupart des systèmes d’apprentissage automatique bien établis, les variables catégorielles sont gérées naturellement. Par exemple, dans R, vous utiliseriez des facteurs, dans WEKA, vous utiliseriez des variables nominales. Ce n'est pas le cas dans scikit-learn. Les arbres de décision implémentés dans scikit-learn utilisent uniquement des fonctionnalités numériques et ces fonctionnalités sont toujours interprétées comme des variables numériques continues .

Par conséquent, il convient d'éviter de remplacer les chaînes par un code de hachage, car tout codage que vous utiliserez sera considéré comme une fonction numérique continue et induira une commande qui n'existe tout simplement pas dans vos données.

Un exemple est de coder ['rouge', 'vert', 'bleu'] avec [1,2,3], cela produirait des choses étranges comme 'rouge' est inférieur à 'bleu', et si vous faites la moyenne, 'rouge' et un «bleu», vous obtiendrez un «vert». Un autre exemple plus subtil pourrait se produire lorsque vous codez ['bas', 'moyen', 'haut'] avec [1,2,3]. Dans ce dernier cas, il peut arriver que l'ordre soit logique, mais certaines incohérences subtiles peuvent survenir lorsque «moyen» n'est pas au milieu de «faible» et «élevé».

Enfin, la réponse à votre question réside dans le codage de la fonctionnalité catégorielle en plusieurs fonctionnalités binaires . Par exemple, vous pouvez coder ['rouge', 'vert', 'bleu'] avec 3 colonnes, une pour chaque catégorie, ayant 1 lorsque la catégorie correspond et 0 sinon. C'est ce qu'on appelle un codage à chaud , un codage binaire, un codage one-of-k ou autre. Vous pouvez consulter la documentation ici pour le codage des caractéristiques catégorielles et de l' extraction de fonctionnalités - hachage et dessins . Évidemment, un codage à chaud augmentera vos besoins en espace et, parfois, votre performance en souffrira.

Rapaio
la source
2
C'est l'implémentation de scikit qui ne gère pas correctement les variables catégorielles. Recoder comme le suggère cette réponse est probablement le mieux que vous puissiez faire. Un utilisateur plus sérieux pourrait rechercher un autre paquet.
SmallChess
3
On peut utiliser sklearn.preprocessing.LabelBinarizer pour un encodage à chaud de la variable catégorielle.
GuSuku
@rapaio Je pense que le codage binaire n'est pas le même codage à chaud. Le codage binaire est lorsque vous représentez 8 catégories avec 3 colonnes, ou entre 9 et 16 catégories avec 4 colonnes et ainsi de suite. Ai-je tort?
Alok Nayak
le paquet patsy python traitera avec l'encodage à une minute des variables catégorielles. patsy.readthedocs.io/en/latest/quickstart.html
zhespelt
5
N'utilisez pas LabelBinarizer, utilisez sklearn.preprocessing.OneHotEncoder . Si vous utilisez des pandas pour importer et prétraiter vos données, vous pouvez également le faire directement en utilisant pandas.get_dummies . Il est nul que scikit-learn ne supporte pas les variables catégorielles.
Ricardo Cruz
11

Vous devez coder vos chaînes sous forme de fonctions numériques que sci-kit peut utiliser pour les algorithmes ML. Cette fonctionnalité est gérée dans le module de prétraitement (par exemple, voir sklearn.preprocessing.LabelEncoder pour un exemple).

Kyle
la source
4
rapaio explique dans sa réponse pourquoi cela donnerait un résultat incorrect
Keith
7

En règle générale, vous devez encoder des variables catégoriques one-hot pour les modèles scikit-learn, notamment la forêt aléatoire. Une forêt aléatoire fonctionnera souvent correctement sans codage one-hot mais fonctionnera généralement mieux si vous effectuez un codage one-hot. Un codage à chaud et des variables "factices" signifient la même chose dans ce contexte. Scikit-learn a sklearn.preprocessing.OneHotEncoder et Pandas a pandas.get_dummies pour accomplir cela.

Cependant, il existe des alternatives. L'article "Beyond One-Hot" de KDnuggets explique très bien pourquoi vous devez coder des variables catégorielles et des alternatives au codage one-hot.

Il existe des variantes d'implémentation de la forêt aléatoire ne nécessitant pas de codage à une étape telle que R ou H2O. L'implémentation dans R est coûteuse en calcul et ne fonctionnera pas si vos entités ont plusieurs catégories . H2O travaillera avec un grand nombre de catégories. Continuum a mis H2O à disposition dans Anaconda Python.

Des efforts sont en cours pour que scikit-learn gère directement les fonctionnalités catégorielles .

Cet article a une explication de l'algorithme utilisé dans H2O. Il fait référence au document académique A Algorithme de décision parallèle en continu et à une version plus longue du même document.

Denson
la source
5

Mise à jour 2018!

Vous pouvez créer un espace d'intégration (vecteur dense) pour vos variables catégorielles. Beaucoup d'entre vous connaissent Word2vec et fastext, qui intègrent des mots dans un espace vectoriel dense et significatif. Même idée ici - vos variables catégorielles mapperont sur un vecteur ayant une signification.

Du papier Guo / Berkhahn :

L’incorporation d’entités réduit non seulement l’utilisation de la mémoire et accélère les réseaux de neurones par rapport au codage simple, mais elle permet surtout de mapper des valeurs similaires les unes aux autres dans l’espace d’incorporation, ce qui révèle les propriétés intrinsèques des variables catégorielles. Nous l’avons appliquée avec succès lors d’une récente compétition Kaggle et avons réussi à atteindre la troisième position grâce à des fonctionnalités relativement simples.

Les auteurs ont constaté que la représentation des variables catégorielles de cette manière améliorait l'efficacité de tous les algorithmes d'apprentissage automatique testés, y compris la forêt aléatoire.

Le meilleur exemple pourrait être l'application de la technique par Pinterest pour regrouper les épingles associées:

entrez la description de l'image ici

Les employés de fastai ont mis en place des embeddings catégoriques et créé un très bon article de blog avec un cahier de démonstration pour compagnon .

Détails supplémentaires et explications

Un réseau de neurones est utilisé pour créer les intégrations, c'est-à-dire pour assigner un vecteur à chaque valeur catégorique. Une fois que vous avez les vecteurs, vous pouvez les utiliser dans n’importe quel modèle acceptant des valeurs numériques. Chaque composante du vecteur devient une variable d'entrée. Par exemple, si vous utilisez des vecteurs 3-D pour incorporer votre liste de couleurs catégorique, vous pouvez obtenir quelque chose comme: rouge = (0, 1,5, -2,3), bleu = (1, 1, 0), etc. Vous utiliseriez trois variables d'entrée dans votre forêt aléatoire correspondant aux trois composants. Pour les choses rouges, c1 = 0, c2 = 1,5 et c3 = -2,3. Pour les choses bleues, c1 = 1, c2 = 1 et c3 = 0.

Vous n'avez pas réellement besoin d'utiliser un réseau de neurones pour créer des intégrations (bien que je ne recommande pas de fuir la technique). Vous êtes libre de créer vos propres embaumements à la main ou par d'autres moyens, lorsque cela est possible. Quelques exemples:

  1. Mappe les couleurs en vecteurs RVB.
  2. Emplacements des cartes en vecteurs lat / long.
  3. Dans un modèle politique américain, mappez les villes sur certaines composantes vectorielles représentant l'alignement gauche / droite, le fardeau fiscal, etc.
Pete
la source
OK cool mais à moins que je n’ai manqué quelque chose, c’est pour les filets du début à la fin. Comment créer une intégration puis la transmettre dans une Forrest? Je suppose que vous devez former tout un réseau avec toutes les fonctionnalités, puis prendre les premières couches et les utiliser comme fonctionnalité d’entrée pour votre Forrest. Ce n'est pas clair comment cela serait fait.
Keith
@Keith Un réseau de neurones est utilisé pour créer les incorporations, c’est-à-dire assigner un vecteur à chaque valeur catégorique. Une fois que vous avez les vecteurs, vous pouvez les utiliser dans n’importe quel modèle acceptant des valeurs numériques. Chaque composante du vecteur devient une variable d'entrée. Par exemple, si vous utilisez des vecteurs 3-D pour incorporer votre liste de couleurs catégorique, vous pouvez obtenir quelque chose du type: rouge = (0, 1.5, -2.3), bleu = (1, 1, 0)etc. Vous utiliseriez trois variables d'entrée dans votre forêt aléatoire correspondant aux trois composants. Pour les choses rouges, c1 = 0, c2 = 1,5 et c3 = -2,3. Pour les choses bleues, c1 = 1, c2 = 1 et c3 = 0.
Pete
Je comprends tout à fait le concept car c'est assez simple. Je veux dire comment cela se ferait dans la mise en œuvre? Le cahier de démonstration fast.ai que vous liez contient un peu un RandomForestRegressor à la fin, mais je ne vois pas vraiment comment cela s’ajoute aux embeddings.
Keith
Je pense que cela peut être un bon exemple de code dans Keras github.com/entron/entity-embedding-rossmann
Keith
3

Vous pouvez utiliser des variables nominales dans de tels scénarios. Avec les pandas, panda.get_dummiesvous pouvez créer des variables factices pour les chaînes que vous souhaitez placer dans l'arbre de décision ou la forêt aléatoire.

Exemple:

import pandas as pd
d = {'one' : pd.Series([1., 2., 3.,4.], index=['a', 'b', 'c','d']),'two' :pd.Series(['Paul', 'John', 'Micheal','George'], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

df_with_dummies= pd.get_dummies(df,columns=["two"],drop_first=False)
df_with_dummies
ozn
la source
2

Transformez-les en chiffres, par exemple pour chaque pays unique en attribuant un numéro unique (comme 1,2,3 et ...)

De plus, vous n’avez pas besoin d’utiliser One-Hot Encoding (variables fictives) lorsque vous travaillez avec une forêt aléatoire, car les arbres ne fonctionnent pas comme un autre algorithme (comme la régression linéaire / logistique) et ils ne fonctionnent pas par travailler à trouver une bonne répartition pour vos fonctions) si INUTILE pour un Hot-Encoding

Arash Jamshidi
la source
1
Cela dépend en fait de l'algorithme particulier qui entraîne l'arbre. En particulier, scikit NE prend PAS en charge les variables catégorielles.
Chuse