在 Python-Scikit Learn 中对决策树表进行矢量化后取回原始特征名称?

Posted

技术标签:

【中文标题】在 Python-Scikit Learn 中对决策树表进行矢量化后取回原始特征名称?【英文标题】:Get back the original feature names after vectorization for decision tree table in Python-Scikit Learn? 【发布时间】:2016-03-15 14:33:41 【问题描述】:

我正在使用一些名称和其他特征来预测 y(二进制类)。名称特征是名称的子字符串。我正在使用 Python Scikit-learn。

这是 X 的一小部分:

['substring=ry': True, 'substring=lo': True, 'substring=oui': True, 'firstLetter-firstName': u'm', 'substring=mar': True, 'avg-length': 5.0, 'substring=bl': True, 'lastLetter-lastName': u'n', 'substring=mary': True, 'substring=lou': True, 'metaphone=MR': True, 'location': u'richmond & wolfe, quebec, canada', 'substring=ma': True, 'substring=ui': True, 'substring=in': True, 'substring=ary': True, 'substring=loui': True, 'firstLetter-lastName': u'b', 'lastLetter-firstName': u'y', 'first-name': u'mary', 'substring=ou': True, 'last-name': u'blouin', 'substring=blo': True, 'substring=uin': True, 'metaphone=PLN': True, 'substring=ar': True, 'name-entity': 2, 'substring=blou': True, 'substring=ouin': True]

然后我用 dictvectorization 将 X 向量化成这个...

  (0, 0)    5.0
  (0, 6798) 1.0
  (0, 9944) 1.0
  (0, 9961) 1.0
  (0, 11454)    1.0
  (0, 28287)    1.0
  (0, 28307)    1.0
  (0, 28483)    1.0
  (0, 33376)    1.0
  (0, 34053)    1.0
  (0, 36901)    2.0
  (0, 39167)    1.0
  (0, 39452)    1.0
  (0, 40797)    1.0
  (0, 40843)    1.0
  (0, 40853)    1.0
  (0, 51489)    1.0
  (0, 54903)    1.0
  (0, 55050)    1.0
  (0, 55058)    1.0
  (0, 55680)    1.0
  (0, 55835)    1.0
  (0, 55856)    1.0
  (0, 60698)    1.0
  (0, 60752)    1.0
  (0, 60759)    1.0
  (0, 64391)    1.0
  (0, 68278)    1.0
  (0, 68318)    1.0

问题是我完全不知道新 X 代表什么。由于我需要制作决策树图,因此我只能得到这些我无法解释的结果。

digraph Tree 
0 [label="X[0] <= 4.5000\ngini = 0.5\nsamples = 25000", shape="box"] ;
1 [label="X[39167] <= 0.5000\ngini = 0.0734231704267\nsamples = 891", shape="box"] ;
0 -> 1 ;
2 [label="X[36901] <= 2.5000\ngini = 0.0575468244736\nsamples = 702", shape="box"] ;
1 -> 2 ;
3 [label="X[58147] <= 0.5000\ngini = 0.0359355212331\nsamples = 442", shape="box"] ;
2 -> 3 ;
4 [label="X[9977] <= 0.5000\ngini = 0.0316694756485\nsamples = 396", shape="box"] ;
3 -> 4 ;
5 [label="X[29713] <= 0.5000\ngini = 0.0275525222406\nsamples = 352", shape="box"] ;
4 -> 5 ;
6 [label="X[9788] <= 0.5000\ngini = 0.0244412457957\nsamples = 319", shape="box"] ;
5 -> 6 ;
7 [label="X[46929] <= 0.5000\ngini = 0.0226406785428\nsamples = 300", shape="box"] ;
6 -> 7 ;
8 [label="X[45465] <= 0.5000\ngini = 0.0209286264458\nsamples = 282", shape="box"] ;
7 -> 8 ;
9 [label="X[45718] <= 0.5000\ngini = 0.0194016759597\nsamples = 266", shape="box"] ;
8 -> 9 ;
10 [label="X[28311] <= 0.5000\ngini = 0.0178698827564\nsamples = 250", shape="box"] ;
9 -> 10 ;...

我的python代码:

from sklearn.feature_extraction import DictVectorizer
from sklearn import tree
classifierUsed2 = tree.DecisionTreeClassifier(class_weight="auto")
dv = DictVectorizer()

newX = dv.fit_transform(all_dict)
X_train, X_test, y_train, y_test = cross_validation.train_test_split(newX, y, test_size=testTrainSplit)
classifierUsed2.fit(X_train, y_train)
y_train_predictions = classifierUsed2.predict(X_train)
y_test_predictions = classifierUsed2.predict(X_test)
tree.export_graphviz(classifierUsed2, out_file='graph.dot')     

【问题讨论】:

你检查过 DictVectorizer 的 get_feature_names() 方法吗? 谢谢。我不知道它存在。我正在查看他们的文档,但我不知道如何将其合并到我的代码中。我是否使用分配了 get_feature_names() 的对象重新分配 newX?我是否按照 X 功能的现有时间顺序执行此操作? 【参考方案1】:

所以要合并特征名称的附加信息,我们首先需要看一下newX是什么。根据文档(以及您在示例中显示的打印输出),newX 是一个稀疏矩阵,具有 n 行和 d 列,其中 n 是样本数,d 是唯一特征数。每一列都用一个整数标识,该整数映射回在原始数据中找到的特征名称。所以我们知道我们想在原始数据中找到从索引到特征的映射,这可以使用get_feature_names() 来帮助。

查看graphviz 的文档后,我发现有一个设置功能名称的选项,简称为功能名称。所以我们需要做的就是在将图形写入文件时包含该参数。我会用一个例子来说明这一点:

from sklearn.feature_extraction import DictVectorizer
from sklearn import tree
from sklearn import cross_validation
classifierUsed2 = tree.DecisionTreeClassifier(class_weight="auto")
dv = DictVectorizer()

在这里,我们只是像您在示例中所做的那样定义所有内容(我必须添加一个导入语句)

all_dict = [ 'dog':1, 'cat':1, 'mouse':0, 'elephant':1, 'tiger':1,
         'dog':0, 'cat':1, 'mouse':0, 'elephant':0, 'tiger':0,
         'dog':0, 'cat':1, 'mouse':1, 'elephant':1, 'tiger':0,
         'dog':0, 'cat':1, 'mouse':1, 'elephant':1, 'tiger':1,
         'dog':0, 'cat':0, 'mouse':1, 'elephant':1, 'tiger':0,
         'dog':1, 'cat':1, 'mouse':0, 'elephant':0, 'tiger':1]
y = [1,0,0,0,1,1]
testTrainSplit=2

这里是一些示例数据和变量初始化

newX = dv.fit_transform(all_dict)
X_train, X_test, y_train, y_test = cross_validation.train_test_split(newX, y, test_size=testTrainSplit)
classifierUsed2.fit(X_train, y_train)
y_train_predictions = classifierUsed2.predict(X_train)
y_test_predictions = classifierUsed2.predict(X_test)
tree.export_graphviz(classifierUsed2, feature_names=dv.get_feature_names(), out_file='graph.dot')

而关键步骤是新参数feature_names=dv.get_feature_names()。不要害怕查看这些库的文档以及您想在其中调用的任何函数,因为它们可能是非常宝贵的资源!

【讨论】:

感谢您的精彩回答,不仅您给出了正确的答案,您还花时间充分解释了您的方法和推理!赞赏。

以上是关于在 Python-Scikit Learn 中对决策树表进行矢量化后取回原始特征名称?的主要内容,如果未能解决你的问题,请参考以下文章

scikit-learn决策树算法类库使用小结

[机器学习与scikit-learn-15]:算法-决策树-分类问题代码详解

决策树算法

nyoj 对决

大天使之剑h5巅峰对决怎么玩

F5应用交付容器解决方案如何?看这场巅峰对决