python 决策树的实现

1.决策树的简介

http://www.cnblogs.com/lufangtao/archive/2013/05/30/3103588.html

2.决策是实现的伪代码
“读入训练数据”
“找出每个属性的可能取值”

“递归调用建立决策树的函数”
“para:节点,剩余样例,剩余属性”

if “剩余属性个数为0"
    return most_of_result
else if “剩余样例都属于同一个分类(yes/no)"    
    return yes/no
else:
       ”对于每一个剩余属性,计算该属性的熵增“,并找到熵增最大的对应的属性,即为最佳分类属性”
    “按照最佳分类属性分类,对于每个分支,递归调用建立函数,最终得到整个决策树”

3.python数据结构设计

1.数据集:用于存储二维的训练数据training_data

二维的list数组,对于二维的list要取得某一列的数据,可以用zip(*dataset)[num]

2.属性集合:用于存储属性的名称attri_name_set

一维的list

3.属性的可能取值:存储各个属性的可能取值状态

dict+set:dict的key是属性的名称,value是set类型,这样可以保证不会有重复
    新建set类型:attri[i] = set()

4.树的节点定义

class Dtree_node(object):
   def init(self):
   self.attriname = None
  self.sub_node = {} #子节点为dict类型
  子节点的类型为dict,key是属性的不同取值,value是对应的子节点
4.code

-- coding: utf-8 --

from future import division
import math

author = ‘Jiayin’
#date:2016-3-28
#决策树的实现,从test.txt中读入训练数据,

#全局变量
training_data = [] #数据集(二维list表)
attri = {} #属性集(dict+set)
attri_name_set = []

class Dtree_node(object):
def init(self):
self.attriname = None
self.sub_node = {} #子节点为dict类型

root = Dtree_node()

#输入数据
def get_input():
#属性集合 属性是dict结构,key为属性名(str),value是该属性可以取到的值类型为set
#第一个属性通常为编号,最后一个属性通常为决策结果,取值只有yes/no
global attri
global attri_name_set
file_read = open(“test.txt”)
line = file_read.readline().split()
attri_name_set = line[:]
#print line
for i in line:
attri[i] = set()

line = file_read.readline().split()
#读入数据,并计算每个属性的可能取值
while line:
        training_data.append(line)
        for i in range(1,len(line)-1):
            attri[attri_name_set[i]].add(line[i])
        line = file_read.readline().split()

#取most_of _result
def getmost(dataset_result):
p = 0
n = 0
for i in dataset_result:
if i == ‘yes’:
p+=1
else:
n+=1
return ‘yes’ if p>n else ‘no’

#计算熵
def cal_entropy(dataset_result):
num_yes = 0
num_no = 0
for i in dataset_result:
if i == ‘yes’:
num_yes +=1
else:
num_no += 1
if num_no == 0 or num_yes == 0:
return 0
total_num = num_no +num_yes
per_yes = num_yes/total_num
per_no = num_no/total_num
return -per_yesmath.log(per_yes,2)-per_nomath.log(per_no,2)

#计算某个属性的熵增
#参数 :数据集和属性名,初始熵
def cal_incr_entr_attri(data_set,attriname,init_entropy):
global attri
global attri_name_set
incr_entr = init_entropy
attri_index = attri_name_set.index(attriname)

#将该属性的不同取值提取出来,并分别计算熵,求出熵增
for i in attri[attriname]:
    #new_data = data_set[:]
    new_data = filter(lambda  x: True if x[attri_index] == i else False ,data_set)
    if len(new_data)==0:
        continue
    num = cal_entropy(zip(*new_data)[-1])
    incr_entr -= len(new_data)/len(data_set)*num

return incr_entr

#判断是否剩余数据集都是一个结果
def if_all_label(dataset_result, result):
#result = dataset_result[0]
for i in range(0,len(dataset_result)):
if dataset_result[i] <> result:
break
return False if dataset_result[i]<>result else True

#建立决策树
#参数:root:节点 dataset:剩下的数据集 attriset:剩下的属性集
def create_Dtree(root_node , data_set , attri_set):
global attri
global attri_name_set
‘’’
#如果当前数据集为空,应该返回上一层的most_of_result,此处要修改
if len(data_set)==0:
return None’’’
#考虑如果剩余属性集为空,则返回most_of_result
if len(attri_set) == 0:
print zip(*data_set)
root_node.attriname = getmost(zip(*data_set)[-1]) #zip(*dataset)[-1]表示取出最后一列,也就是yes/no那一列
return None
#考虑如果剩余的数据集都是一个结果的话,返回这个结果
elif if_all_label(zip(*data_set)[-1],‘yes’):
root_node.attriname = ‘yes’
return None
elif if_all_label(zip(*data_set)[-1],‘no’):
root_node.attriname = ‘no’
return None

#print zip(*data_set)
init_entropy = cal_entropy(zip(*data_set)[-1])#计算初始熵
max_entropy  = 0
for i in attri_set:
    entropy = cal_incr_entr_attri(data_set,i,init_entropy)
    if entropy > max_entropy:
        max_entropy = entropy
        best_attri = i

new_attri = attri_set[:]
root_node.attriname = best_attri
attri_index = attri_name_set.index(best_attri)
for attri_value in attri[best_attri]:
    #new_data = data_set[:]
    new_data = filter(lambda  x: True if x[attri_index] == attri_value else False ,data_set)
    root_node.sub_node[attri_value] = Dtree_node()
    #如果该分支下面的数据集个数为0,则采用父节点的most_of_result
    if len(new_data)==0:
        root_node.sub_node[attri_value].attriname = getmost(zip(*data_set)[-1])
    else:
        create_Dtree(root_node.sub_node[attri_value],new_data,new_attri)

def print_Dtree(Root_node,layer):
print Root_node.attriname
count = 1
if len(Root_node.sub_node) > 0:
for sub in Root_node.sub_node.keys():
for i in range(layer):
print "| ",
print “|----%10s—”%sub,
assert isinstance(layer, object)
print_Dtree(Root_node.sub_node[sub] , layer+1)
#count += 1

def main():
global root
global attri_name_set
get_input()#输入
attri_set = attri_name_set[1:-1]#提取出要分类的属性
create_Dtree(root,training_data,attri_set)#创建决策树
print_Dtree(root,0)#打印决策树

main()

猜你喜欢

转载自blog.csdn.net/qq_41235445/article/details/87901077