使用sklearn构建含有标量属性的决策树

网络上使用sklearn生成决策树的资料很多,这里主要说明遇见标量数据的处理。

经查验参考资料,sklearn并非使用了课上以及书上讲的ID3算法,而是选择了CART,该算法生成二叉树;scikit-learn使用了一种优化的CART算法,要求元数据为数值型(要能转换为np.float32类型的矩阵),因为该实现同时可以做回归分析。然而,题目数据中有天气等标量数据,所以还要进行转化,这里采用了sklearn中的LabelEncoder来将n个标量转化为1至n-1的整数。将数据训练完毕后,安装并使用了Graphviz(一个图形显示库)和pydotplus(方便使用Graphviz的Python编程接口)来进行结果图形化显示;查阅资料说的配置好像比较复杂,其实下载下来Graphviz后解压缩,并把bin文件夹加入环境变量就可以用pydotplus来访问了。使用信息熵作为度量,结果如图所示,其中value表示目标两类各包含多少实例。

结果:

为展示训练结果如何,将原数据再次使用score函数输入,发现正确率100%。应该是由于没有限制树的深度结果比较精确,并且发现“湿度”这个属性根本没有使用!但是一旦数据比较多,就需要限制树的深度了和每个叶子的实例个数了,由max_depth、min_samples_split、min_samples_leaf来设置。

最后还有一些疑问,就是把标量当做数值属性来处理,会影响最后分类的结果吗?需要拿数据说话还是有一些已经存在的结论。。。?

 1 # -*- coding: utf-8 -*-
 2 """
 3 Created on Tue Nov 22 17:45:37 2016
 4 
 5 @author: Ascii0x03
 6 """
 7 
 8 from sklearn import tree
 9 from sklearn import preprocessing
10 import pydotplus
11 from IPython.display import Image
12 
13 #将数据集data中的字符串属性全部转化为对应的标签
14 #data为矩阵,同tree.DecisionTreeClassifier.fit方法中的数据
15 #返回值le_list是preprocessing.LabelEncoder()对象的列表
16 #str_index是属性中字符串类型的下标
17 def preprocess(data):
18     str_index = []
19     #temp_label = []
20     le_list = []
21     le_num = 0
22     for i in range(0,len(data[1])):
23         if (isinstance(data[1][i], str)):
24             str_index.append(i)
25     #整理出labelEncoder
26     for index in str_index:
27         temp_label = []
28         for i in data:
29             temp_label.append(i[index])
30         le_list.append(preprocessing.LabelEncoder())
31         le_list[le_num].fit(temp_label)
32         #根据labelEncoder修改原始数据
33         #print temp_label
34         for i in data:
35             i[index] = le_list[le_num].transform([(i[index])])[0]
36         
37         le_num += 1
38        
39     return (le_list, str_index)
40     
41     
42     
43 clf = tree.DecisionTreeClassifier(criterion = "entropy")
44 #每行是一个数据,分别为天气,温度,湿度风况
45 data = [["Sunny", 85, 85, "No"], 
46         ["Sunny", 80, 90, "Yes"],
47         ["Cloudy", 83, 78, "No"], 
48         ["Rainy", 70, 96, "No"], 
49         ["Rainy", 68, 80, "No"],
50         ["Rainy", 65, 70, "Yes"],
51         ["Cloudy", 64, 65, "Yes"],
52         ["Sunny", 72, 95, "No"],
53         ["Sunny", 69, 70, "No"],
54         ["Rainy", 75, 80, "No"],
55         ["Sunny", 75, 70, "Yes"],
56         ["Cloudy", 72, 90, "Yes"],
57         ["Cloudy", 81, 75, "No"],
58         ["Rainy", 71, 80, "Yes"]
59         ]
60 #针对每行数据,分类为适合运动与不适合运动
61 labels = ["unfit", "unfit", "fit", "fit", "fit",
62           "unfit", "fit", "unfit", "fit", "fit",
63           "fit", "fit", "fit","unfit"]
64 (le_list, str_index) = preprocess(data)
65 #print data
66 clf.fit(data, labels)
67 
68 print clf.feature_importances_
69 dot_data = tree.export_graphviz(clf, out_file=None) 
70 graph = pydotplus.graph_from_dot_data(dot_data)
71 Image(graph.create_png()) #这里貌似不能正确显示
72 graph.write_pdf("test1.pdf")
73 graph.write_png("test1.png") 
74 #print dot_data
75 
76 test = [["Rainy", 71, 80, "Yes"]]
77 #Preprocessing the test data
78 for index in range(0, len(str_index)):
79     for i in test:
80         i[str_index[index]] = le_list[index].transform([i[str_index[index]]])[0]
81 #print test
82 print clf.predict(test)
83 print clf.predict_proba(test)
84 print clf.score(data, labels)
View Code

 

参考:

0. ID3算法实现决策树可http://blog.csdn.net/u012822866/article/details/42419471

1. http://scikit-learn.org/stable/modules/tree.html#tree-classification

2. http://scikit-learn.org/dev/modules/generated/sklearn.preprocessing.LabelEncoder.html

3. http://pydotplus.readthedocs.io/

4. http://www.graphviz.org/

posted @ 2016-11-23 21:47  ASCII0x03  阅读(1032)  评论(0编辑  收藏  举报