我尝试使用python和sklearn启动决策树。 工作方法是这样的:
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)
现在我尝试使用DictVectorizer做同样的事情,但我的代码不起作用:
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)
我在最后一行遇到错误:“ValueError:标签数= 332448与样本数= 55匹配”。正如我从文档中学到的,DictVectorize旨在将名义特征转换为数字特征。我做错了什么?
更正了(感谢ogrisel推动我做一个完整的例子):
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'])
最后一段代码是在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
一切正常
答案 0 :(得分:14)
您枚举样本的方式没有意义。只需将它们打印出来即可:
>>> 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'}]
现在这在语法上是一个词典列表,但没有你期望的那样。试着这样做:
>>> 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'}]
这看起来好多了,让我们现在尝试对这些词汇进行矢量化:
>>> 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.]])
要获得每列的含义,请询问矢量化器:
>>> vectorizer.get_feature_names()
['a=a', 'a=b', 'b', 'c=b', 'c=c', 'd=e', 'd=f']
答案 1 :(得分:1)
vec.fit_transform
返回一个稀疏数组。而且IIRC DecisionTreeClassifier
并不能很好地发挥作用。
在将train_fea = train_fea.toarray()
传递给DecisionTreeClassifier
之前尝试{{1}}。