Python 将听写向量器与sklearn DecisionTreeClassifier一起使用

Python 将听写向量器与sklearn DecisionTreeClassifier一起使用,python,machine-learning,scikit-learn,Python,Machine Learning,Scikit Learn,我尝试用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 enumera

我尝试用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:Number of labels=332448与Number of samples=55不匹配”。正如我从文档中了解到的,DictVectorize旨在将名义特征转换为数字特征。我做错了什么

更正(感谢ogrisel给我举了一个完整的例子):

最后一个代码是在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

一切正常

vec.fit\u transform
返回一个稀疏数组。IIRC
DecisionTreeClassifier
不能很好地处理这个问题


在将其传递给
DecisionTreeClassifier
之前,请尝试
train\u fea=train\u fea.toarray()。只需将它们打印出来,使其清晰可见:

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

目前还不清楚样品的结构。您的培训集中有多少个样本?你能在你的描述中打印这样一个示例吗?修复-我添加了示例代码谢谢我现在回答。train是一个数据帧,train_fea是一个numpy.ndarray,所以如果我写dt.fit(train_fea.toarray(),labels)会给我一个错误“AttributeError:'numpy.ndarray'对象没有属性'toarray'”如果您打印train_fea,第一段代码有3行,第二段代码有4行,如果我不使用vec=DictVectorizer(sparse=False),您是对的。在“sparse=False”的情况下,不需要添加.toarray().ogrisel,非常感谢,它可以工作。但现在我无法收回我的标签:)。在问题中添加了工作代码。您能将答案标记为已接受吗?它有助于跟踪用户尚未回答的问题。至于标签,只需将其直接传递给
DecisionTreeClassifier
,而无需使用
DictVectorier
:默认情况下标签应是分类的。奥利弗,谢谢你的回答!如果我不使用DictVectorizer,我会得到一个错误“ValueError:无法将字符串转换为float:b”好的对不起,对于标签,一些分类器直接接受字符串,其他分类器仍然需要手动传递。将来,sklearn中的所有分类器都应该在内部使用LabelEncoder。
>>> 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']