2016-06-29 33 views
15

Ci sono diversi post su come codificare i dati categorici agli alberi Sklearn decission, ma dalla documentazione Sklearn, abbiamo ottenuto questiPassando dati categorici per Sklearn Albero decisionale

Some advantages of decision trees are:

(...)

Able to handle both numerical and categorical data. Other techniques are usually specialised in analysing datasets that have only one type of variable. See algorithms for more information.

Ma eseguendo lo script seguente

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

emette il seguente errore:

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 

So che in R è possibile passare dati categoriali, con Sklearn, è possibile?

risposta

4

Contrariamente alla risposta accettata, io preferirei usare gli strumenti forniti da scikit-learn per questo scopo. Il motivo principale per farlo è che possono essere facilmente integrati in un Pipeline.

Scikit-Learn fornisce in sé ottime classi per gestire i dati categoriali. Invece di scrivere la tua funzione personalizzata, dovresti usare LabelEncoder che è appositamente progettato per questo scopo.

fare riferimento al seguente codice dalla documentazione:

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

Questo li codifica automaticamente in numeri per le vostre algoritmi di apprendimento automatico. Ora questo supporta anche il ritorno alle stringhe da numeri interi. Si può fare questo semplicemente chiamando inverse_transform come segue:

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

Questo sarebbe tornato ['tokyo', 'tokyo', 'paris'].

Si noti inoltre che per molti altri classificatori, a parte gli alberi decisionali, come la regressione logistica o SVM, si desidera codificare le variabili categoriali utilizzando One-Hot encoding. Scikit-learn supporta anche questo attraverso la classe OneHotEncoder.

Spero che questo aiuti!

+31

-1 questo è fuorviante. Allo stato attuale, gli alberi decisionali sklearn non gestiscono dati categoriali - [vedi n. 5442] (https://github.com/scikit-learn/scikit-learn/issues/5442). Questo approccio all'utilizzo di Label Encoding converte in numeri interi che 'DecisionClassifier()' ** considererà come numerico **. Se i tuoi dati categoriali non sono ordinali, questo non va bene - finirai con divisioni che non hanno senso. L'uso di un 'OneHotEncoder' è l'unico modo valido corrente, ma è dispendioso dal punto di vista computazionale. – kungfujam

+0

@Abhinav, è possibile applicare 'LabelEncoder' su più di una colonna di un dataframe in una volta?Ad esempio, nel dataframe della domanda, possiamo fare qualcosa come "le.fit_transform (data [['A', 'B', 'C']])' per ottenere etichette per tutte le colonne categoriali in una sola volta? O dovrebbe essere specificare le colonne categoriali in modo esplicito per convertire solo le colonne categoriali. – Minu

+0

@kungfujam, Inoltre, mi piacerebbe 'One-Hot Encode' le colonne categoriali una volta che' LabelEncode' loro - per affrontare il problema che @kungfujam ha sottolineato. Come posso farlo una volta ottenuta la codifica dell'etichetta? – Minu

1

Gli alberi di decisione di scansioni non gestiscono la conversione di stringhe categoriali in numeri. Vi suggerisco di trovare una funzione in Sklearn (forse this), che lo fa o manualmente scrivere del codice come:

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

Sì, quel wat di solito lo fa, ma per la stampa non è veramente buono. – 0xhfff

+0

Se si desidera passare dal numero intero alla rappresentazione di stringa, creare un dizionario che contenga il mapping tra stringa e intero e utilizzarlo per "decodificare" la rappresentazione intera. – mrwyatt

+0

L'affermazione è imprecisa. I classificatori di apprendimento di Scikit non gestiscono implicitamente la codifica delle etichette. Tuttavia, Scikit-learn fornisce un sacco di classi per gestire questo. Consiglierei di usare gli strumenti di apprendimento di scikit perché possono anche essere adatti a una pipeline di apprendimento automatico con il minimo sforzo. –