决策树是一种基本的分类与回归方法。这两天根据李航的《统计学习方法》里讲的决策树算法,
用python手撸了一遍决策树代码,写此博客作为记录。
DataSet.py:用于读数据集
import numpy
import re
def readData(filename, reg="\\s+"):
if(filename.strip() == ''):
print("文件名不能为空!")
return
file = open(filename)
arraylines = file.readlines()
alllist = []
for line in arraylines:
line = line.strip()
listfromline = re.split(reg,line)
print(listfromline)
alllist.append(listfromline)
returnmat = numpy.array(alllist)
return returnmat
DecisionTree.py
import numpy
import DataSet
#计算集合D的经验熵H(D)
def EE(D):
#D为矩阵,D中最后一列为类别,其余每列为一种特征
C = dict.fromkeys(D[:,-1],0)
for i in range(len(D)):
C[D[i][-1]] = C[D[i][-1]]+1
H = 0
lenD = len(D)
for key in C:
t = -(C[key]/lenD)*numpy.log2(C[key]/lenD)
H += t
return H
#计算第A个特征对数据集D的经验条件熵,A(从0开始)为第几个特征
def ECE(D,Ai):
H_DA = 0
#得到第A个特征的分类
dictA = dict.fromkeys(D[:, Ai], [])
Di = numpy.array([])
#将D中按照第A个特征分类
lenD = len(D)
for key in dictA:
dictA[key] = list(numpy.where(D[:, Ai] == key)[0])
Di = D[dictA[key]]
H_DA += (len(dictA[key])/lenD)*EE(Di)
return H_DA
#计算信息增益
def IG(D,Ai):
G_DA = EE(D) - ECE(D,Ai)
return G_DA
#得到最大信息增益
def getMostIG(D,A):
GDAlist = []
for Ai in range(len(A)):
G_DA = IG(D, Ai)
GDAlist.append([A[Ai],G_DA])
best = sorted(GDAlist, key=lambda GDAlist: GDAlist[-1], reverse=True)
return best[0][0],best[0][1]
def isSameType(D):
for i in range(len(D)-1):
if D[i,-1] != D[i+1,-1]:
return False
return True
def getMostLabel(D):
dictlabel = dict.fromkeys(D[:,-1],0)
for i in range(len(D)):
dictlabel[D[i,-1]] = dictlabel[D[i,-1]]+1
mostlabel = sorted(dictlabel.items(), key=lambda dictlabel: dictlabel[1], reverse=True)
return mostlabel[0][0] #返回标签
def createTree(D,A,delta):
#判断D中所有实例是否属于同一类Ck,若是就返回Ck作为该节点的类标记:
if isSameType(D):
return D[0,-1]
#如果A为空,那么返回D中实例数最多的类作为该节点的类标记
if len(A)==0:
mostlabel = getMostLabel(D)
return mostlabel
#找到A中特征使得该特征对D有最大信息增益
bestlabel,bestIG = getMostIG(D,A)
if bestIG < delta:
mostlabel = getMostLabel(D)
return mostlabel
#对bestlabel中每一个可能值,分割D,得到Di,使得Di重复以上步骤,同时将A-bestlabel作为新A输入
index = A.index(bestlabel)
del A[index]
dictA = dict.fromkeys(D[:, index], [])
myTree = {bestlabel:{}}
for key in dictA:
dictA[key] = list(numpy.where(D[:, index] == key)[0])
Di = D[dictA[key]]
Di = numpy.delete(Di,index,axis=1)
myTree[bestlabel][key] = createTree(Di,A,delta)
return myTree
#D为数据集矩阵,A为特征list,delta为阈值
def ID3(D,A,delta):
dicisiontree = createTree(D,A,delta)
return dicisiontree
D = DataSet.readData("d://dataset.txt")
A = ['年龄','有工作','有自己的房子','信贷情况']
delta = 0.01
dicisiontree = ID3(D,A,delta)
print(dicisiontree)
dataset.txt:数据集:
青年 否 否 一般 否
青年 否 否 好 否
青年 是 否 好 是
青年 是 是 一般 是
青年 否 否 一般 否
中年 否 否 一般 否
中年 否 否 好 否
中年 是 是 好 是
中年 否 是 非常好 是
中年 否 是 非常好 是
老年 否 是 非常好 是
老年 否 是 好 是
老年 是 否 好 是
老年 是 否 非常好 是
老年 否 否 一般 否
运行结果:
{'有自己的房子': {'否': {'有工作': {'否': '否', '是': '是'}}, '是': '是'}}