python - tfidftransformer - Usar DictVectorizer con sklearn DecisionTreeClassifier
tfidfvectorizer (2)
vec.fit_transform
devuelve una matriz dispersa. Y IIRC DecisionTreeClassifier
no funciona bien con eso.
Pruebe train_fea = train_fea.toarray()
antes de pasarlo a DecisionTreeClassifier
.
Intento comenzar un árbol de decisión con python y sklearn. El enfoque de trabajo fue así:
import pandas as pd
from sklearn import tree
for col in set(train.columns):
if train[col].dtype == np.dtype(''object''):
s = np.unique(train[col].values)
mapping = pd.Series([x[0] for x in enumerate(s)], index = s)
train_fea = train_fea.join(train[col].map(mapping))
else:
train_fea = train_fea.join(train[col])
dt = tree.DecisionTreeClassifier(min_samples_split=3,
compute_importances=True,max_depth=5)
dt.fit(train_fea, labels)
Ahora trato de hacer lo mismo con DictVectorizer, pero mi código no funciona:
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer(sparse=False)
train_fea = vec.fit_transform([dict(enumerate(sample)) for sample in train])
dt = tree.DecisionTreeClassifier(min_samples_split=3,
compute_importances=True,max_depth=5)
dt.fit(train_fea, labels)
Tengo un error en la última línea: "ValueError: número de etiquetas = 332448 no coincide con el número de muestras = 55". Como aprendí de la documentación, DictVectorize fue diseñado para transformar las características nominales en numéricas. ¿Qué hago mal?
corregido (gracias ogrisel por empujarme a hacer un ejemplo completo):
import pandas as pd
import numpy as np
from sklearn import tree
##################################
# working example
train = pd.DataFrame({''a'' : [''a'', ''b'', ''a''], ''d'' : [''e'', ''e'', ''f''],
''b'' : [0, 1, 1], ''c'' : [''b'', ''c'', ''b'']})
columns = set(train.columns)
columns.remove(''b'')
train_fea = train[[''b'']]
for col in columns:
if train[col].dtype == np.dtype(''object''):
s = np.unique(train[col].values)
mapping = pd.Series([x[0] for x in enumerate(s)], index = s)
train_fea = train_fea.join(train[col].map(mapping))
else:
train_fea = train_fea.join(train[col])
dt = tree.DecisionTreeClassifier(min_samples_split=3,
compute_importances=True,max_depth=5)
dt.fit(train_fea, train[''c''])
##########################################
# example with DictVectorizer and error
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer(sparse=False)
train_fea = vec.fit_transform([dict(enumerate(sample)) for sample in train])
dt = tree.DecisionTreeClassifier(min_samples_split=3,
compute_importances=True,max_depth=5)
dt.fit(train_fea, train[''c''])
El último código fue arreglado con la ayuda de ogrisel:
import pandas as pd
from sklearn import tree
from sklearn.feature_extraction import DictVectorizer
from sklearn import preprocessing
train = pd.DataFrame({''a'' : [''a'', ''b'', ''a''], ''d'' : [''e'', ''x'', ''f''],
''b'' : [0, 1, 1], ''c'' : [''b'', ''c'', ''b'']})
# encode labels
labels = train[[''c'']]
le = preprocessing.LabelEncoder()
labels_fea = le.fit_transform(labels)
# vectorize training data
del train[''c'']
train_as_dicts = [dict(r.iteritems()) for _, r in train.iterrows()]
train_fea = DictVectorizer(sparse=False).fit_transform(train_as_dicts)
# use decision tree
dt = tree.DecisionTreeClassifier()
dt.fit(train_fea, labels_fea)
# transform result
predictions = le.inverse_transform(dt.predict(train_fea).astype(''I''))
predictions_as_dataframe = train.join(pd.DataFrame({"Prediction": predictions}))
print predictions_as_dataframe
Todo funciona
La forma en que enumeras tus muestras no es significativa. Simplemente imprímalos para que sean obvios:
>>> import pandas as pd
>>> train = pd.DataFrame({''a'' : [''a'', ''b'', ''a''], ''d'' : [''e'', ''e'', ''f''],
... ''b'' : [0, 1, 1], ''c'' : [''b'', ''c'', ''b'']})
>>> samples = [dict(enumerate(sample)) for sample in train]
>>> samples
[{0: ''a''}, {0: ''b''}, {0: ''c''}, {0: ''d''}]
Ahora bien, esta es, sintácticamente, una lista de dictados, pero nada de lo que cabría esperar. Intenta hacer esto en su lugar:
>>> train_as_dicts = [dict(r.iteritems()) for _, r in train.iterrows()]
>>> train_as_dicts
[{''a'': ''a'', ''c'': ''b'', ''b'': 0, ''d'': ''e''},
{''a'': ''b'', ''c'': ''c'', ''b'': 1, ''d'': ''e''},
{''a'': ''a'', ''c'': ''b'', ''b'': 1, ''d'': ''f''}]
Esto se ve mucho mejor, intentemos vectorizar esos dicts:
>>> from sklearn.feature_extraction import DictVectorizer
>>> vectorizer = DictVectorizer()
>>> vectorized_sparse = vectorizer.fit_transform(train_as_dicts)
>>> vectorized_sparse
<3x7 sparse matrix of type ''<type ''numpy.float64''>''
with 12 stored elements in Compressed Sparse Row format>
>>> vectorized_array = vectorized_sparse.toarray()
>>> vectorized_array
array([[ 1., 0., 0., 1., 0., 1., 0.],
[ 0., 1., 1., 0., 1., 1., 0.],
[ 1., 0., 1., 1., 0., 0., 1.]])
Para obtener el significado de cada columna, pregúntale al vectorizador:
>>> vectorizer.get_feature_names()
[''a=a'', ''a=b'', ''b'', ''c=b'', ''c=c'', ''d=e'', ''d=f'']