起步
在理论篇我们介绍了决策树的构建和一些关于熵的计算方法,这篇文章将根据一个例子,用代码上来实现决策树。
实验环境
- 操作系统: win10 64
- 编程语言: Python3.6
用到的第三方模块有:
numpy (1.12.1+mkl)
scikit-learn (0.19.1)
数据源
为了方便理解和架设,我们用理论篇中买电脑的例子:
将这些记录保存成 csv
文件:
RID,age,income,student,credit_rating,class:buys_computer
1,youth,hight,no,fair,no
2,youth,hight,no,excellent,no
3,middle_aged,hight,no,fair,yes
4,senior,medium,no,fair,yes
5,senior,low,yes,fair,yes
6,senior,low,yes,excellent,no
7,middle_aged,low,yes,excellent,yes
8,youth,medium,no,fair,no
9,youth,low,yes,fair,yes
10,senior,medium,yes,fair,yes
11,youth,medium,yes,excellent,yes
12,middle_aged,medium,no,excellent,yes
13,middle_aged,hight,yes,fair,yes
14,senior,medium,no,excellent,no
这些数据就是这次应用的数据源。
数据整理
可以利用python标准库中 csv
来对这个数据源进行读取,要对原始数据集进行整理,随机变量放在一个数组,分类结果放在另一个数组,形如:
future_list = [
{
"age" : "youth",
"income": "hight",
...
}
...
]
answer_list = ["no", "no", "yes", ...]
按照这个思路我们构造一下:
data_file = open("computer_buy.csv", "r")
reader = csv.reader(data_file)
headers = next(reader)
future_list = []
label_list = []
for row in reader:
label_list.append(row[-1])
row_dict = {}
for i in range(1, len(row) -1):
row_dict[ headers[i] ] = row[i]
future_list.append(row_dict)
data_file.close()
随机变量向量化
在 sklearn
提供的库中,对输入的特征有一定的要求,所有特征和分类都要是数值型的值,不能是例子中的类别的值。
怎么转化呢?
比方说 age
这个特征,它有三个值: youth
, middle_aged
, senior
。有一条记录的 age=youth
针对这个特征我们就变成:
youth | middle_aged | senior |
---|---|---|
1 | 0 | 0 |
那么第一条记录 youth,hight,no,fair
转化为:
age=middle_aged | age=senior | age=youth | credit_rating=excellent | credit_rating=fair | income=hight | income=low | income=medium | student=no | student=yes |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 |
特征向量化
from sklearn.feature_extraction import DictVectorizer
dummy_x = vec.fit_transform(future_list).toarray()
print("dummy_x:", dummy_x)
print("vec.get_feature_names()", vec.get_feature_names())
分类结果向量化
from sklearn import preprocessing
lb = preprocessing.LabelBinarizer()
dummy_y = lb.fit_transform(label_list)
构造决策树
在 sklearn
中提供了多种决策树构建方法,这边需要向其表明,是依据 信息增益
的方式来构造决策树的,因此需要传入一个参数criterion='entropy'
:
from sklearn import tree
# 构造决策树
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf.fit(dummy_x, dummy_y)
print("clf: ", clf)
保存模型
将训练好的模型保存到文件里去:
# 保存模型
with open("result.dot", "w") as f:
tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)
测试数据
接下来就是给它随机变量,让决策树来进行分类。我们修改第一条记录来进行测试:
# 测试数据
first_row = dummy_x[0, :]
new_row = list(first_row)
new_row[0] = 1
new_row[2] = 0
predict = clf.predict([new_row])
print("predict:", predict) # output: [1]
模型可视化
可视化用到了 Graphviz
软件,可以到官网:http://www.graphviz.org/ 下载,我下载的是 zip 文件,解压后将目录加到环境变量中去。
转化 dot
文件至 pdf
可视化决策树的命令:
dot -Tpdf result.dot -o outpu.pdf
得到一个pdf文件,打开可以看到决策树:
附录
本次应用的全部代码:
# coding: utf-8
import csv
from sklearn.feature_extraction import DictVectorizer
from sklearn import preprocessing
from sklearn import tree
data_file = open("computer_buy.csv", "r")
reader = csv.reader(data_file)
headers = next(reader)
future_list = []
label_list = []
for row in reader:
label_list.append(row[-1])
row_dict = {}
for i in range(1, len(row) -1):
row_dict[ headers[i] ] = row[i]
future_list.append(row_dict)
data_file.close()
# 向量化 x
vec = DictVectorizer()
dummy_x = vec.fit_transform(future_list).toarray()
print("dummy_x:", dummy_x)
print("vec.get_feature_names()", vec.get_feature_names())
# 向量化 y
lb = preprocessing.LabelBinarizer()
dummy_y = lb.fit_transform(label_list)
# 构造决策树
clf = tree.DecisionTreeClassifier(criterion='entropy')
clf.fit(dummy_x, dummy_y)
print("clf: ", clf)
# 保存模型
with open("result.dot", "w") as f:
tree.export_graphviz(clf, feature_names=vec.get_feature_names(), out_file=f)
# 测试数据
first_row = dummy_x[0, :]
new_row = list(first_row)
new_row[0] = 1
new_row[2] = 0
predict = clf.predict([new_row])
print("predict:", predict)