分类算法之决策树(应用篇)

Python,机器学习 2017-12-05

起步

在理论篇我们介绍了决策树的构建和一些关于熵的计算方法,这篇文章将根据一个例子,用代码上来实现决策树。

实验环境

  • 操作系统: win10 64
  • 编程语言: Python3.6

用到的第三方模块有:

numpy (1.12.1+mkl)
scikit-learn (0.19.1)

数据源

为了方便理解和架设,我们用理论篇中买电脑的例子:

Image.png

将这些记录保存成 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文件,打开可以看到决策树:

20171205153457.png

附录

本次应用的全部代码:

# 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)

本文由 hongweipeng 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

赏个馒头吧