python决策树生成规则_ID3决策树(python实现)

决策树的生成(该函数是一个递归的过程)CreateTree

输入:数据集、特征

输出:字典型数据——决策树

a、判断是否满足停止划分的条件

若当前数据集的属性值为空,则投票表决当前样本中最多的类别

若当前所有的样本类别相同,则返回当前数据的类别。

b、寻找当前数据的最佳划分特征

c、将最佳特征作为关键字,保存到字典中

d、从当前的属性集合中删除该最佳特征

e、遍历该最佳划分特征的所有属性值feat,循环调用函数 CreateTree(输入参数为:最佳特征值为feat的所有数据集,去除最佳特征的属性集合)

代码注意:

1、生成的决策树用字典保存,并且每个关键字的值是一个字典;

2、生成的决策树可以用 pickle 序列化对象保存;

3、ID3 算法适用于标称型数据,在函数的输入、输出中,数据类型为 listlist。

代码:

#-*- coding:utf-8 -*-

import numpy as np

from numpy import *

import pandas as pd

from math import *

import operator

import pickle # 使用该模块实现对决策树的保存

# 数据导入

def loadData(fileName):

dataSet = []

fr = open(fileName)

for featVector in fr.readlines():

lineVector = featVector.strip().split('\t')

dataSet.append(lineVector)

return dataSet

def calcuEntropy(myData): # 计算信息熵

numSample = len(myData)

myClassCount = {}

for featVector in myData:

theKey = featVector[-1]

if theKey not in myClassCount:

myClassCount[theKey] = 0

myClassCount[theKey] += 1

myEntropy = 0

for Keys in myClassCount.keys():

Px = float(myClassCount[Keys])/numSample

myEntropy -= Px*log(Px,2) # 需要导入 math 库

return myEntropy

# 划分数据集:返回划分好的数据集

def splitDataSet(dataX,FeatureNumber,value): # 输入:数据集、第i 个特征、该属性的值

retMat = []

for featVect in dataX:

if featVect[FeatureNumber] == value:

x1 = featVect[:FeatureNumber]

x2 = featVect[FeatureNumber+1:]

x1.extend(x2)

retMat.append(x1)

#print"retMat", retMat

return retMat

# 计算最优特征:计算每个特征下的信息熵,信息熵最大的既是最优特征,返回的数字 i 代表第 i 个特征

def GetBestFeature(dataM):

BestFeat = -1; LargestInformGain = -1 # 最佳特征、最大信息增益

theEntropy = calcuEntropy(dataM)

FeatNumber = len(dataM[0])-1

for i in range(FeatNumber):

FeatList = [example[i] for example in dataM] # 统计每个特征有几个特征值

FeatUnique = set(FeatList) # 每个特征中的特征值,计算每个特征值下的信息增益

NewEntropy = 0.0

for j in FeatUnique:

retMat = splitDataSet(dataM,i,j) # 得到满足条件的数据

Prob = len(retMat)/float(len(dataM))

NewEntropy -= Prob*calcuEntropy(retMat) # 注意:这里是子数据集的概率x 该数据集的熵

informGain = theEntropy + NewEntropy

if informGain > LargestInformGain:

LargestInformGain = informGain

BestFeat = i

return BestFeat

def RoleOfVote(dataM): # 投票规则:少数服从多数

lables = [example[-1] for example in dataM]

lablesCount = {}

for i in lables:

if i not in lablesCount.keys():

lablesCount[i] = 0

lablesCount[i] += 1

theSort = sorted(lablesCount.iteritems(),key =operator.itemgetter(1),reverse=True)

return theSort[0][0] # 返回出现次数最多的类别标签

# 决策树生成: 首先,判断是否满足停止划分的条件:1、所有的类别标签相同 2、属性值为空

def CreateTree(dataSet,label):

allLabels = [example[-1] for example in dataSet]

#print "调用几次"

if allLabels.count(allLabels[0])==len(allLabels):

return allLabels[0]

if(len(dataSet[0])==1): # 没有属性可以划分时,采用投票规则

return RoleOfVote(dataSet)

featNumber = GetBestFeature(dataSet) # 返回最佳划分的编号

#print featNumber

bestFeature = label[featNumber]

myTree = {bestFeature:{}}

del(label[featNumber])

featValue = [example[featNumber] for example in dataSet]

uniqueFeatValues = set(featValue)

for i in uniqueFeatValues:

subLabels = label[:]

myTree[bestFeature][i] = CreateTree(splitDataSet(dataSet, featNumber, i), subLabels)

return myTree

# 对输入样本进行分类

def SampleClassify(inputTree, featLabels, testVec): # 输入树、属性标签、测试向量

firstStr = inputTree.keys()[0] # 决策树的第一个关键词(第一个划分的属性)

secondDict = inputTree[firstStr] # 决策树每个关键字对应的值也是字典

featIndex = featLabels.index(firstStr) # 得到该特征在属性标签中的编号 K

key = testVec[featIndex] # 得到当前测试向量中第 K 号特征值

valueOfFeat = secondDict[key]

if isinstance(valueOfFeat, dict): # 判断变量是否为字典类型

classLabel = SampleClassify(valueOfFeat, featLabels, testVec)

else:

classLabel = valueOfFeat

return classLabel

# 将生成的树保存

def storeTree(inputTree, filename):

fw = open(filename, 'w')

pickle.dump(inputTree, fw)

fw.close()

# 加载保存的树

def loadTree(filename):

fr = open(filename)

return pickle.load(fr)

if __name__=="__main__":

print "hello world"

dataSet = loadData('lenses.txt')

labels = ['age','prescript','astigmatic','tearRate']

slabels = labels[:] # pyhton 函数中的参数是按照引用方式传递的,为防止labels 改变,复制类标签带入

myTree = CreateTree(dataSet,slabels)

print labels

#storeTree(myTree,"xu") # 保存决策树

test = dataSet[0]

#print test[:-1]

print"预测结果是:", SampleClassify(myTree,labels,test[:-1])

print"真是标签是:",test[-1]

注:

ID3决策树在选择属性时,会找到信息增益最大的划分属性

ID3决策树如果对连续变化的属性进行划分,则需要先将连续值离散化(分区间)

你可能感兴趣的:(python决策树生成规则)