web-dev-qa-db-fra.com

Passer des données catégoriques à un arbre de décision Sklearn

Plusieurs articles expliquent comment coder des données catégoriques dans les arbres de Sklearn Decission, mais la documentation de Sklearn nous en fournit

Certains avantages des arbres de décision sont:

(...)

Capable de traiter à la fois des données numériques et catégoriques. D'autres techniques sont généralement spécialisées dans l'analyse de jeux de données ne comportant qu'un seul type de variable. Voir algorithmes pour plus d'informations.

Mais exécuter le script suivant

import pandas as pd
from sklearn.tree import DecisionTreeClassifier

data = pd.DataFrame()
data['A'] = ['a','a','b','a']
data['B'] = ['b','b','a','b']
data['C'] = [0, 0, 1, 0]
data['Class'] = ['n','n','y','n']

tree = DecisionTreeClassifier()
tree.fit(data[['A','B','C']], data['Class'])

renvoie l'erreur suivante:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/sklearn/tree/tree.py", line 154, in fit
    X = check_array(X, dtype=DTYPE, accept_sparse="csc")
  File "/usr/local/lib/python2.7/site-packages/sklearn/utils/validation.py", line 377, in check_array
    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: could not convert string to float: b

Je sais qu’en R il est possible de transmettre des données catégoriques, avec Sklearn, est-ce possible?

48
0xhfff

Contrairement à la réponse acceptée, je préférerais utiliser les outils fournis par Scikit-Learn à cette fin. La raison principale en est qu’ils peuvent être facilement intégrés dans un Pipeline .

Scikit-Learn lui-même fournit de très bonnes classes pour gérer des données catégorielles. Au lieu d'écrire votre fonction personnalisée, vous devriez utiliser LabelEncoder qui est spécialement conçu à cet effet .

Reportez-vous au code suivant de la documentation:

from sklearn import preprocessing
le = preprocessing.LabelEncoder()
le.fit(["paris", "paris", "tokyo", "amsterdam"])
le.transform(["tokyo", "tokyo", "paris"]) 

Cela les code automatiquement en nombres pour vos algorithmes d’apprentissage automatique. Maintenant, cela permet également de retourner aux chaînes à partir d'entiers. Vous pouvez le faire en appelant simplement inverse_transform comme suit:

list(le.inverse_transform([2, 2, 1]))

Cela retournerait ['tokyo', 'tokyo', 'paris'].

Notez également que pour de nombreux autres classificateurs, mis à part les arbres de décision, tels que la régression logistique ou SVM, vous souhaitez coder vos variables catégorielles à l'aide de codage One-Hot . Scikit-learn prend également en charge cela via la classe OneHotEncoder .

J'espère que cela t'aides!

6
Abhinav Arora

(Ceci est juste un reformat de mon commentaire ci-dessus à partir de 2016 ... cela reste vrai.)

La réponse acceptée pour cette question est trompeuse.

Dans l'état actuel des choses, les arbres de décision à utiliser ne traitent pas les données catégoriques - cf. numéro 5442 .

L'approche recommandée consistant à utiliser le codage d'étiquettes convertit en entiers que la DecisionTreeClassifier() traitera comme numérique . Si vos données catégorielles ne sont pas ordinales, ce n'est pas bon - vous allez vous retrouver avec des fractionnements qui n'ont pas de sens.

L'utilisation de OneHotEncoder est la seule méthode valide en vigueur, permettant des scissions arbitraires ne dépendant pas de l'ordre des étiquettes mais coûtant cher en calculs.

9
James Owers

(..)

Capable de traiter à la fois des données numériques et catégoriques.

Cela signifie seulement que vous pouvez utiliser

  • la classe DecisionTreeClassifier pour les problèmes de classification
  • la classe DecisionTreeRegressor pour la régression.

Dans tous les cas, vous devez encoder à chaud les variables catégoriques avant d'adapter une arborescence à sklearn, comme ceci:

import pandas as pd
from sklearn.tree import DecisionTreeClassifier

data = pd.DataFrame()
data['A'] = ['a','a','b','a']
data['B'] = ['b','b','a','b']
data['C'] = [0, 0, 1, 0]
data['Class'] = ['n','n','y','n']

tree = DecisionTreeClassifier()

one_hot_data = pd.get_dummies(data[['A','B','C']],drop_first=True)
tree.fit(one_hot_data, data['Class'])
7
Guillaume

Les arbres de décision Sklearn ne gèrent pas la conversion de chaînes catégorielles en nombres. Je vous suggère de trouver une fonction dans Sklearn (peut-être this ) qui le fait ou d'écrire manuellement du code comme:

def cat2int(column):
    vals = list(set(column))
    for i, string in enumerate(column):
        column[i] = vals.index(string)
    return column
3
mrwyatt